MDL-78251 editor_tiny: Update TinyMCE to 6.6.2
[moodle.git] / lib / editor / tiny / js / tinymce / plugins / importcss / plugin.js
blob245fc074fc383f75cbc63b62e325e0a37928c1fb
1 /**
2  * TinyMCE version 6.6.2 (2023-08-09)
3  */
5 (function () {
6     'use strict';
8     var global$4 = tinymce.util.Tools.resolve('tinymce.PluginManager');
10     const hasProto = (v, constructor, predicate) => {
11       var _a;
12       if (predicate(v, constructor.prototype)) {
13         return true;
14       } else {
15         return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
16       }
17     };
18     const typeOf = x => {
19       const t = typeof x;
20       if (x === null) {
21         return 'null';
22       } else if (t === 'object' && Array.isArray(x)) {
23         return 'array';
24       } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
25         return 'string';
26       } else {
27         return t;
28       }
29     };
30     const isType = type => value => typeOf(value) === type;
31     const isSimpleType = type => value => typeof value === type;
32     const isString = isType('string');
33     const isObject = isType('object');
34     const isArray = isType('array');
35     const isFunction = isSimpleType('function');
37     var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
39     var global$2 = tinymce.util.Tools.resolve('tinymce.EditorManager');
41     var global$1 = tinymce.util.Tools.resolve('tinymce.Env');
43     var global = tinymce.util.Tools.resolve('tinymce.util.Tools');
45     const option = name => editor => editor.options.get(name);
46     const register = editor => {
47       const registerOption = editor.options.register;
48       const filterProcessor = value => isString(value) || isFunction(value) || isObject(value);
49       registerOption('importcss_merge_classes', {
50         processor: 'boolean',
51         default: true
52       });
53       registerOption('importcss_exclusive', {
54         processor: 'boolean',
55         default: true
56       });
57       registerOption('importcss_selector_converter', { processor: 'function' });
58       registerOption('importcss_selector_filter', { processor: filterProcessor });
59       registerOption('importcss_file_filter', { processor: filterProcessor });
60       registerOption('importcss_groups', { processor: 'object[]' });
61       registerOption('importcss_append', {
62         processor: 'boolean',
63         default: false
64       });
65     };
66     const shouldMergeClasses = option('importcss_merge_classes');
67     const shouldImportExclusive = option('importcss_exclusive');
68     const getSelectorConverter = option('importcss_selector_converter');
69     const getSelectorFilter = option('importcss_selector_filter');
70     const getCssGroups = option('importcss_groups');
71     const shouldAppend = option('importcss_append');
72     const getFileFilter = option('importcss_file_filter');
73     const getSkin = option('skin');
74     const getSkinUrl = option('skin_url');
76     const nativePush = Array.prototype.push;
77     const map = (xs, f) => {
78       const len = xs.length;
79       const r = new Array(len);
80       for (let i = 0; i < len; i++) {
81         const x = xs[i];
82         r[i] = f(x, i);
83       }
84       return r;
85     };
86     const flatten = xs => {
87       const r = [];
88       for (let i = 0, len = xs.length; i < len; ++i) {
89         if (!isArray(xs[i])) {
90           throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
91         }
92         nativePush.apply(r, xs[i]);
93       }
94       return r;
95     };
96     const bind = (xs, f) => flatten(map(xs, f));
98     const generate = () => {
99       const ungroupedOrder = [];
100       const groupOrder = [];
101       const groups = {};
102       const addItemToGroup = (groupTitle, itemInfo) => {
103         if (groups[groupTitle]) {
104           groups[groupTitle].push(itemInfo);
105         } else {
106           groupOrder.push(groupTitle);
107           groups[groupTitle] = [itemInfo];
108         }
109       };
110       const addItem = itemInfo => {
111         ungroupedOrder.push(itemInfo);
112       };
113       const toFormats = () => {
114         const groupItems = bind(groupOrder, g => {
115           const items = groups[g];
116           return items.length === 0 ? [] : [{
117               title: g,
118               items
119             }];
120         });
121         return groupItems.concat(ungroupedOrder);
122       };
123       return {
124         addItemToGroup,
125         addItem,
126         toFormats
127       };
128     };
130     const internalEditorStyle = /^\.(?:ephox|tiny-pageembed|mce)(?:[.-]+\w+)+$/;
131     const removeCacheSuffix = url => {
132       const cacheSuffix = global$1.cacheSuffix;
133       if (isString(url)) {
134         url = url.replace('?' + cacheSuffix, '').replace('&' + cacheSuffix, '');
135       }
136       return url;
137     };
138     const isSkinContentCss = (editor, href) => {
139       const skin = getSkin(editor);
140       if (skin) {
141         const skinUrlBase = getSkinUrl(editor);
142         const skinUrl = skinUrlBase ? editor.documentBaseURI.toAbsolute(skinUrlBase) : global$2.baseURL + '/skins/ui/' + skin;
143         const contentSkinUrlPart = global$2.baseURL + '/skins/content/';
144         return href === skinUrl + '/content' + (editor.inline ? '.inline' : '') + '.min.css' || href.indexOf(contentSkinUrlPart) !== -1;
145       }
146       return false;
147     };
148     const compileFilter = filter => {
149       if (isString(filter)) {
150         return value => {
151           return value.indexOf(filter) !== -1;
152         };
153       } else if (filter instanceof RegExp) {
154         return value => {
155           return filter.test(value);
156         };
157       }
158       return filter;
159     };
160     const isCssImportRule = rule => rule.styleSheet;
161     const isCssPageRule = rule => rule.selectorText;
162     const getSelectors = (editor, doc, fileFilter) => {
163       const selectors = [];
164       const contentCSSUrls = {};
165       const append = (styleSheet, imported) => {
166         let href = styleSheet.href;
167         let rules;
168         href = removeCacheSuffix(href);
169         if (!href || fileFilter && !fileFilter(href, imported) || isSkinContentCss(editor, href)) {
170           return;
171         }
172         global.each(styleSheet.imports, styleSheet => {
173           append(styleSheet, true);
174         });
175         try {
176           rules = styleSheet.cssRules || styleSheet.rules;
177         } catch (e) {
178         }
179         global.each(rules, cssRule => {
180           if (isCssImportRule(cssRule)) {
181             append(cssRule.styleSheet, true);
182           } else if (isCssPageRule(cssRule)) {
183             global.each(cssRule.selectorText.split(','), selector => {
184               selectors.push(global.trim(selector));
185             });
186           }
187         });
188       };
189       global.each(editor.contentCSS, url => {
190         contentCSSUrls[url] = true;
191       });
192       if (!fileFilter) {
193         fileFilter = (href, imported) => {
194           return imported || contentCSSUrls[href];
195         };
196       }
197       try {
198         global.each(doc.styleSheets, styleSheet => {
199           append(styleSheet);
200         });
201       } catch (e) {
202       }
203       return selectors;
204     };
205     const defaultConvertSelectorToFormat = (editor, selectorText) => {
206       let format = {};
207       const selector = /^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(selectorText);
208       if (!selector) {
209         return;
210       }
211       const elementName = selector[1];
212       const classes = selector[2].substr(1).split('.').join(' ');
213       const inlineSelectorElements = global.makeMap('a,img');
214       if (selector[1]) {
215         format = { title: selectorText };
216         if (editor.schema.getTextBlockElements()[elementName]) {
217           format.block = elementName;
218         } else if (editor.schema.getBlockElements()[elementName] || inlineSelectorElements[elementName.toLowerCase()]) {
219           format.selector = elementName;
220         } else {
221           format.inline = elementName;
222         }
223       } else if (selector[2]) {
224         format = {
225           inline: 'span',
226           title: selectorText.substr(1),
227           classes
228         };
229       }
230       if (shouldMergeClasses(editor)) {
231         format.classes = classes;
232       } else {
233         format.attributes = { class: classes };
234       }
235       return format;
236     };
237     const getGroupsBySelector = (groups, selector) => {
238       return global.grep(groups, group => {
239         return !group.filter || group.filter(selector);
240       });
241     };
242     const compileUserDefinedGroups = groups => {
243       return global.map(groups, group => {
244         return global.extend({}, group, {
245           original: group,
246           selectors: {},
247           filter: compileFilter(group.filter)
248         });
249       });
250     };
251     const isExclusiveMode = (editor, group) => {
252       return group === null || shouldImportExclusive(editor);
253     };
254     const isUniqueSelector = (editor, selector, group, globallyUniqueSelectors) => {
255       return !(isExclusiveMode(editor, group) ? selector in globallyUniqueSelectors : selector in group.selectors);
256     };
257     const markUniqueSelector = (editor, selector, group, globallyUniqueSelectors) => {
258       if (isExclusiveMode(editor, group)) {
259         globallyUniqueSelectors[selector] = true;
260       } else {
261         group.selectors[selector] = true;
262       }
263     };
264     const convertSelectorToFormat = (editor, plugin, selector, group) => {
265       let selectorConverter;
266       const converter = getSelectorConverter(editor);
267       if (group && group.selector_converter) {
268         selectorConverter = group.selector_converter;
269       } else if (converter) {
270         selectorConverter = converter;
271       } else {
272         selectorConverter = () => {
273           return defaultConvertSelectorToFormat(editor, selector);
274         };
275       }
276       return selectorConverter.call(plugin, selector, group);
277     };
278     const setup = editor => {
279       editor.on('init', () => {
280         const model = generate();
281         const globallyUniqueSelectors = {};
282         const selectorFilter = compileFilter(getSelectorFilter(editor));
283         const groups = compileUserDefinedGroups(getCssGroups(editor));
284         const processSelector = (selector, group) => {
285           if (isUniqueSelector(editor, selector, group, globallyUniqueSelectors)) {
286             markUniqueSelector(editor, selector, group, globallyUniqueSelectors);
287             const format = convertSelectorToFormat(editor, editor.plugins.importcss, selector, group);
288             if (format) {
289               const formatName = format.name || global$3.DOM.uniqueId();
290               editor.formatter.register(formatName, format);
291               return {
292                 title: format.title,
293                 format: formatName
294               };
295             }
296           }
297           return null;
298         };
299         global.each(getSelectors(editor, editor.getDoc(), compileFilter(getFileFilter(editor))), selector => {
300           if (!internalEditorStyle.test(selector)) {
301             if (!selectorFilter || selectorFilter(selector)) {
302               const selectorGroups = getGroupsBySelector(groups, selector);
303               if (selectorGroups.length > 0) {
304                 global.each(selectorGroups, group => {
305                   const menuItem = processSelector(selector, group);
306                   if (menuItem) {
307                     model.addItemToGroup(group.title, menuItem);
308                   }
309                 });
310               } else {
311                 const menuItem = processSelector(selector, null);
312                 if (menuItem) {
313                   model.addItem(menuItem);
314                 }
315               }
316             }
317           }
318         });
319         const items = model.toFormats();
320         editor.dispatch('addStyleModifications', {
321           items,
322           replace: !shouldAppend(editor)
323         });
324       });
325     };
327     const get = editor => {
328       const convertSelectorToFormat = selectorText => {
329         return defaultConvertSelectorToFormat(editor, selectorText);
330       };
331       return { convertSelectorToFormat };
332     };
334     var Plugin = () => {
335       global$4.add('importcss', editor => {
336         register(editor);
337         setup(editor);
338         return get(editor);
339       });
340     };
342     Plugin();
344 })();