Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

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