plugin.js 11 KB

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