plugin.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /**
  2. * TinyMCE version 6.4.2 (2023-04-26)
  3. */
  4. (function () {
  5. 'use strict';
  6. var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');
  7. const applyListFormat = (editor, listName, styleValue) => {
  8. const cmd = listName === 'UL' ? 'InsertUnorderedList' : 'InsertOrderedList';
  9. editor.execCommand(cmd, false, styleValue === false ? null : { 'list-style-type': styleValue });
  10. };
  11. const register$2 = editor => {
  12. editor.addCommand('ApplyUnorderedListStyle', (ui, value) => {
  13. applyListFormat(editor, 'UL', value['list-style-type']);
  14. });
  15. editor.addCommand('ApplyOrderedListStyle', (ui, value) => {
  16. applyListFormat(editor, 'OL', value['list-style-type']);
  17. });
  18. };
  19. const option = name => editor => editor.options.get(name);
  20. const register$1 = editor => {
  21. const registerOption = editor.options.register;
  22. registerOption('advlist_number_styles', {
  23. processor: 'string[]',
  24. default: 'default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman'.split(',')
  25. });
  26. registerOption('advlist_bullet_styles', {
  27. processor: 'string[]',
  28. default: 'default,circle,square'.split(',')
  29. });
  30. };
  31. const getNumberStyles = option('advlist_number_styles');
  32. const getBulletStyles = option('advlist_bullet_styles');
  33. const isNullable = a => a === null || a === undefined;
  34. const isNonNullable = a => !isNullable(a);
  35. var global = tinymce.util.Tools.resolve('tinymce.util.Tools');
  36. class Optional {
  37. constructor(tag, value) {
  38. this.tag = tag;
  39. this.value = value;
  40. }
  41. static some(value) {
  42. return new Optional(true, value);
  43. }
  44. static none() {
  45. return Optional.singletonNone;
  46. }
  47. fold(onNone, onSome) {
  48. if (this.tag) {
  49. return onSome(this.value);
  50. } else {
  51. return onNone();
  52. }
  53. }
  54. isSome() {
  55. return this.tag;
  56. }
  57. isNone() {
  58. return !this.tag;
  59. }
  60. map(mapper) {
  61. if (this.tag) {
  62. return Optional.some(mapper(this.value));
  63. } else {
  64. return Optional.none();
  65. }
  66. }
  67. bind(binder) {
  68. if (this.tag) {
  69. return binder(this.value);
  70. } else {
  71. return Optional.none();
  72. }
  73. }
  74. exists(predicate) {
  75. return this.tag && predicate(this.value);
  76. }
  77. forall(predicate) {
  78. return !this.tag || predicate(this.value);
  79. }
  80. filter(predicate) {
  81. if (!this.tag || predicate(this.value)) {
  82. return this;
  83. } else {
  84. return Optional.none();
  85. }
  86. }
  87. getOr(replacement) {
  88. return this.tag ? this.value : replacement;
  89. }
  90. or(replacement) {
  91. return this.tag ? this : replacement;
  92. }
  93. getOrThunk(thunk) {
  94. return this.tag ? this.value : thunk();
  95. }
  96. orThunk(thunk) {
  97. return this.tag ? this : thunk();
  98. }
  99. getOrDie(message) {
  100. if (!this.tag) {
  101. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  102. } else {
  103. return this.value;
  104. }
  105. }
  106. static from(value) {
  107. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  108. }
  109. getOrNull() {
  110. return this.tag ? this.value : null;
  111. }
  112. getOrUndefined() {
  113. return this.value;
  114. }
  115. each(worker) {
  116. if (this.tag) {
  117. worker(this.value);
  118. }
  119. }
  120. toArray() {
  121. return this.tag ? [this.value] : [];
  122. }
  123. toString() {
  124. return this.tag ? `some(${ this.value })` : 'none()';
  125. }
  126. }
  127. Optional.singletonNone = new Optional(false);
  128. const findUntil = (xs, pred, until) => {
  129. for (let i = 0, len = xs.length; i < len; i++) {
  130. const x = xs[i];
  131. if (pred(x, i)) {
  132. return Optional.some(x);
  133. } else if (until(x, i)) {
  134. break;
  135. }
  136. }
  137. return Optional.none();
  138. };
  139. const isCustomList = list => /\btox\-/.test(list.className);
  140. const isChildOfBody = (editor, elm) => {
  141. return editor.dom.isChildOf(elm, editor.getBody());
  142. };
  143. const matchNodeNames = regex => node => isNonNullable(node) && regex.test(node.nodeName);
  144. const isListNode = matchNodeNames(/^(OL|UL|DL)$/);
  145. const isTableCellNode = matchNodeNames(/^(TH|TD)$/);
  146. const inList = (editor, parents, nodeName) => findUntil(parents, parent => isListNode(parent) && !isCustomList(parent), isTableCellNode).exists(list => list.nodeName === nodeName && isChildOfBody(editor, list));
  147. const getSelectedStyleType = editor => {
  148. const listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul');
  149. const style = editor.dom.getStyle(listElm, 'listStyleType');
  150. return Optional.from(style);
  151. };
  152. const isWithinNonEditable = (editor, element) => element !== null && !editor.dom.isEditable(element);
  153. const isWithinNonEditableList = (editor, element) => {
  154. const parentList = editor.dom.getParent(element, 'ol,ul,dl');
  155. return isWithinNonEditable(editor, parentList);
  156. };
  157. const setNodeChangeHandler = (editor, nodeChangeHandler) => {
  158. const initialNode = editor.selection.getNode();
  159. nodeChangeHandler({
  160. parents: editor.dom.getParents(initialNode),
  161. element: initialNode
  162. });
  163. editor.on('NodeChange', nodeChangeHandler);
  164. return () => editor.off('NodeChange', nodeChangeHandler);
  165. };
  166. const styleValueToText = styleValue => {
  167. return styleValue.replace(/\-/g, ' ').replace(/\b\w/g, chr => {
  168. return chr.toUpperCase();
  169. });
  170. };
  171. const normalizeStyleValue = styleValue => isNullable(styleValue) || styleValue === 'default' ? '' : styleValue;
  172. const makeSetupHandler = (editor, nodeName) => api => {
  173. const updateButtonState = (editor, parents) => {
  174. const element = editor.selection.getStart(true);
  175. api.setActive(inList(editor, parents, nodeName));
  176. api.setEnabled(!isWithinNonEditableList(editor, element));
  177. };
  178. const nodeChangeHandler = e => updateButtonState(editor, e.parents);
  179. return setNodeChangeHandler(editor, nodeChangeHandler);
  180. };
  181. const addSplitButton = (editor, id, tooltip, cmd, nodeName, styles) => {
  182. editor.ui.registry.addSplitButton(id, {
  183. tooltip,
  184. icon: nodeName === 'OL' ? 'ordered-list' : 'unordered-list',
  185. presets: 'listpreview',
  186. columns: 3,
  187. fetch: callback => {
  188. const items = global.map(styles, styleValue => {
  189. const iconStyle = nodeName === 'OL' ? 'num' : 'bull';
  190. const iconName = styleValue === 'disc' || styleValue === 'decimal' ? 'default' : styleValue;
  191. const itemValue = normalizeStyleValue(styleValue);
  192. const displayText = styleValueToText(styleValue);
  193. return {
  194. type: 'choiceitem',
  195. value: itemValue,
  196. icon: 'list-' + iconStyle + '-' + iconName,
  197. text: displayText
  198. };
  199. });
  200. callback(items);
  201. },
  202. onAction: () => editor.execCommand(cmd),
  203. onItemAction: (_splitButtonApi, value) => {
  204. applyListFormat(editor, nodeName, value);
  205. },
  206. select: value => {
  207. const listStyleType = getSelectedStyleType(editor);
  208. return listStyleType.map(listStyle => value === listStyle).getOr(false);
  209. },
  210. onSetup: makeSetupHandler(editor, nodeName)
  211. });
  212. };
  213. const addButton = (editor, id, tooltip, cmd, nodeName, styleValue) => {
  214. editor.ui.registry.addToggleButton(id, {
  215. active: false,
  216. tooltip,
  217. icon: nodeName === 'OL' ? 'ordered-list' : 'unordered-list',
  218. onSetup: makeSetupHandler(editor, nodeName),
  219. onAction: () => editor.queryCommandState(cmd) || styleValue === '' ? editor.execCommand(cmd) : applyListFormat(editor, nodeName, styleValue)
  220. });
  221. };
  222. const addControl = (editor, id, tooltip, cmd, nodeName, styles) => {
  223. if (styles.length > 1) {
  224. addSplitButton(editor, id, tooltip, cmd, nodeName, styles);
  225. } else {
  226. addButton(editor, id, tooltip, cmd, nodeName, normalizeStyleValue(styles[0]));
  227. }
  228. };
  229. const register = editor => {
  230. addControl(editor, 'numlist', 'Numbered list', 'InsertOrderedList', 'OL', getNumberStyles(editor));
  231. addControl(editor, 'bullist', 'Bullet list', 'InsertUnorderedList', 'UL', getBulletStyles(editor));
  232. };
  233. var Plugin = () => {
  234. global$1.add('advlist', editor => {
  235. if (editor.hasPlugin('lists')) {
  236. register$1(editor);
  237. register(editor);
  238. register$2(editor);
  239. } else {
  240. console.error('Please use the Lists plugin together with the Advanced List plugin.');
  241. }
  242. });
  243. };
  244. Plugin();
  245. })();