plugin.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  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.0.7 (2019-06-05)
  8. */
  9. (function () {
  10. var template = (function () {
  11. 'use strict';
  12. var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  13. var constant = function (value) {
  14. return function () {
  15. return value;
  16. };
  17. };
  18. function curry(fn) {
  19. var initialArgs = [];
  20. for (var _i = 1; _i < arguments.length; _i++) {
  21. initialArgs[_i - 1] = arguments[_i];
  22. }
  23. return function () {
  24. var restArgs = [];
  25. for (var _i = 0; _i < arguments.length; _i++) {
  26. restArgs[_i] = arguments[_i];
  27. }
  28. var all = initialArgs.concat(restArgs);
  29. return fn.apply(null, all);
  30. };
  31. }
  32. var never = constant(false);
  33. var always = constant(true);
  34. var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
  35. var global$2 = tinymce.util.Tools.resolve('tinymce.util.XHR');
  36. var getCreationDateClasses = function (editor) {
  37. return editor.getParam('template_cdate_classes', 'cdate');
  38. };
  39. var getModificationDateClasses = function (editor) {
  40. return editor.getParam('template_mdate_classes', 'mdate');
  41. };
  42. var getSelectedContentClasses = function (editor) {
  43. return editor.getParam('template_selected_content_classes', 'selcontent');
  44. };
  45. var getPreviewReplaceValues = function (editor) {
  46. return editor.getParam('template_preview_replace_values');
  47. };
  48. var getTemplateReplaceValues = function (editor) {
  49. return editor.getParam('template_replace_values');
  50. };
  51. var getTemplates = function (editorSettings) {
  52. return editorSettings.templates;
  53. };
  54. var getCdateFormat = function (editor) {
  55. return editor.getParam('template_cdate_format', editor.translate('%Y-%m-%d'));
  56. };
  57. var getMdateFormat = function (editor) {
  58. return editor.getParam('template_mdate_format', editor.translate('%Y-%m-%d'));
  59. };
  60. var Settings = {
  61. getCreationDateClasses: getCreationDateClasses,
  62. getModificationDateClasses: getModificationDateClasses,
  63. getSelectedContentClasses: getSelectedContentClasses,
  64. getPreviewReplaceValues: getPreviewReplaceValues,
  65. getTemplateReplaceValues: getTemplateReplaceValues,
  66. getTemplates: getTemplates,
  67. getCdateFormat: getCdateFormat,
  68. getMdateFormat: getMdateFormat
  69. };
  70. var addZeros = function (value, len) {
  71. value = '' + value;
  72. if (value.length < len) {
  73. for (var i = 0; i < len - value.length; i++) {
  74. value = '0' + value;
  75. }
  76. }
  77. return value;
  78. };
  79. var getDateTime = function (editor, fmt, date) {
  80. var daysShort = 'Sun Mon Tue Wed Thu Fri Sat Sun'.split(' ');
  81. var daysLong = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday'.split(' ');
  82. var monthsShort = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' ');
  83. var monthsLong = 'January February March April May June July August September October November December'.split(' ');
  84. date = date || new Date();
  85. fmt = fmt.replace('%D', '%m/%d/%Y');
  86. fmt = fmt.replace('%r', '%I:%M:%S %p');
  87. fmt = fmt.replace('%Y', '' + date.getFullYear());
  88. fmt = fmt.replace('%y', '' + date.getYear());
  89. fmt = fmt.replace('%m', addZeros(date.getMonth() + 1, 2));
  90. fmt = fmt.replace('%d', addZeros(date.getDate(), 2));
  91. fmt = fmt.replace('%H', '' + addZeros(date.getHours(), 2));
  92. fmt = fmt.replace('%M', '' + addZeros(date.getMinutes(), 2));
  93. fmt = fmt.replace('%S', '' + addZeros(date.getSeconds(), 2));
  94. fmt = fmt.replace('%I', '' + ((date.getHours() + 11) % 12 + 1));
  95. fmt = fmt.replace('%p', '' + (date.getHours() < 12 ? 'AM' : 'PM'));
  96. fmt = fmt.replace('%B', '' + editor.translate(monthsLong[date.getMonth()]));
  97. fmt = fmt.replace('%b', '' + editor.translate(monthsShort[date.getMonth()]));
  98. fmt = fmt.replace('%A', '' + editor.translate(daysLong[date.getDay()]));
  99. fmt = fmt.replace('%a', '' + editor.translate(daysShort[date.getDay()]));
  100. fmt = fmt.replace('%%', '%');
  101. return fmt;
  102. };
  103. var DateTimeHelper = { getDateTime: getDateTime };
  104. var createTemplateList = function (editorSettings, callback) {
  105. return function () {
  106. var templateList = Settings.getTemplates(editorSettings);
  107. if (typeof templateList === 'function') {
  108. templateList(callback);
  109. return;
  110. }
  111. if (typeof templateList === 'string') {
  112. global$2.send({
  113. url: templateList,
  114. success: function (text) {
  115. callback(JSON.parse(text));
  116. }
  117. });
  118. } else {
  119. callback(templateList);
  120. }
  121. };
  122. };
  123. var replaceTemplateValues = function (html, templateValues) {
  124. global$1.each(templateValues, function (v, k) {
  125. if (typeof v === 'function') {
  126. v = v(k);
  127. }
  128. html = html.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v);
  129. });
  130. return html;
  131. };
  132. var replaceVals = function (editor, e) {
  133. var dom = editor.dom, vl = Settings.getTemplateReplaceValues(editor);
  134. global$1.each(dom.select('*', e), function (e) {
  135. global$1.each(vl, function (v, k) {
  136. if (dom.hasClass(e, k)) {
  137. if (typeof vl[k] === 'function') {
  138. vl[k](e);
  139. }
  140. }
  141. });
  142. });
  143. };
  144. var hasClass = function (n, c) {
  145. return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
  146. };
  147. var insertTemplate = function (editor, ui, html) {
  148. var el;
  149. var n;
  150. var dom = editor.dom;
  151. var sel = editor.selection.getContent();
  152. html = replaceTemplateValues(html, Settings.getTemplateReplaceValues(editor));
  153. el = dom.create('div', null, html);
  154. n = dom.select('.mceTmpl', el);
  155. if (n && n.length > 0) {
  156. el = dom.create('div', null);
  157. el.appendChild(n[0].cloneNode(true));
  158. }
  159. global$1.each(dom.select('*', el), function (n) {
  160. if (hasClass(n, Settings.getCreationDateClasses(editor).replace(/\s+/g, '|'))) {
  161. n.innerHTML = DateTimeHelper.getDateTime(editor, Settings.getCdateFormat(editor));
  162. }
  163. if (hasClass(n, Settings.getModificationDateClasses(editor).replace(/\s+/g, '|'))) {
  164. n.innerHTML = DateTimeHelper.getDateTime(editor, Settings.getMdateFormat(editor));
  165. }
  166. if (hasClass(n, Settings.getSelectedContentClasses(editor).replace(/\s+/g, '|'))) {
  167. n.innerHTML = sel;
  168. }
  169. });
  170. replaceVals(editor, el);
  171. editor.execCommand('mceInsertContent', false, el.innerHTML);
  172. editor.addVisual();
  173. };
  174. var Templates = {
  175. createTemplateList: createTemplateList,
  176. replaceTemplateValues: replaceTemplateValues,
  177. replaceVals: replaceVals,
  178. insertTemplate: insertTemplate
  179. };
  180. var register = function (editor) {
  181. editor.addCommand('mceInsertTemplate', curry(Templates.insertTemplate, editor));
  182. };
  183. var Commands = { register: register };
  184. var setup = function (editor) {
  185. editor.on('PreProcess', function (o) {
  186. var dom = editor.dom, dateFormat = Settings.getMdateFormat(editor);
  187. global$1.each(dom.select('div', o.node), function (e) {
  188. if (dom.hasClass(e, 'mceTmpl')) {
  189. global$1.each(dom.select('*', e), function (e) {
  190. if (dom.hasClass(e, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) {
  191. e.innerHTML = DateTimeHelper.getDateTime(editor, dateFormat);
  192. }
  193. });
  194. Templates.replaceVals(editor, e);
  195. }
  196. });
  197. });
  198. };
  199. var FilterContent = { setup: setup };
  200. var never$1 = never;
  201. var always$1 = always;
  202. var none = function () {
  203. return NONE;
  204. };
  205. var NONE = function () {
  206. var eq = function (o) {
  207. return o.isNone();
  208. };
  209. var call = function (thunk) {
  210. return thunk();
  211. };
  212. var id = function (n) {
  213. return n;
  214. };
  215. var noop = function () {
  216. };
  217. var nul = function () {
  218. return null;
  219. };
  220. var undef = function () {
  221. return undefined;
  222. };
  223. var me = {
  224. fold: function (n, s) {
  225. return n();
  226. },
  227. is: never$1,
  228. isSome: never$1,
  229. isNone: always$1,
  230. getOr: id,
  231. getOrThunk: call,
  232. getOrDie: function (msg) {
  233. throw new Error(msg || 'error: getOrDie called on none.');
  234. },
  235. getOrNull: nul,
  236. getOrUndefined: undef,
  237. or: id,
  238. orThunk: call,
  239. map: none,
  240. ap: none,
  241. each: noop,
  242. bind: none,
  243. flatten: none,
  244. exists: never$1,
  245. forall: always$1,
  246. filter: none,
  247. equals: eq,
  248. equals_: eq,
  249. toArray: function () {
  250. return [];
  251. },
  252. toString: constant('none()')
  253. };
  254. if (Object.freeze)
  255. Object.freeze(me);
  256. return me;
  257. }();
  258. var some = function (a) {
  259. var constant_a = function () {
  260. return a;
  261. };
  262. var self = function () {
  263. return me;
  264. };
  265. var map = function (f) {
  266. return some(f(a));
  267. };
  268. var bind = function (f) {
  269. return f(a);
  270. };
  271. var me = {
  272. fold: function (n, s) {
  273. return s(a);
  274. },
  275. is: function (v) {
  276. return a === v;
  277. },
  278. isSome: always$1,
  279. isNone: never$1,
  280. getOr: constant_a,
  281. getOrThunk: constant_a,
  282. getOrDie: constant_a,
  283. getOrNull: constant_a,
  284. getOrUndefined: constant_a,
  285. or: self,
  286. orThunk: self,
  287. map: map,
  288. ap: function (optfab) {
  289. return optfab.fold(none, function (fab) {
  290. return some(fab(a));
  291. });
  292. },
  293. each: function (f) {
  294. f(a);
  295. },
  296. bind: bind,
  297. flatten: constant_a,
  298. exists: bind,
  299. forall: bind,
  300. filter: function (f) {
  301. return f(a) ? me : NONE;
  302. },
  303. equals: function (o) {
  304. return o.is(a);
  305. },
  306. equals_: function (o, elementEq) {
  307. return o.fold(never$1, function (b) {
  308. return elementEq(a, b);
  309. });
  310. },
  311. toArray: function () {
  312. return [a];
  313. },
  314. toString: function () {
  315. return 'some(' + a + ')';
  316. }
  317. };
  318. return me;
  319. };
  320. var from = function (value) {
  321. return value === null || value === undefined ? NONE : some(value);
  322. };
  323. var Option = {
  324. some: some,
  325. none: none,
  326. from: from
  327. };
  328. var typeOf = function (x) {
  329. if (x === null)
  330. return 'null';
  331. var t = typeof x;
  332. if (t === 'object' && Array.prototype.isPrototypeOf(x))
  333. return 'array';
  334. if (t === 'object' && String.prototype.isPrototypeOf(x))
  335. return 'string';
  336. return t;
  337. };
  338. var isType = function (type) {
  339. return function (value) {
  340. return typeOf(value) === type;
  341. };
  342. };
  343. var isFunction = isType('function');
  344. var slice = Array.prototype.slice;
  345. var map = function (xs, f) {
  346. var len = xs.length;
  347. var r = new Array(len);
  348. for (var i = 0; i < len; i++) {
  349. var x = xs[i];
  350. r[i] = f(x, i, xs);
  351. }
  352. return r;
  353. };
  354. var find = function (xs, pred) {
  355. for (var i = 0, len = xs.length; i < len; i++) {
  356. var x = xs[i];
  357. if (pred(x, i, xs)) {
  358. return Option.some(x);
  359. }
  360. }
  361. return Option.none();
  362. };
  363. var from$1 = isFunction(Array.from) ? Array.from : function (x) {
  364. return slice.call(x);
  365. };
  366. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise');
  367. var hasOwnProperty = Object.hasOwnProperty;
  368. var get = function (obj, key) {
  369. return has(obj, key) ? Option.from(obj[key]) : Option.none();
  370. };
  371. var has = function (obj, key) {
  372. return hasOwnProperty.call(obj, key);
  373. };
  374. var entitiesAttr = {
  375. '"': '&quot;',
  376. '<': '&lt;',
  377. '>': '&gt;',
  378. '&': '&amp;',
  379. '\'': '&#039;'
  380. };
  381. var htmlEscape = function (html) {
  382. return html.replace(/["'<>&]/g, function (match) {
  383. return get(entitiesAttr, match).getOr(match);
  384. });
  385. };
  386. var getPreviewContent = function (editor, html) {
  387. if (html.indexOf('<html>') === -1) {
  388. var contentCssLinks_1 = '';
  389. global$1.each(editor.contentCSS, function (url) {
  390. contentCssLinks_1 += '<link type="text/css" rel="stylesheet" href="' + editor.documentBaseURI.toAbsolute(url) + '">';
  391. });
  392. var bodyClass = editor.settings.body_class || '';
  393. if (bodyClass.indexOf('=') !== -1) {
  394. bodyClass = editor.getParam('body_class', '', 'hash');
  395. bodyClass = bodyClass[editor.id] || '';
  396. }
  397. var encode = editor.dom.encode;
  398. var directionality = editor.getBody().dir;
  399. var dirAttr = directionality ? ' dir="' + encode(directionality) + '"' : '';
  400. html = '<!DOCTYPE html>' + '<html>' + '<head>' + contentCssLinks_1 + '</head>' + '<body class="' + encode(bodyClass) + '"' + dirAttr + '>' + html + '</body>' + '</html>';
  401. }
  402. return Templates.replaceTemplateValues(html, Settings.getPreviewReplaceValues(editor));
  403. };
  404. var open = function (editor, templateList) {
  405. var createTemplates = function () {
  406. if (!templateList || templateList.length === 0) {
  407. var message = editor.translate('No templates defined.');
  408. editor.notificationManager.open({
  409. text: message,
  410. type: 'info'
  411. });
  412. return Option.none();
  413. }
  414. return Option.from(global$1.map(templateList, function (template, index) {
  415. return {
  416. selected: index === 0,
  417. text: template.title,
  418. value: {
  419. url: template.url,
  420. content: template.content,
  421. description: template.description
  422. }
  423. };
  424. }));
  425. };
  426. var createSelectBoxItems = function (templates) {
  427. return map(templates, function (v) {
  428. return {
  429. text: v.text,
  430. value: v.text
  431. };
  432. });
  433. };
  434. var findTemplate = function (templates, templateTitle) {
  435. return find(templates, function (t) {
  436. return t.text === templateTitle;
  437. });
  438. };
  439. var getTemplateContent = function (t) {
  440. return new global$3(function (resolve, reject) {
  441. if (t.value.url) {
  442. global$2.send({
  443. url: t.value.url,
  444. success: function (html) {
  445. resolve(html);
  446. },
  447. error: function (e) {
  448. reject(e);
  449. }
  450. });
  451. } else {
  452. resolve(t.value.content);
  453. }
  454. });
  455. };
  456. var onChange = function (templates, updateDialog) {
  457. return function (api, change) {
  458. if (change.name === 'template') {
  459. var newTemplateTitle = api.getData().template;
  460. findTemplate(templates, newTemplateTitle).each(function (t) {
  461. api.block('Loading...');
  462. getTemplateContent(t).then(function (previewHtml) {
  463. updateDialog(api, t, previewHtml);
  464. api.unblock();
  465. });
  466. });
  467. }
  468. };
  469. };
  470. var onSubmit = function (templates) {
  471. return function (api) {
  472. var data = api.getData();
  473. findTemplate(templates, data.template).each(function (t) {
  474. getTemplateContent(t).then(function (previewHtml) {
  475. Templates.insertTemplate(editor, false, previewHtml);
  476. api.close();
  477. });
  478. });
  479. };
  480. };
  481. var openDialog = function (templates) {
  482. var selectBoxItems = createSelectBoxItems(templates);
  483. var buildDialogSpec = function (bodyItems, initialData) {
  484. return {
  485. title: 'Insert Template',
  486. size: 'large',
  487. body: {
  488. type: 'panel',
  489. items: bodyItems
  490. },
  491. initialData: initialData,
  492. buttons: [
  493. {
  494. type: 'cancel',
  495. name: 'cancel',
  496. text: 'Cancel'
  497. },
  498. {
  499. type: 'submit',
  500. name: 'save',
  501. text: 'Save',
  502. primary: true
  503. }
  504. ],
  505. onSubmit: onSubmit(templates),
  506. onChange: onChange(templates, updateDialog)
  507. };
  508. };
  509. var updateDialog = function (dialogApi, template, previewHtml) {
  510. var content = getPreviewContent(editor, previewHtml);
  511. var bodyItems = [
  512. {
  513. type: 'selectbox',
  514. name: 'template',
  515. label: 'Templates',
  516. items: selectBoxItems
  517. },
  518. {
  519. type: 'htmlpanel',
  520. html: '<p aria-live="polite">' + htmlEscape(template.value.description) + '</p>'
  521. },
  522. {
  523. label: 'Preview',
  524. type: 'iframe',
  525. name: 'preview',
  526. sandboxed: false
  527. }
  528. ];
  529. var initialData = {
  530. template: template.text,
  531. preview: content
  532. };
  533. dialogApi.unblock();
  534. dialogApi.redial(buildDialogSpec(bodyItems, initialData));
  535. dialogApi.focus('template');
  536. };
  537. var dialogApi = editor.windowManager.open(buildDialogSpec([], {
  538. template: '',
  539. preview: ''
  540. }));
  541. dialogApi.block('Loading...');
  542. getTemplateContent(templates[0]).then(function (previewHtml) {
  543. updateDialog(dialogApi, templates[0], previewHtml);
  544. });
  545. };
  546. var optTemplates = createTemplates();
  547. optTemplates.each(openDialog);
  548. };
  549. var Dialog = { open: open };
  550. var showDialog = function (editor) {
  551. return function (templates) {
  552. Dialog.open(editor, templates);
  553. };
  554. };
  555. var register$1 = function (editor) {
  556. editor.ui.registry.addButton('template', {
  557. icon: 'template',
  558. tooltip: 'Insert template',
  559. onAction: Templates.createTemplateList(editor.settings, showDialog(editor))
  560. });
  561. editor.ui.registry.addMenuItem('template', {
  562. icon: 'template',
  563. text: 'Insert template...',
  564. onAction: Templates.createTemplateList(editor.settings, showDialog(editor))
  565. });
  566. };
  567. var Buttons = { register: register$1 };
  568. global.add('template', function (editor) {
  569. Buttons.register(editor);
  570. Commands.register(editor);
  571. FilterContent.setup(editor);
  572. });
  573. function Plugin () {
  574. }
  575. return Plugin;
  576. }());
  577. })();