plugin.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. /**
  2. * TinyMCE version 6.4.2 (2023-04-26)
  3. */
  4. (function () {
  5. 'use strict';
  6. const Cell = initial => {
  7. let value = initial;
  8. const get = () => {
  9. return value;
  10. };
  11. const set = v => {
  12. value = v;
  13. };
  14. return {
  15. get,
  16. set
  17. };
  18. };
  19. var global$3 = tinymce.util.Tools.resolve('tinymce.PluginManager');
  20. let unique = 0;
  21. const generate = prefix => {
  22. const date = new Date();
  23. const time = date.getTime();
  24. const random = Math.floor(Math.random() * 1000000000);
  25. unique++;
  26. return prefix + '_' + random + unique + String(time);
  27. };
  28. const get$1 = customTabs => {
  29. const addTab = spec => {
  30. var _a;
  31. const name = (_a = spec.name) !== null && _a !== void 0 ? _a : generate('tab-name');
  32. const currentCustomTabs = customTabs.get();
  33. currentCustomTabs[name] = spec;
  34. customTabs.set(currentCustomTabs);
  35. };
  36. return { addTab };
  37. };
  38. const register$2 = (editor, dialogOpener) => {
  39. editor.addCommand('mceHelp', dialogOpener);
  40. };
  41. const option = name => editor => editor.options.get(name);
  42. const register$1 = editor => {
  43. const registerOption = editor.options.register;
  44. registerOption('help_tabs', { processor: 'array' });
  45. };
  46. const getHelpTabs = option('help_tabs');
  47. const getForcedPlugins = option('forced_plugins');
  48. const register = (editor, dialogOpener) => {
  49. editor.ui.registry.addButton('help', {
  50. icon: 'help',
  51. tooltip: 'Help',
  52. onAction: dialogOpener
  53. });
  54. editor.ui.registry.addMenuItem('help', {
  55. text: 'Help',
  56. icon: 'help',
  57. shortcut: 'Alt+0',
  58. onAction: dialogOpener
  59. });
  60. };
  61. const hasProto = (v, constructor, predicate) => {
  62. var _a;
  63. if (predicate(v, constructor.prototype)) {
  64. return true;
  65. } else {
  66. return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
  67. }
  68. };
  69. const typeOf = x => {
  70. const t = typeof x;
  71. if (x === null) {
  72. return 'null';
  73. } else if (t === 'object' && Array.isArray(x)) {
  74. return 'array';
  75. } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
  76. return 'string';
  77. } else {
  78. return t;
  79. }
  80. };
  81. const isType = type => value => typeOf(value) === type;
  82. const isSimpleType = type => value => typeof value === type;
  83. const eq = t => a => t === a;
  84. const isString = isType('string');
  85. const isUndefined = eq(undefined);
  86. const isNullable = a => a === null || a === undefined;
  87. const isNonNullable = a => !isNullable(a);
  88. const isFunction = isSimpleType('function');
  89. const constant = value => {
  90. return () => {
  91. return value;
  92. };
  93. };
  94. const never = constant(false);
  95. class Optional {
  96. constructor(tag, value) {
  97. this.tag = tag;
  98. this.value = value;
  99. }
  100. static some(value) {
  101. return new Optional(true, value);
  102. }
  103. static none() {
  104. return Optional.singletonNone;
  105. }
  106. fold(onNone, onSome) {
  107. if (this.tag) {
  108. return onSome(this.value);
  109. } else {
  110. return onNone();
  111. }
  112. }
  113. isSome() {
  114. return this.tag;
  115. }
  116. isNone() {
  117. return !this.tag;
  118. }
  119. map(mapper) {
  120. if (this.tag) {
  121. return Optional.some(mapper(this.value));
  122. } else {
  123. return Optional.none();
  124. }
  125. }
  126. bind(binder) {
  127. if (this.tag) {
  128. return binder(this.value);
  129. } else {
  130. return Optional.none();
  131. }
  132. }
  133. exists(predicate) {
  134. return this.tag && predicate(this.value);
  135. }
  136. forall(predicate) {
  137. return !this.tag || predicate(this.value);
  138. }
  139. filter(predicate) {
  140. if (!this.tag || predicate(this.value)) {
  141. return this;
  142. } else {
  143. return Optional.none();
  144. }
  145. }
  146. getOr(replacement) {
  147. return this.tag ? this.value : replacement;
  148. }
  149. or(replacement) {
  150. return this.tag ? this : replacement;
  151. }
  152. getOrThunk(thunk) {
  153. return this.tag ? this.value : thunk();
  154. }
  155. orThunk(thunk) {
  156. return this.tag ? this : thunk();
  157. }
  158. getOrDie(message) {
  159. if (!this.tag) {
  160. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  161. } else {
  162. return this.value;
  163. }
  164. }
  165. static from(value) {
  166. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  167. }
  168. getOrNull() {
  169. return this.tag ? this.value : null;
  170. }
  171. getOrUndefined() {
  172. return this.value;
  173. }
  174. each(worker) {
  175. if (this.tag) {
  176. worker(this.value);
  177. }
  178. }
  179. toArray() {
  180. return this.tag ? [this.value] : [];
  181. }
  182. toString() {
  183. return this.tag ? `some(${ this.value })` : 'none()';
  184. }
  185. }
  186. Optional.singletonNone = new Optional(false);
  187. const nativeSlice = Array.prototype.slice;
  188. const nativeIndexOf = Array.prototype.indexOf;
  189. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  190. const contains = (xs, x) => rawIndexOf(xs, x) > -1;
  191. const map = (xs, f) => {
  192. const len = xs.length;
  193. const r = new Array(len);
  194. for (let i = 0; i < len; i++) {
  195. const x = xs[i];
  196. r[i] = f(x, i);
  197. }
  198. return r;
  199. };
  200. const filter = (xs, pred) => {
  201. const r = [];
  202. for (let i = 0, len = xs.length; i < len; i++) {
  203. const x = xs[i];
  204. if (pred(x, i)) {
  205. r.push(x);
  206. }
  207. }
  208. return r;
  209. };
  210. const findUntil = (xs, pred, until) => {
  211. for (let i = 0, len = xs.length; i < len; i++) {
  212. const x = xs[i];
  213. if (pred(x, i)) {
  214. return Optional.some(x);
  215. } else if (until(x, i)) {
  216. break;
  217. }
  218. }
  219. return Optional.none();
  220. };
  221. const find = (xs, pred) => {
  222. return findUntil(xs, pred, never);
  223. };
  224. const sort = (xs, comparator) => {
  225. const copy = nativeSlice.call(xs, 0);
  226. copy.sort(comparator);
  227. return copy;
  228. };
  229. const keys = Object.keys;
  230. const hasOwnProperty = Object.hasOwnProperty;
  231. const get = (obj, key) => {
  232. return has(obj, key) ? Optional.from(obj[key]) : Optional.none();
  233. };
  234. const has = (obj, key) => hasOwnProperty.call(obj, key);
  235. const cat = arr => {
  236. const r = [];
  237. const push = x => {
  238. r.push(x);
  239. };
  240. for (let i = 0; i < arr.length; i++) {
  241. arr[i].each(push);
  242. }
  243. return r;
  244. };
  245. const description = `<h1>Editor UI keyboard navigation</h1>
  246. <h2>Activating keyboard navigation</h2>
  247. <p>The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:</p>
  248. <ul>
  249. <li>Focus the menubar: Alt + F9 (Windows) or &#x2325;F9 (MacOS)</li>
  250. <li>Focus the toolbar: Alt + F10 (Windows) or &#x2325;F10 (MacOS)</li>
  251. <li>Focus the footer: Alt + F11 (Windows) or &#x2325;F11 (MacOS)</li>
  252. </ul>
  253. <p>Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline. </p>
  254. <h2>Moving between UI sections</h2>
  255. <p>When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:</p>
  256. <ul>
  257. <li>the menubar</li>
  258. <li>each group of the toolbar </li>
  259. <li>the sidebar</li>
  260. <li>the element path in the footer </li>
  261. <li>the wordcount toggle button in the footer </li>
  262. <li>the branding link in the footer </li>
  263. <li>the editor resize handle in the footer</li>
  264. </ul>
  265. <p>Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.</p>
  266. <h2>Moving within UI sections</h2>
  267. <p>Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:</p>
  268. <ul>
  269. <li>moving between menus in the menubar</li>
  270. <li>moving between buttons in a toolbar group</li>
  271. <li>moving between items in the element path</li>
  272. </ul>
  273. <p>In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group. </p>
  274. <h1>Executing buttons</h1>
  275. <p>To execute a button, navigate the selection to the desired button and hit space or enter.</p>
  276. <h1>Opening, navigating and closing menus</h1>
  277. <p>When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.</p>
  278. <p>To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.</p>
  279. <h1>Context toolbars and menus</h1>
  280. <p>To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or &#x2303;F9 (MacOS).</p>
  281. <p>Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.</p>
  282. <h1>Dialog navigation</h1>
  283. <p>There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.</p>
  284. <p>When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.</p>
  285. <p>When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.</p>`;
  286. const tab$3 = () => {
  287. const body = {
  288. type: 'htmlpanel',
  289. presets: 'document',
  290. html: description
  291. };
  292. return {
  293. name: 'keyboardnav',
  294. title: 'Keyboard Navigation',
  295. items: [body]
  296. };
  297. };
  298. var global$2 = tinymce.util.Tools.resolve('tinymce.Env');
  299. const convertText = source => {
  300. const isMac = global$2.os.isMacOS() || global$2.os.isiOS();
  301. const mac = {
  302. alt: '&#x2325;',
  303. ctrl: '&#x2303;',
  304. shift: '&#x21E7;',
  305. meta: '&#x2318;',
  306. access: '&#x2303;&#x2325;'
  307. };
  308. const other = {
  309. meta: 'Ctrl ',
  310. access: 'Shift + Alt '
  311. };
  312. const replace = isMac ? mac : other;
  313. const shortcut = source.split('+');
  314. const updated = map(shortcut, segment => {
  315. const search = segment.toLowerCase().trim();
  316. return has(replace, search) ? replace[search] : segment;
  317. });
  318. return isMac ? updated.join('').replace(/\s/, '') : updated.join('+');
  319. };
  320. const shortcuts = [
  321. {
  322. shortcuts: ['Meta + B'],
  323. action: 'Bold'
  324. },
  325. {
  326. shortcuts: ['Meta + I'],
  327. action: 'Italic'
  328. },
  329. {
  330. shortcuts: ['Meta + U'],
  331. action: 'Underline'
  332. },
  333. {
  334. shortcuts: ['Meta + A'],
  335. action: 'Select all'
  336. },
  337. {
  338. shortcuts: [
  339. 'Meta + Y',
  340. 'Meta + Shift + Z'
  341. ],
  342. action: 'Redo'
  343. },
  344. {
  345. shortcuts: ['Meta + Z'],
  346. action: 'Undo'
  347. },
  348. {
  349. shortcuts: ['Access + 1'],
  350. action: 'Heading 1'
  351. },
  352. {
  353. shortcuts: ['Access + 2'],
  354. action: 'Heading 2'
  355. },
  356. {
  357. shortcuts: ['Access + 3'],
  358. action: 'Heading 3'
  359. },
  360. {
  361. shortcuts: ['Access + 4'],
  362. action: 'Heading 4'
  363. },
  364. {
  365. shortcuts: ['Access + 5'],
  366. action: 'Heading 5'
  367. },
  368. {
  369. shortcuts: ['Access + 6'],
  370. action: 'Heading 6'
  371. },
  372. {
  373. shortcuts: ['Access + 7'],
  374. action: 'Paragraph'
  375. },
  376. {
  377. shortcuts: ['Access + 8'],
  378. action: 'Div'
  379. },
  380. {
  381. shortcuts: ['Access + 9'],
  382. action: 'Address'
  383. },
  384. {
  385. shortcuts: ['Alt + 0'],
  386. action: 'Open help dialog'
  387. },
  388. {
  389. shortcuts: ['Alt + F9'],
  390. action: 'Focus to menubar'
  391. },
  392. {
  393. shortcuts: ['Alt + F10'],
  394. action: 'Focus to toolbar'
  395. },
  396. {
  397. shortcuts: ['Alt + F11'],
  398. action: 'Focus to element path'
  399. },
  400. {
  401. shortcuts: ['Ctrl + F9'],
  402. action: 'Focus to contextual toolbar'
  403. },
  404. {
  405. shortcuts: ['Shift + Enter'],
  406. action: 'Open popup menu for split buttons'
  407. },
  408. {
  409. shortcuts: ['Meta + K'],
  410. action: 'Insert link (if link plugin activated)'
  411. },
  412. {
  413. shortcuts: ['Meta + S'],
  414. action: 'Save (if save plugin activated)'
  415. },
  416. {
  417. shortcuts: ['Meta + F'],
  418. action: 'Find (if searchreplace plugin activated)'
  419. },
  420. {
  421. shortcuts: ['Meta + Shift + F'],
  422. action: 'Switch to or from fullscreen mode'
  423. }
  424. ];
  425. const tab$2 = () => {
  426. const shortcutList = map(shortcuts, shortcut => {
  427. const shortcutText = map(shortcut.shortcuts, convertText).join(' or ');
  428. return [
  429. shortcut.action,
  430. shortcutText
  431. ];
  432. });
  433. const tablePanel = {
  434. type: 'table',
  435. header: [
  436. 'Action',
  437. 'Shortcut'
  438. ],
  439. cells: shortcutList
  440. };
  441. return {
  442. name: 'shortcuts',
  443. title: 'Handy Shortcuts',
  444. items: [tablePanel]
  445. };
  446. };
  447. var global$1 = tinymce.util.Tools.resolve('tinymce.util.I18n');
  448. const urls = map([
  449. {
  450. key: 'advlist',
  451. name: 'Advanced List'
  452. },
  453. {
  454. key: 'anchor',
  455. name: 'Anchor'
  456. },
  457. {
  458. key: 'autolink',
  459. name: 'Autolink'
  460. },
  461. {
  462. key: 'autoresize',
  463. name: 'Autoresize'
  464. },
  465. {
  466. key: 'autosave',
  467. name: 'Autosave'
  468. },
  469. {
  470. key: 'charmap',
  471. name: 'Character Map'
  472. },
  473. {
  474. key: 'code',
  475. name: 'Code'
  476. },
  477. {
  478. key: 'codesample',
  479. name: 'Code Sample'
  480. },
  481. {
  482. key: 'colorpicker',
  483. name: 'Color Picker'
  484. },
  485. {
  486. key: 'directionality',
  487. name: 'Directionality'
  488. },
  489. {
  490. key: 'emoticons',
  491. name: 'Emoticons'
  492. },
  493. {
  494. key: 'fullscreen',
  495. name: 'Full Screen'
  496. },
  497. {
  498. key: 'help',
  499. name: 'Help'
  500. },
  501. {
  502. key: 'image',
  503. name: 'Image'
  504. },
  505. {
  506. key: 'importcss',
  507. name: 'Import CSS'
  508. },
  509. {
  510. key: 'insertdatetime',
  511. name: 'Insert Date/Time'
  512. },
  513. {
  514. key: 'link',
  515. name: 'Link'
  516. },
  517. {
  518. key: 'lists',
  519. name: 'Lists'
  520. },
  521. {
  522. key: 'media',
  523. name: 'Media'
  524. },
  525. {
  526. key: 'nonbreaking',
  527. name: 'Nonbreaking'
  528. },
  529. {
  530. key: 'pagebreak',
  531. name: 'Page Break'
  532. },
  533. {
  534. key: 'preview',
  535. name: 'Preview'
  536. },
  537. {
  538. key: 'quickbars',
  539. name: 'Quick Toolbars'
  540. },
  541. {
  542. key: 'save',
  543. name: 'Save'
  544. },
  545. {
  546. key: 'searchreplace',
  547. name: 'Search and Replace'
  548. },
  549. {
  550. key: 'table',
  551. name: 'Table'
  552. },
  553. {
  554. key: 'template',
  555. name: 'Template'
  556. },
  557. {
  558. key: 'textcolor',
  559. name: 'Text Color'
  560. },
  561. {
  562. key: 'visualblocks',
  563. name: 'Visual Blocks'
  564. },
  565. {
  566. key: 'visualchars',
  567. name: 'Visual Characters'
  568. },
  569. {
  570. key: 'wordcount',
  571. name: 'Word Count'
  572. },
  573. {
  574. key: 'a11ychecker',
  575. name: 'Accessibility Checker',
  576. type: 'premium'
  577. },
  578. {
  579. key: 'advcode',
  580. name: 'Advanced Code Editor',
  581. type: 'premium'
  582. },
  583. {
  584. key: 'advtable',
  585. name: 'Advanced Tables',
  586. type: 'premium'
  587. },
  588. {
  589. key: 'advtemplate',
  590. name: 'Advanced Templates',
  591. type: 'premium',
  592. slug: 'advanced-templates'
  593. },
  594. {
  595. key: 'casechange',
  596. name: 'Case Change',
  597. type: 'premium'
  598. },
  599. {
  600. key: 'checklist',
  601. name: 'Checklist',
  602. type: 'premium'
  603. },
  604. {
  605. key: 'editimage',
  606. name: 'Enhanced Image Editing',
  607. type: 'premium'
  608. },
  609. {
  610. key: 'footnotes',
  611. name: 'Footnotes',
  612. type: 'premium'
  613. },
  614. {
  615. key: 'typography',
  616. name: 'Advanced Typography',
  617. type: 'premium',
  618. slug: 'advanced-typography'
  619. },
  620. {
  621. key: 'mediaembed',
  622. name: 'Enhanced Media Embed',
  623. type: 'premium',
  624. slug: 'introduction-to-mediaembed'
  625. },
  626. {
  627. key: 'export',
  628. name: 'Export',
  629. type: 'premium'
  630. },
  631. {
  632. key: 'formatpainter',
  633. name: 'Format Painter',
  634. type: 'premium'
  635. },
  636. {
  637. key: 'inlinecss',
  638. name: 'Inline CSS',
  639. type: 'premium',
  640. slug: 'inline-css'
  641. },
  642. {
  643. key: 'linkchecker',
  644. name: 'Link Checker',
  645. type: 'premium'
  646. },
  647. {
  648. key: 'mentions',
  649. name: 'Mentions',
  650. type: 'premium'
  651. },
  652. {
  653. key: 'mergetags',
  654. name: 'Merge Tags',
  655. type: 'premium'
  656. },
  657. {
  658. key: 'pageembed',
  659. name: 'Page Embed',
  660. type: 'premium'
  661. },
  662. {
  663. key: 'permanentpen',
  664. name: 'Permanent Pen',
  665. type: 'premium'
  666. },
  667. {
  668. key: 'powerpaste',
  669. name: 'PowerPaste',
  670. type: 'premium',
  671. slug: 'introduction-to-powerpaste'
  672. },
  673. {
  674. key: 'rtc',
  675. name: 'Real-Time Collaboration',
  676. type: 'premium',
  677. slug: 'rtc-introduction'
  678. },
  679. {
  680. key: 'tinymcespellchecker',
  681. name: 'Spell Checker Pro',
  682. type: 'premium',
  683. slug: 'introduction-to-tiny-spellchecker'
  684. },
  685. {
  686. key: 'autocorrect',
  687. name: 'Spelling Autocorrect',
  688. type: 'premium'
  689. },
  690. {
  691. key: 'tableofcontents',
  692. name: 'Table of Contents',
  693. type: 'premium'
  694. },
  695. {
  696. key: 'tinycomments',
  697. name: 'Tiny Comments',
  698. type: 'premium',
  699. slug: 'introduction-to-tiny-comments'
  700. },
  701. {
  702. key: 'tinydrive',
  703. name: 'Tiny Drive',
  704. type: 'premium',
  705. slug: 'tinydrive-introduction'
  706. }
  707. ], item => ({
  708. ...item,
  709. type: item.type || 'opensource',
  710. slug: item.slug || item.key
  711. }));
  712. const tab$1 = editor => {
  713. const availablePlugins = () => {
  714. const premiumPlugins = filter(urls, ({type}) => {
  715. return type === 'premium';
  716. });
  717. const sortedPremiumPlugins = sort(map(premiumPlugins, p => p.name), (s1, s2) => s1.localeCompare(s2));
  718. const premiumPluginList = map(sortedPremiumPlugins, pluginName => `<li>${ pluginName }</li>`).join('');
  719. return '<div data-mce-tabstop="1" tabindex="-1">' + '<p><b>' + global$1.translate('Premium plugins:') + '</b></p>' + '<ul>' + premiumPluginList + '<li class="tox-help__more-link" "><a href="https://www.tiny.cloud/pricing/?utm_campaign=editor_referral&utm_medium=help_dialog&utm_source=tinymce" rel="noopener" target="_blank">' + global$1.translate('Learn more...') + '</a></li>' + '</ul>' + '</div>';
  720. };
  721. const makeLink = p => `<a href="${ p.url }" target="_blank" rel="noopener">${ p.name }</a>`;
  722. const identifyUnknownPlugin = (editor, key) => {
  723. const getMetadata = editor.plugins[key].getMetadata;
  724. if (isFunction(getMetadata)) {
  725. const metadata = getMetadata();
  726. return {
  727. name: metadata.name,
  728. html: makeLink(metadata)
  729. };
  730. } else {
  731. return {
  732. name: key,
  733. html: key
  734. };
  735. }
  736. };
  737. const getPluginData = (editor, key) => find(urls, x => {
  738. return x.key === key;
  739. }).fold(() => {
  740. return identifyUnknownPlugin(editor, key);
  741. }, x => {
  742. const name = x.type === 'premium' ? `${ x.name }*` : x.name;
  743. const html = makeLink({
  744. name,
  745. url: `https://www.tiny.cloud/docs/tinymce/6/${ x.slug }/`
  746. });
  747. return {
  748. name,
  749. html
  750. };
  751. });
  752. const getPluginKeys = editor => {
  753. const keys$1 = keys(editor.plugins);
  754. const forcedPlugins = getForcedPlugins(editor);
  755. return isUndefined(forcedPlugins) ? keys$1 : filter(keys$1, k => !contains(forcedPlugins, k));
  756. };
  757. const pluginLister = editor => {
  758. const pluginKeys = getPluginKeys(editor);
  759. const sortedPluginData = sort(map(pluginKeys, k => getPluginData(editor, k)), (pd1, pd2) => pd1.name.localeCompare(pd2.name));
  760. const pluginLis = map(sortedPluginData, key => {
  761. return '<li>' + key.html + '</li>';
  762. });
  763. const count = pluginLis.length;
  764. const pluginsString = pluginLis.join('');
  765. const html = '<p><b>' + global$1.translate([
  766. 'Plugins installed ({0}):',
  767. count
  768. ]) + '</b></p>' + '<ul>' + pluginsString + '</ul>';
  769. return html;
  770. };
  771. const installedPlugins = editor => {
  772. if (editor == null) {
  773. return '';
  774. }
  775. return '<div data-mce-tabstop="1" tabindex="-1">' + pluginLister(editor) + '</div>';
  776. };
  777. const htmlPanel = {
  778. type: 'htmlpanel',
  779. presets: 'document',
  780. html: [
  781. installedPlugins(editor),
  782. availablePlugins()
  783. ].join('')
  784. };
  785. return {
  786. name: 'plugins',
  787. title: 'Plugins',
  788. items: [htmlPanel]
  789. };
  790. };
  791. var global = tinymce.util.Tools.resolve('tinymce.EditorManager');
  792. const tab = () => {
  793. const getVersion = (major, minor) => major.indexOf('@') === 0 ? 'X.X.X' : major + '.' + minor;
  794. const version = getVersion(global.majorVersion, global.minorVersion);
  795. const changeLogLink = '<a href="https://www.tiny.cloud/docs/tinymce/6/changelog/?utm_campaign=editor_referral&utm_medium=help_dialog&utm_source=tinymce" rel="noopener" target="_blank">TinyMCE ' + version + '</a>';
  796. const htmlPanel = {
  797. type: 'htmlpanel',
  798. html: '<p>' + global$1.translate([
  799. 'You are using {0}',
  800. changeLogLink
  801. ]) + '</p>',
  802. presets: 'document'
  803. };
  804. return {
  805. name: 'versions',
  806. title: 'Version',
  807. items: [htmlPanel]
  808. };
  809. };
  810. const parseHelpTabsSetting = (tabsFromSettings, tabs) => {
  811. const newTabs = {};
  812. const names = map(tabsFromSettings, t => {
  813. var _a;
  814. if (isString(t)) {
  815. if (has(tabs, t)) {
  816. newTabs[t] = tabs[t];
  817. }
  818. return t;
  819. } else {
  820. const name = (_a = t.name) !== null && _a !== void 0 ? _a : generate('tab-name');
  821. newTabs[name] = t;
  822. return name;
  823. }
  824. });
  825. return {
  826. tabs: newTabs,
  827. names
  828. };
  829. };
  830. const getNamesFromTabs = tabs => {
  831. const names = keys(tabs);
  832. const idx = names.indexOf('versions');
  833. if (idx !== -1) {
  834. names.splice(idx, 1);
  835. names.push('versions');
  836. }
  837. return {
  838. tabs,
  839. names
  840. };
  841. };
  842. const parseCustomTabs = (editor, customTabs) => {
  843. const shortcuts = tab$2();
  844. const nav = tab$3();
  845. const plugins = tab$1(editor);
  846. const versions = tab();
  847. const tabs = {
  848. [shortcuts.name]: shortcuts,
  849. [nav.name]: nav,
  850. [plugins.name]: plugins,
  851. [versions.name]: versions,
  852. ...customTabs.get()
  853. };
  854. return Optional.from(getHelpTabs(editor)).fold(() => getNamesFromTabs(tabs), tabsFromSettings => parseHelpTabsSetting(tabsFromSettings, tabs));
  855. };
  856. const init = (editor, customTabs) => () => {
  857. const {tabs, names} = parseCustomTabs(editor, customTabs);
  858. const foundTabs = map(names, name => get(tabs, name));
  859. const dialogTabs = cat(foundTabs);
  860. const body = {
  861. type: 'tabpanel',
  862. tabs: dialogTabs
  863. };
  864. editor.windowManager.open({
  865. title: 'Help',
  866. size: 'normal',
  867. body,
  868. buttons: [{
  869. type: 'cancel',
  870. name: 'close',
  871. text: 'Close',
  872. primary: true
  873. }],
  874. initialData: {}
  875. });
  876. };
  877. var Plugin = () => {
  878. global$3.add('help', editor => {
  879. const customTabs = Cell({});
  880. const api = get$1(customTabs);
  881. register$1(editor);
  882. const dialogOpener = init(editor, customTabs);
  883. register(editor, dialogOpener);
  884. register$2(editor, dialogOpener);
  885. editor.shortcuts.add('Alt+0', 'Open help dialog', 'mceHelp');
  886. return api;
  887. });
  888. };
  889. Plugin();
  890. })();