plugin.js 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842
  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.2.0 (2020-02-13)
  8. */
  9. (function (domGlobals) {
  10. 'use strict';
  11. var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');
  12. var global$2 = tinymce.util.Tools.resolve('tinymce.util.VK');
  13. var typeOf = function (x) {
  14. if (x === null) {
  15. return 'null';
  16. }
  17. var t = typeof x;
  18. if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
  19. return 'array';
  20. }
  21. if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
  22. return 'string';
  23. }
  24. return t;
  25. };
  26. var isType = function (type) {
  27. return function (value) {
  28. return typeOf(value) === type;
  29. };
  30. };
  31. var isString = isType('string');
  32. var isArray = isType('array');
  33. var isBoolean = isType('boolean');
  34. var isFunction = isType('function');
  35. var assumeExternalTargets = function (editor) {
  36. var externalTargets = editor.getParam('link_assume_external_targets', false);
  37. if (isBoolean(externalTargets) && externalTargets) {
  38. return 1;
  39. } else if (isString(externalTargets) && (externalTargets === 'http' || externalTargets === 'https')) {
  40. return externalTargets;
  41. }
  42. return 0;
  43. };
  44. var hasContextToolbar = function (editor) {
  45. return editor.getParam('link_context_toolbar', false, 'boolean');
  46. };
  47. var getLinkList = function (editor) {
  48. return editor.getParam('link_list');
  49. };
  50. var getDefaultLinkTarget = function (editor) {
  51. return editor.getParam('default_link_target');
  52. };
  53. var getTargetList = function (editor) {
  54. return editor.getParam('target_list', true);
  55. };
  56. var getRelList = function (editor) {
  57. return editor.getParam('rel_list', [], 'array');
  58. };
  59. var getLinkClassList = function (editor) {
  60. return editor.getParam('link_class_list', [], 'array');
  61. };
  62. var shouldShowLinkTitle = function (editor) {
  63. return editor.getParam('link_title', true, 'boolean');
  64. };
  65. var allowUnsafeLinkTarget = function (editor) {
  66. return editor.getParam('allow_unsafe_link_target', false, 'boolean');
  67. };
  68. var useQuickLink = function (editor) {
  69. return editor.getParam('link_quicklink', false, 'boolean');
  70. };
  71. var getDefaultLinkProtocol = function (editor) {
  72. return editor.getParam('link_default_protocol', 'http', 'string');
  73. };
  74. var Settings = {
  75. assumeExternalTargets: assumeExternalTargets,
  76. hasContextToolbar: hasContextToolbar,
  77. getLinkList: getLinkList,
  78. getDefaultLinkTarget: getDefaultLinkTarget,
  79. getTargetList: getTargetList,
  80. getRelList: getRelList,
  81. getLinkClassList: getLinkClassList,
  82. shouldShowLinkTitle: shouldShowLinkTitle,
  83. allowUnsafeLinkTarget: allowUnsafeLinkTarget,
  84. useQuickLink: useQuickLink,
  85. getDefaultLinkProtocol: getDefaultLinkProtocol
  86. };
  87. var appendClickRemove = function (link, evt) {
  88. domGlobals.document.body.appendChild(link);
  89. link.dispatchEvent(evt);
  90. domGlobals.document.body.removeChild(link);
  91. };
  92. var open = function (url) {
  93. var link = domGlobals.document.createElement('a');
  94. link.target = '_blank';
  95. link.href = url;
  96. link.rel = 'noreferrer noopener';
  97. var evt = domGlobals.document.createEvent('MouseEvents');
  98. evt.initMouseEvent('click', true, true, domGlobals.window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  99. appendClickRemove(link, evt);
  100. };
  101. var OpenUrl = { open: open };
  102. var __assign = function () {
  103. __assign = Object.assign || function __assign(t) {
  104. for (var s, i = 1, n = arguments.length; i < n; i++) {
  105. s = arguments[i];
  106. for (var p in s)
  107. if (Object.prototype.hasOwnProperty.call(s, p))
  108. t[p] = s[p];
  109. }
  110. return t;
  111. };
  112. return __assign.apply(this, arguments);
  113. };
  114. var noop = function () {
  115. };
  116. var constant = function (value) {
  117. return function () {
  118. return value;
  119. };
  120. };
  121. var never = constant(false);
  122. var always = constant(true);
  123. var none = function () {
  124. return NONE;
  125. };
  126. var NONE = function () {
  127. var eq = function (o) {
  128. return o.isNone();
  129. };
  130. var call = function (thunk) {
  131. return thunk();
  132. };
  133. var id = function (n) {
  134. return n;
  135. };
  136. var me = {
  137. fold: function (n, s) {
  138. return n();
  139. },
  140. is: never,
  141. isSome: never,
  142. isNone: always,
  143. getOr: id,
  144. getOrThunk: call,
  145. getOrDie: function (msg) {
  146. throw new Error(msg || 'error: getOrDie called on none.');
  147. },
  148. getOrNull: constant(null),
  149. getOrUndefined: constant(undefined),
  150. or: id,
  151. orThunk: call,
  152. map: none,
  153. each: noop,
  154. bind: none,
  155. exists: never,
  156. forall: always,
  157. filter: none,
  158. equals: eq,
  159. equals_: eq,
  160. toArray: function () {
  161. return [];
  162. },
  163. toString: constant('none()')
  164. };
  165. if (Object.freeze) {
  166. Object.freeze(me);
  167. }
  168. return me;
  169. }();
  170. var some = function (a) {
  171. var constant_a = constant(a);
  172. var self = function () {
  173. return me;
  174. };
  175. var bind = function (f) {
  176. return f(a);
  177. };
  178. var me = {
  179. fold: function (n, s) {
  180. return s(a);
  181. },
  182. is: function (v) {
  183. return a === v;
  184. },
  185. isSome: always,
  186. isNone: never,
  187. getOr: constant_a,
  188. getOrThunk: constant_a,
  189. getOrDie: constant_a,
  190. getOrNull: constant_a,
  191. getOrUndefined: constant_a,
  192. or: self,
  193. orThunk: self,
  194. map: function (f) {
  195. return some(f(a));
  196. },
  197. each: function (f) {
  198. f(a);
  199. },
  200. bind: bind,
  201. exists: bind,
  202. forall: bind,
  203. filter: function (f) {
  204. return f(a) ? me : NONE;
  205. },
  206. toArray: function () {
  207. return [a];
  208. },
  209. toString: function () {
  210. return 'some(' + a + ')';
  211. },
  212. equals: function (o) {
  213. return o.is(a);
  214. },
  215. equals_: function (o, elementEq) {
  216. return o.fold(never, function (b) {
  217. return elementEq(a, b);
  218. });
  219. }
  220. };
  221. return me;
  222. };
  223. var from = function (value) {
  224. return value === null || value === undefined ? NONE : some(value);
  225. };
  226. var Option = {
  227. some: some,
  228. none: none,
  229. from: from
  230. };
  231. var nativeSlice = Array.prototype.slice;
  232. var nativeIndexOf = Array.prototype.indexOf;
  233. var nativePush = Array.prototype.push;
  234. var rawIndexOf = function (ts, t) {
  235. return nativeIndexOf.call(ts, t);
  236. };
  237. var contains = function (xs, x) {
  238. return rawIndexOf(xs, x) > -1;
  239. };
  240. var map = function (xs, f) {
  241. var len = xs.length;
  242. var r = new Array(len);
  243. for (var i = 0; i < len; i++) {
  244. var x = xs[i];
  245. r[i] = f(x, i);
  246. }
  247. return r;
  248. };
  249. var each = function (xs, f) {
  250. for (var i = 0, len = xs.length; i < len; i++) {
  251. var x = xs[i];
  252. f(x, i);
  253. }
  254. };
  255. var foldl = function (xs, f, acc) {
  256. each(xs, function (x) {
  257. acc = f(acc, x);
  258. });
  259. return acc;
  260. };
  261. var flatten = function (xs) {
  262. var r = [];
  263. for (var i = 0, len = xs.length; i < len; ++i) {
  264. if (!isArray(xs[i])) {
  265. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  266. }
  267. nativePush.apply(r, xs[i]);
  268. }
  269. return r;
  270. };
  271. var bind = function (xs, f) {
  272. return flatten(map(xs, f));
  273. };
  274. var from$1 = isFunction(Array.from) ? Array.from : function (x) {
  275. return nativeSlice.call(x);
  276. };
  277. var findMap = function (arr, f) {
  278. for (var i = 0; i < arr.length; i++) {
  279. var r = f(arr[i], i);
  280. if (r.isSome()) {
  281. return r;
  282. }
  283. }
  284. return Option.none();
  285. };
  286. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools');
  287. var hasProtocol = function (url) {
  288. return /^\w+:/i.test(url);
  289. };
  290. var getHref = function (elm) {
  291. var href = elm.getAttribute('data-mce-href');
  292. return href ? href : elm.getAttribute('href');
  293. };
  294. var applyRelTargetRules = function (rel, isUnsafe) {
  295. var rules = ['noopener'];
  296. var rels = rel ? rel.split(/\s+/) : [];
  297. var toString = function (rels) {
  298. return global$3.trim(rels.sort().join(' '));
  299. };
  300. var addTargetRules = function (rels) {
  301. rels = removeTargetRules(rels);
  302. return rels.length > 0 ? rels.concat(rules) : rules;
  303. };
  304. var removeTargetRules = function (rels) {
  305. return rels.filter(function (val) {
  306. return global$3.inArray(rules, val) === -1;
  307. });
  308. };
  309. var newRels = isUnsafe ? addTargetRules(rels) : removeTargetRules(rels);
  310. return newRels.length > 0 ? toString(newRels) : '';
  311. };
  312. var trimCaretContainers = function (text) {
  313. return text.replace(/\uFEFF/g, '');
  314. };
  315. var getAnchorElement = function (editor, selectedElm) {
  316. selectedElm = selectedElm || editor.selection.getNode();
  317. if (isImageFigure(selectedElm)) {
  318. return editor.dom.select('a[href]', selectedElm)[0];
  319. } else {
  320. return editor.dom.getParent(selectedElm, 'a[href]');
  321. }
  322. };
  323. var getAnchorText = function (selection, anchorElm) {
  324. var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' });
  325. return trimCaretContainers(text);
  326. };
  327. var isLink = function (elm) {
  328. return elm && elm.nodeName === 'A' && !!elm.href;
  329. };
  330. var hasLinks = function (elements) {
  331. return global$3.grep(elements, isLink).length > 0;
  332. };
  333. var isOnlyTextSelected = function (html) {
  334. if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') === -1)) {
  335. return false;
  336. }
  337. return true;
  338. };
  339. var isImageFigure = function (elm) {
  340. return elm && elm.nodeName === 'FIGURE' && /\bimage\b/i.test(elm.className);
  341. };
  342. var getLinkAttrs = function (data) {
  343. return foldl([
  344. 'title',
  345. 'rel',
  346. 'class',
  347. 'target'
  348. ], function (acc, key) {
  349. data[key].each(function (value) {
  350. acc[key] = value.length > 0 ? value : null;
  351. });
  352. return acc;
  353. }, { href: data.href });
  354. };
  355. var handleExternalTargets = function (href, assumeExternalTargets) {
  356. if ((assumeExternalTargets === 'http' || assumeExternalTargets === 'https') && !hasProtocol(href)) {
  357. return assumeExternalTargets + '://' + href;
  358. }
  359. return href;
  360. };
  361. var applyLinkOverrides = function (editor, linkAttrs) {
  362. var newLinkAttrs = __assign({}, linkAttrs);
  363. if (!(Settings.getRelList(editor).length > 0) && Settings.allowUnsafeLinkTarget(editor) === false) {
  364. var newRel = applyRelTargetRules(newLinkAttrs.rel, newLinkAttrs.target === '_blank');
  365. newLinkAttrs.rel = newRel ? newRel : null;
  366. }
  367. if (Option.from(newLinkAttrs.target).isNone() && Settings.getTargetList(editor) === false) {
  368. newLinkAttrs.target = Settings.getDefaultLinkTarget(editor);
  369. }
  370. newLinkAttrs.href = handleExternalTargets(newLinkAttrs.href, Settings.assumeExternalTargets(editor));
  371. return newLinkAttrs;
  372. };
  373. var updateLink = function (editor, anchorElm, text, linkAttrs) {
  374. text.each(function (text) {
  375. if (anchorElm.hasOwnProperty('innerText')) {
  376. anchorElm.innerText = text;
  377. } else {
  378. anchorElm.textContent = text;
  379. }
  380. });
  381. editor.dom.setAttribs(anchorElm, linkAttrs);
  382. editor.selection.select(anchorElm);
  383. };
  384. var createLink = function (editor, selectedElm, text, linkAttrs) {
  385. if (isImageFigure(selectedElm)) {
  386. linkImageFigure(editor, selectedElm, linkAttrs);
  387. } else {
  388. text.fold(function () {
  389. editor.execCommand('mceInsertLink', false, linkAttrs);
  390. }, function (text) {
  391. editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(text)));
  392. });
  393. }
  394. };
  395. var link = function (editor, attachState, data) {
  396. var selectedElm = editor.selection.getNode();
  397. var anchorElm = getAnchorElement(editor, selectedElm);
  398. var linkAttrs = applyLinkOverrides(editor, getLinkAttrs(data));
  399. editor.undoManager.transact(function () {
  400. if (data.href === attachState.href) {
  401. attachState.attach();
  402. }
  403. if (anchorElm) {
  404. editor.focus();
  405. updateLink(editor, anchorElm, data.text, linkAttrs);
  406. } else {
  407. createLink(editor, selectedElm, data.text, linkAttrs);
  408. }
  409. });
  410. };
  411. var unlink = function (editor) {
  412. editor.undoManager.transact(function () {
  413. var node = editor.selection.getNode();
  414. if (isImageFigure(node)) {
  415. unlinkImageFigure(editor, node);
  416. } else {
  417. var anchorElm = editor.dom.getParent(node, 'a[href]', editor.getBody());
  418. if (anchorElm) {
  419. editor.dom.remove(anchorElm, true);
  420. }
  421. }
  422. editor.focus();
  423. });
  424. };
  425. var unlinkImageFigure = function (editor, fig) {
  426. var img = editor.dom.select('img', fig)[0];
  427. if (img) {
  428. var a = editor.dom.getParents(img, 'a[href]', fig)[0];
  429. if (a) {
  430. a.parentNode.insertBefore(img, a);
  431. editor.dom.remove(a);
  432. }
  433. }
  434. };
  435. var linkImageFigure = function (editor, fig, attrs) {
  436. var img = editor.dom.select('img', fig)[0];
  437. if (img) {
  438. var a = editor.dom.create('a', attrs);
  439. img.parentNode.insertBefore(a, img);
  440. a.appendChild(img);
  441. }
  442. };
  443. var Utils = {
  444. link: link,
  445. unlink: unlink,
  446. isLink: isLink,
  447. hasLinks: hasLinks,
  448. getHref: getHref,
  449. isOnlyTextSelected: isOnlyTextSelected,
  450. getAnchorElement: getAnchorElement,
  451. getAnchorText: getAnchorText,
  452. applyRelTargetRules: applyRelTargetRules,
  453. hasProtocol: hasProtocol
  454. };
  455. var cat = function (arr) {
  456. var r = [];
  457. var push = function (x) {
  458. r.push(x);
  459. };
  460. for (var i = 0; i < arr.length; i++) {
  461. arr[i].each(push);
  462. }
  463. return r;
  464. };
  465. var getValue = function (item) {
  466. return isString(item.value) ? item.value : '';
  467. };
  468. var sanitizeList = function (list, extractValue) {
  469. var out = [];
  470. global$3.each(list, function (item) {
  471. var text = isString(item.text) ? item.text : isString(item.title) ? item.title : '';
  472. if (item.menu !== undefined) ; else {
  473. var value = extractValue(item);
  474. out.push({
  475. text: text,
  476. value: value
  477. });
  478. }
  479. });
  480. return out;
  481. };
  482. var sanitizeWith = function (extracter) {
  483. if (extracter === void 0) {
  484. extracter = getValue;
  485. }
  486. return function (list) {
  487. return Option.from(list).map(function (list) {
  488. return sanitizeList(list, extracter);
  489. });
  490. };
  491. };
  492. var sanitize = function (list) {
  493. return sanitizeWith(getValue)(list);
  494. };
  495. var createUi = function (name, label) {
  496. return function (items) {
  497. return {
  498. name: name,
  499. type: 'selectbox',
  500. label: label,
  501. items: items
  502. };
  503. };
  504. };
  505. var ListOptions = {
  506. sanitize: sanitize,
  507. sanitizeWith: sanitizeWith,
  508. createUi: createUi,
  509. getValue: getValue
  510. };
  511. var Cell = function (initial) {
  512. var value = initial;
  513. var get = function () {
  514. return value;
  515. };
  516. var set = function (v) {
  517. value = v;
  518. };
  519. var clone = function () {
  520. return Cell(get());
  521. };
  522. return {
  523. get: get,
  524. set: set,
  525. clone: clone
  526. };
  527. };
  528. var findTextByValue = function (value, catalog) {
  529. return findMap(catalog, function (item) {
  530. return Option.some(item).filter(function (i) {
  531. return i.value === value;
  532. });
  533. });
  534. };
  535. var getDelta = function (persistentText, fieldName, catalog, data) {
  536. var value = data[fieldName];
  537. var hasPersistentText = persistentText.length > 0;
  538. return value !== undefined ? findTextByValue(value, catalog).map(function (i) {
  539. return {
  540. url: {
  541. value: i.value,
  542. meta: {
  543. text: hasPersistentText ? persistentText : i.text,
  544. attach: noop
  545. }
  546. },
  547. text: hasPersistentText ? persistentText : i.text
  548. };
  549. }) : Option.none();
  550. };
  551. var findCatalog = function (settings, fieldName) {
  552. if (fieldName === 'link') {
  553. return settings.catalogs.link;
  554. } else if (fieldName === 'anchor') {
  555. return settings.catalogs.anchor;
  556. } else {
  557. return Option.none();
  558. }
  559. };
  560. var init = function (initialData, linkSettings) {
  561. var persistentText = Cell(initialData.text);
  562. var onUrlChange = function (data) {
  563. if (persistentText.get().length <= 0) {
  564. var urlText = data.url.meta.text !== undefined ? data.url.meta.text : data.url.value;
  565. var urlTitle = data.url.meta.title !== undefined ? data.url.meta.title : '';
  566. return Option.some({
  567. text: urlText,
  568. title: urlTitle
  569. });
  570. } else {
  571. return Option.none();
  572. }
  573. };
  574. var onCatalogChange = function (data, change) {
  575. var catalog = findCatalog(linkSettings, change.name).getOr([]);
  576. return getDelta(persistentText.get(), change.name, catalog, data);
  577. };
  578. var onChange = function (getData, change) {
  579. if (change.name === 'url') {
  580. return onUrlChange(getData());
  581. } else if (contains([
  582. 'anchor',
  583. 'link'
  584. ], change.name)) {
  585. return onCatalogChange(getData(), change);
  586. } else if (change.name === 'text') {
  587. persistentText.set(getData().text);
  588. return Option.none();
  589. } else {
  590. return Option.none();
  591. }
  592. };
  593. return { onChange: onChange };
  594. };
  595. var DialogChanges = {
  596. init: init,
  597. getDelta: getDelta
  598. };
  599. var exports$1 = {}, module = { exports: exports$1 };
  600. (function (define, exports, module, require) {
  601. (function (f) {
  602. if (typeof exports === 'object' && typeof module !== 'undefined') {
  603. module.exports = f();
  604. } else if (typeof define === 'function' && define.amd) {
  605. define([], f);
  606. } else {
  607. var g;
  608. if (typeof window !== 'undefined') {
  609. g = window;
  610. } else if (typeof global !== 'undefined') {
  611. g = global;
  612. } else if (typeof self !== 'undefined') {
  613. g = self;
  614. } else {
  615. g = this;
  616. }
  617. g.EphoxContactWrapper = f();
  618. }
  619. }(function () {
  620. return function () {
  621. function r(e, n, t) {
  622. function o(i, f) {
  623. if (!n[i]) {
  624. if (!e[i]) {
  625. var c = 'function' == typeof require && require;
  626. if (!f && c)
  627. return c(i, !0);
  628. if (u)
  629. return u(i, !0);
  630. var a = new Error('Cannot find module \'' + i + '\'');
  631. throw a.code = 'MODULE_NOT_FOUND', a;
  632. }
  633. var p = n[i] = { exports: {} };
  634. e[i][0].call(p.exports, function (r) {
  635. var n = e[i][1][r];
  636. return o(n || r);
  637. }, p, p.exports, r, e, n, t);
  638. }
  639. return n[i].exports;
  640. }
  641. for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++)
  642. o(t[i]);
  643. return o;
  644. }
  645. return r;
  646. }()({
  647. 1: [
  648. function (require, module, exports) {
  649. var process = module.exports = {};
  650. var cachedSetTimeout;
  651. var cachedClearTimeout;
  652. function defaultSetTimout() {
  653. throw new Error('setTimeout has not been defined');
  654. }
  655. function defaultClearTimeout() {
  656. throw new Error('clearTimeout has not been defined');
  657. }
  658. (function () {
  659. try {
  660. if (typeof setTimeout === 'function') {
  661. cachedSetTimeout = setTimeout;
  662. } else {
  663. cachedSetTimeout = defaultSetTimout;
  664. }
  665. } catch (e) {
  666. cachedSetTimeout = defaultSetTimout;
  667. }
  668. try {
  669. if (typeof clearTimeout === 'function') {
  670. cachedClearTimeout = clearTimeout;
  671. } else {
  672. cachedClearTimeout = defaultClearTimeout;
  673. }
  674. } catch (e) {
  675. cachedClearTimeout = defaultClearTimeout;
  676. }
  677. }());
  678. function runTimeout(fun) {
  679. if (cachedSetTimeout === setTimeout) {
  680. return setTimeout(fun, 0);
  681. }
  682. if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
  683. cachedSetTimeout = setTimeout;
  684. return setTimeout(fun, 0);
  685. }
  686. try {
  687. return cachedSetTimeout(fun, 0);
  688. } catch (e) {
  689. try {
  690. return cachedSetTimeout.call(null, fun, 0);
  691. } catch (e) {
  692. return cachedSetTimeout.call(this, fun, 0);
  693. }
  694. }
  695. }
  696. function runClearTimeout(marker) {
  697. if (cachedClearTimeout === clearTimeout) {
  698. return clearTimeout(marker);
  699. }
  700. if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
  701. cachedClearTimeout = clearTimeout;
  702. return clearTimeout(marker);
  703. }
  704. try {
  705. return cachedClearTimeout(marker);
  706. } catch (e) {
  707. try {
  708. return cachedClearTimeout.call(null, marker);
  709. } catch (e) {
  710. return cachedClearTimeout.call(this, marker);
  711. }
  712. }
  713. }
  714. var queue = [];
  715. var draining = false;
  716. var currentQueue;
  717. var queueIndex = -1;
  718. function cleanUpNextTick() {
  719. if (!draining || !currentQueue) {
  720. return;
  721. }
  722. draining = false;
  723. if (currentQueue.length) {
  724. queue = currentQueue.concat(queue);
  725. } else {
  726. queueIndex = -1;
  727. }
  728. if (queue.length) {
  729. drainQueue();
  730. }
  731. }
  732. function drainQueue() {
  733. if (draining) {
  734. return;
  735. }
  736. var timeout = runTimeout(cleanUpNextTick);
  737. draining = true;
  738. var len = queue.length;
  739. while (len) {
  740. currentQueue = queue;
  741. queue = [];
  742. while (++queueIndex < len) {
  743. if (currentQueue) {
  744. currentQueue[queueIndex].run();
  745. }
  746. }
  747. queueIndex = -1;
  748. len = queue.length;
  749. }
  750. currentQueue = null;
  751. draining = false;
  752. runClearTimeout(timeout);
  753. }
  754. process.nextTick = function (fun) {
  755. var args = new Array(arguments.length - 1);
  756. if (arguments.length > 1) {
  757. for (var i = 1; i < arguments.length; i++) {
  758. args[i - 1] = arguments[i];
  759. }
  760. }
  761. queue.push(new Item(fun, args));
  762. if (queue.length === 1 && !draining) {
  763. runTimeout(drainQueue);
  764. }
  765. };
  766. function Item(fun, array) {
  767. this.fun = fun;
  768. this.array = array;
  769. }
  770. Item.prototype.run = function () {
  771. this.fun.apply(null, this.array);
  772. };
  773. process.title = 'browser';
  774. process.browser = true;
  775. process.env = {};
  776. process.argv = [];
  777. process.version = '';
  778. process.versions = {};
  779. function noop() {
  780. }
  781. process.on = noop;
  782. process.addListener = noop;
  783. process.once = noop;
  784. process.off = noop;
  785. process.removeListener = noop;
  786. process.removeAllListeners = noop;
  787. process.emit = noop;
  788. process.prependListener = noop;
  789. process.prependOnceListener = noop;
  790. process.listeners = function (name) {
  791. return [];
  792. };
  793. process.binding = function (name) {
  794. throw new Error('process.binding is not supported');
  795. };
  796. process.cwd = function () {
  797. return '/';
  798. };
  799. process.chdir = function (dir) {
  800. throw new Error('process.chdir is not supported');
  801. };
  802. process.umask = function () {
  803. return 0;
  804. };
  805. },
  806. {}
  807. ],
  808. 2: [
  809. function (require, module, exports) {
  810. (function (setImmediate) {
  811. (function (root) {
  812. var setTimeoutFunc = setTimeout;
  813. function noop() {
  814. }
  815. function bind(fn, thisArg) {
  816. return function () {
  817. fn.apply(thisArg, arguments);
  818. };
  819. }
  820. function Promise(fn) {
  821. if (typeof this !== 'object')
  822. throw new TypeError('Promises must be constructed via new');
  823. if (typeof fn !== 'function')
  824. throw new TypeError('not a function');
  825. this._state = 0;
  826. this._handled = false;
  827. this._value = undefined;
  828. this._deferreds = [];
  829. doResolve(fn, this);
  830. }
  831. function handle(self, deferred) {
  832. while (self._state === 3) {
  833. self = self._value;
  834. }
  835. if (self._state === 0) {
  836. self._deferreds.push(deferred);
  837. return;
  838. }
  839. self._handled = true;
  840. Promise._immediateFn(function () {
  841. var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
  842. if (cb === null) {
  843. (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
  844. return;
  845. }
  846. var ret;
  847. try {
  848. ret = cb(self._value);
  849. } catch (e) {
  850. reject(deferred.promise, e);
  851. return;
  852. }
  853. resolve(deferred.promise, ret);
  854. });
  855. }
  856. function resolve(self, newValue) {
  857. try {
  858. if (newValue === self)
  859. throw new TypeError('A promise cannot be resolved with itself.');
  860. if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
  861. var then = newValue.then;
  862. if (newValue instanceof Promise) {
  863. self._state = 3;
  864. self._value = newValue;
  865. finale(self);
  866. return;
  867. } else if (typeof then === 'function') {
  868. doResolve(bind(then, newValue), self);
  869. return;
  870. }
  871. }
  872. self._state = 1;
  873. self._value = newValue;
  874. finale(self);
  875. } catch (e) {
  876. reject(self, e);
  877. }
  878. }
  879. function reject(self, newValue) {
  880. self._state = 2;
  881. self._value = newValue;
  882. finale(self);
  883. }
  884. function finale(self) {
  885. if (self._state === 2 && self._deferreds.length === 0) {
  886. Promise._immediateFn(function () {
  887. if (!self._handled) {
  888. Promise._unhandledRejectionFn(self._value);
  889. }
  890. });
  891. }
  892. for (var i = 0, len = self._deferreds.length; i < len; i++) {
  893. handle(self, self._deferreds[i]);
  894. }
  895. self._deferreds = null;
  896. }
  897. function Handler(onFulfilled, onRejected, promise) {
  898. this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  899. this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  900. this.promise = promise;
  901. }
  902. function doResolve(fn, self) {
  903. var done = false;
  904. try {
  905. fn(function (value) {
  906. if (done)
  907. return;
  908. done = true;
  909. resolve(self, value);
  910. }, function (reason) {
  911. if (done)
  912. return;
  913. done = true;
  914. reject(self, reason);
  915. });
  916. } catch (ex) {
  917. if (done)
  918. return;
  919. done = true;
  920. reject(self, ex);
  921. }
  922. }
  923. Promise.prototype['catch'] = function (onRejected) {
  924. return this.then(null, onRejected);
  925. };
  926. Promise.prototype.then = function (onFulfilled, onRejected) {
  927. var prom = new this.constructor(noop);
  928. handle(this, new Handler(onFulfilled, onRejected, prom));
  929. return prom;
  930. };
  931. Promise.all = function (arr) {
  932. var args = Array.prototype.slice.call(arr);
  933. return new Promise(function (resolve, reject) {
  934. if (args.length === 0)
  935. return resolve([]);
  936. var remaining = args.length;
  937. function res(i, val) {
  938. try {
  939. if (val && (typeof val === 'object' || typeof val === 'function')) {
  940. var then = val.then;
  941. if (typeof then === 'function') {
  942. then.call(val, function (val) {
  943. res(i, val);
  944. }, reject);
  945. return;
  946. }
  947. }
  948. args[i] = val;
  949. if (--remaining === 0) {
  950. resolve(args);
  951. }
  952. } catch (ex) {
  953. reject(ex);
  954. }
  955. }
  956. for (var i = 0; i < args.length; i++) {
  957. res(i, args[i]);
  958. }
  959. });
  960. };
  961. Promise.resolve = function (value) {
  962. if (value && typeof value === 'object' && value.constructor === Promise) {
  963. return value;
  964. }
  965. return new Promise(function (resolve) {
  966. resolve(value);
  967. });
  968. };
  969. Promise.reject = function (value) {
  970. return new Promise(function (resolve, reject) {
  971. reject(value);
  972. });
  973. };
  974. Promise.race = function (values) {
  975. return new Promise(function (resolve, reject) {
  976. for (var i = 0, len = values.length; i < len; i++) {
  977. values[i].then(resolve, reject);
  978. }
  979. });
  980. };
  981. Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) {
  982. setImmediate(fn);
  983. } : function (fn) {
  984. setTimeoutFunc(fn, 0);
  985. };
  986. Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
  987. if (typeof console !== 'undefined' && console) {
  988. console.warn('Possible Unhandled Promise Rejection:', err);
  989. }
  990. };
  991. Promise._setImmediateFn = function _setImmediateFn(fn) {
  992. Promise._immediateFn = fn;
  993. };
  994. Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
  995. Promise._unhandledRejectionFn = fn;
  996. };
  997. if (typeof module !== 'undefined' && module.exports) {
  998. module.exports = Promise;
  999. } else if (!root.Promise) {
  1000. root.Promise = Promise;
  1001. }
  1002. }(this));
  1003. }.call(this, require('timers').setImmediate));
  1004. },
  1005. { 'timers': 3 }
  1006. ],
  1007. 3: [
  1008. function (require, module, exports) {
  1009. (function (setImmediate, clearImmediate) {
  1010. var nextTick = require('process/browser.js').nextTick;
  1011. var apply = Function.prototype.apply;
  1012. var slice = Array.prototype.slice;
  1013. var immediateIds = {};
  1014. var nextImmediateId = 0;
  1015. exports.setTimeout = function () {
  1016. return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
  1017. };
  1018. exports.setInterval = function () {
  1019. return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
  1020. };
  1021. exports.clearTimeout = exports.clearInterval = function (timeout) {
  1022. timeout.close();
  1023. };
  1024. function Timeout(id, clearFn) {
  1025. this._id = id;
  1026. this._clearFn = clearFn;
  1027. }
  1028. Timeout.prototype.unref = Timeout.prototype.ref = function () {
  1029. };
  1030. Timeout.prototype.close = function () {
  1031. this._clearFn.call(window, this._id);
  1032. };
  1033. exports.enroll = function (item, msecs) {
  1034. clearTimeout(item._idleTimeoutId);
  1035. item._idleTimeout = msecs;
  1036. };
  1037. exports.unenroll = function (item) {
  1038. clearTimeout(item._idleTimeoutId);
  1039. item._idleTimeout = -1;
  1040. };
  1041. exports._unrefActive = exports.active = function (item) {
  1042. clearTimeout(item._idleTimeoutId);
  1043. var msecs = item._idleTimeout;
  1044. if (msecs >= 0) {
  1045. item._idleTimeoutId = setTimeout(function onTimeout() {
  1046. if (item._onTimeout)
  1047. item._onTimeout();
  1048. }, msecs);
  1049. }
  1050. };
  1051. exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) {
  1052. var id = nextImmediateId++;
  1053. var args = arguments.length < 2 ? false : slice.call(arguments, 1);
  1054. immediateIds[id] = true;
  1055. nextTick(function onNextTick() {
  1056. if (immediateIds[id]) {
  1057. if (args) {
  1058. fn.apply(null, args);
  1059. } else {
  1060. fn.call(null);
  1061. }
  1062. exports.clearImmediate(id);
  1063. }
  1064. });
  1065. return id;
  1066. };
  1067. exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) {
  1068. delete immediateIds[id];
  1069. };
  1070. }.call(this, require('timers').setImmediate, require('timers').clearImmediate));
  1071. },
  1072. {
  1073. 'process/browser.js': 1,
  1074. 'timers': 3
  1075. }
  1076. ],
  1077. 4: [
  1078. function (require, module, exports) {
  1079. var promisePolyfill = require('promise-polyfill');
  1080. var Global = function () {
  1081. if (typeof window !== 'undefined') {
  1082. return window;
  1083. } else {
  1084. return Function('return this;')();
  1085. }
  1086. }();
  1087. module.exports = { boltExport: Global.Promise || promisePolyfill };
  1088. },
  1089. { 'promise-polyfill': 2 }
  1090. ]
  1091. }, {}, [4])(4);
  1092. }));
  1093. }(undefined, exports$1, module, undefined));
  1094. var Promise = module.exports.boltExport;
  1095. var nu = function (baseFn) {
  1096. var data = Option.none();
  1097. var callbacks = [];
  1098. var map = function (f) {
  1099. return nu(function (nCallback) {
  1100. get(function (data) {
  1101. nCallback(f(data));
  1102. });
  1103. });
  1104. };
  1105. var get = function (nCallback) {
  1106. if (isReady()) {
  1107. call(nCallback);
  1108. } else {
  1109. callbacks.push(nCallback);
  1110. }
  1111. };
  1112. var set = function (x) {
  1113. data = Option.some(x);
  1114. run(callbacks);
  1115. callbacks = [];
  1116. };
  1117. var isReady = function () {
  1118. return data.isSome();
  1119. };
  1120. var run = function (cbs) {
  1121. each(cbs, call);
  1122. };
  1123. var call = function (cb) {
  1124. data.each(function (x) {
  1125. domGlobals.setTimeout(function () {
  1126. cb(x);
  1127. }, 0);
  1128. });
  1129. };
  1130. baseFn(set);
  1131. return {
  1132. get: get,
  1133. map: map,
  1134. isReady: isReady
  1135. };
  1136. };
  1137. var pure = function (a) {
  1138. return nu(function (callback) {
  1139. callback(a);
  1140. });
  1141. };
  1142. var LazyValue = {
  1143. nu: nu,
  1144. pure: pure
  1145. };
  1146. var errorReporter = function (err) {
  1147. domGlobals.setTimeout(function () {
  1148. throw err;
  1149. }, 0);
  1150. };
  1151. var make = function (run) {
  1152. var get = function (callback) {
  1153. run().then(callback, errorReporter);
  1154. };
  1155. var map = function (fab) {
  1156. return make(function () {
  1157. return run().then(fab);
  1158. });
  1159. };
  1160. var bind = function (aFutureB) {
  1161. return make(function () {
  1162. return run().then(function (v) {
  1163. return aFutureB(v).toPromise();
  1164. });
  1165. });
  1166. };
  1167. var anonBind = function (futureB) {
  1168. return make(function () {
  1169. return run().then(function () {
  1170. return futureB.toPromise();
  1171. });
  1172. });
  1173. };
  1174. var toLazy = function () {
  1175. return LazyValue.nu(get);
  1176. };
  1177. var toCached = function () {
  1178. var cache = null;
  1179. return make(function () {
  1180. if (cache === null) {
  1181. cache = run();
  1182. }
  1183. return cache;
  1184. });
  1185. };
  1186. var toPromise = run;
  1187. return {
  1188. map: map,
  1189. bind: bind,
  1190. anonBind: anonBind,
  1191. toLazy: toLazy,
  1192. toCached: toCached,
  1193. toPromise: toPromise,
  1194. get: get
  1195. };
  1196. };
  1197. var nu$1 = function (baseFn) {
  1198. return make(function () {
  1199. return new Promise(baseFn);
  1200. });
  1201. };
  1202. var pure$1 = function (a) {
  1203. return make(function () {
  1204. return Promise.resolve(a);
  1205. });
  1206. };
  1207. var Future = {
  1208. nu: nu$1,
  1209. pure: pure$1
  1210. };
  1211. var global$4 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  1212. var delayedConfirm = function (editor, message, callback) {
  1213. var rng = editor.selection.getRng();
  1214. global$4.setEditorTimeout(editor, function () {
  1215. editor.windowManager.confirm(message, function (state) {
  1216. editor.selection.setRng(rng);
  1217. callback(state);
  1218. });
  1219. });
  1220. };
  1221. var tryEmailTransform = function (data) {
  1222. var url = data.href;
  1223. var suggestMailTo = url.indexOf('@') > 0 && url.indexOf('//') === -1 && url.indexOf('mailto:') === -1;
  1224. return suggestMailTo ? Option.some({
  1225. message: 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?',
  1226. preprocess: function (oldData) {
  1227. return __assign(__assign({}, oldData), { href: 'mailto:' + url });
  1228. }
  1229. }) : Option.none();
  1230. };
  1231. var tryProtocolTransform = function (assumeExternalTargets, defaultLinkProtocol) {
  1232. return function (data) {
  1233. var url = data.href;
  1234. var suggestProtocol = assumeExternalTargets === 1 && !Utils.hasProtocol(url) || assumeExternalTargets === 0 && /^\s*www[\.|\d\.]/i.test(url);
  1235. return suggestProtocol ? Option.some({
  1236. message: 'The URL you entered seems to be an external link. Do you want to add the required ' + defaultLinkProtocol + ':// prefix?',
  1237. preprocess: function (oldData) {
  1238. return __assign(__assign({}, oldData), { href: defaultLinkProtocol + '://' + url });
  1239. }
  1240. }) : Option.none();
  1241. };
  1242. };
  1243. var preprocess = function (editor, data) {
  1244. return findMap([
  1245. tryEmailTransform,
  1246. tryProtocolTransform(Settings.assumeExternalTargets(editor), Settings.getDefaultLinkProtocol(editor))
  1247. ], function (f) {
  1248. return f(data);
  1249. }).fold(function () {
  1250. return Future.pure(data);
  1251. }, function (transform) {
  1252. return Future.nu(function (callback) {
  1253. delayedConfirm(editor, transform.message, function (state) {
  1254. callback(state ? transform.preprocess(data) : data);
  1255. });
  1256. });
  1257. });
  1258. };
  1259. var DialogConfirms = { preprocess: preprocess };
  1260. var getAnchors = function (editor) {
  1261. var anchorNodes = editor.dom.select('a:not([href])');
  1262. var anchors = bind(anchorNodes, function (anchor) {
  1263. var id = anchor.name || anchor.id;
  1264. return id ? [{
  1265. text: id,
  1266. value: '#' + id
  1267. }] : [];
  1268. });
  1269. return anchors.length > 0 ? Option.some([{
  1270. text: 'None',
  1271. value: ''
  1272. }].concat(anchors)) : Option.none();
  1273. };
  1274. var AnchorListOptions = { getAnchors: getAnchors };
  1275. var getClasses = function (editor) {
  1276. var list = Settings.getLinkClassList(editor);
  1277. if (list.length > 0) {
  1278. return ListOptions.sanitize(list);
  1279. }
  1280. return Option.none();
  1281. };
  1282. var ClassListOptions = { getClasses: getClasses };
  1283. var global$5 = tinymce.util.Tools.resolve('tinymce.util.XHR');
  1284. var parseJson = function (text) {
  1285. try {
  1286. return Option.some(JSON.parse(text));
  1287. } catch (err) {
  1288. return Option.none();
  1289. }
  1290. };
  1291. var getLinks = function (editor) {
  1292. var extractor = function (item) {
  1293. return editor.convertURL(item.value || item.url, 'href');
  1294. };
  1295. var linkList = Settings.getLinkList(editor);
  1296. return Future.nu(function (callback) {
  1297. if (isString(linkList)) {
  1298. global$5.send({
  1299. url: linkList,
  1300. success: function (text) {
  1301. return callback(parseJson(text));
  1302. },
  1303. error: function (_) {
  1304. return callback(Option.none());
  1305. }
  1306. });
  1307. } else if (isFunction(linkList)) {
  1308. linkList(function (output) {
  1309. return callback(Option.some(output));
  1310. });
  1311. } else {
  1312. callback(Option.from(linkList));
  1313. }
  1314. }).map(function (optItems) {
  1315. return optItems.bind(ListOptions.sanitizeWith(extractor)).map(function (items) {
  1316. if (items.length > 0) {
  1317. return [{
  1318. text: 'None',
  1319. value: ''
  1320. }].concat(items);
  1321. } else {
  1322. return items;
  1323. }
  1324. });
  1325. });
  1326. };
  1327. var LinkListOptions = { getLinks: getLinks };
  1328. var getRels = function (editor, initialTarget) {
  1329. var list = Settings.getRelList(editor);
  1330. if (list.length > 0) {
  1331. var isTargetBlank_1 = initialTarget.is('_blank');
  1332. var enforceSafe = Settings.allowUnsafeLinkTarget(editor) === false;
  1333. var safeRelExtractor = function (item) {
  1334. return Utils.applyRelTargetRules(ListOptions.getValue(item), isTargetBlank_1);
  1335. };
  1336. var sanitizer = enforceSafe ? ListOptions.sanitizeWith(safeRelExtractor) : ListOptions.sanitize;
  1337. return sanitizer(list);
  1338. }
  1339. return Option.none();
  1340. };
  1341. var RelOptions = { getRels: getRels };
  1342. var fallbacks = [
  1343. {
  1344. text: 'Current window',
  1345. value: ''
  1346. },
  1347. {
  1348. text: 'New window',
  1349. value: '_blank'
  1350. }
  1351. ];
  1352. var getTargets = function (editor) {
  1353. var list = Settings.getTargetList(editor);
  1354. if (isArray(list)) {
  1355. return ListOptions.sanitize(list).orThunk(function () {
  1356. return Option.some(fallbacks);
  1357. });
  1358. } else if (list === false) {
  1359. return Option.none();
  1360. }
  1361. return Option.some(fallbacks);
  1362. };
  1363. var TargetOptions = { getTargets: getTargets };
  1364. var nonEmptyAttr = function (dom, elem, name) {
  1365. var val = dom.getAttrib(elem, name);
  1366. return val !== null && val.length > 0 ? Option.some(val) : Option.none();
  1367. };
  1368. var extractFromAnchor = function (editor, anchor) {
  1369. var dom = editor.dom;
  1370. var onlyText = Utils.isOnlyTextSelected(editor.selection.getContent());
  1371. var text = onlyText ? Option.some(Utils.getAnchorText(editor.selection, anchor)) : Option.none();
  1372. var url = anchor ? Option.some(dom.getAttrib(anchor, 'href')) : Option.none();
  1373. var target = anchor ? Option.from(dom.getAttrib(anchor, 'target')) : Option.none();
  1374. var rel = nonEmptyAttr(dom, anchor, 'rel');
  1375. var linkClass = nonEmptyAttr(dom, anchor, 'class');
  1376. var title = nonEmptyAttr(dom, anchor, 'title');
  1377. return {
  1378. url: url,
  1379. text: text,
  1380. title: title,
  1381. target: target,
  1382. rel: rel,
  1383. linkClass: linkClass
  1384. };
  1385. };
  1386. var collect = function (editor, linkNode) {
  1387. return LinkListOptions.getLinks(editor).map(function (links) {
  1388. var anchor = extractFromAnchor(editor, linkNode);
  1389. return {
  1390. anchor: anchor,
  1391. catalogs: {
  1392. targets: TargetOptions.getTargets(editor),
  1393. rels: RelOptions.getRels(editor, anchor.target),
  1394. classes: ClassListOptions.getClasses(editor),
  1395. anchor: AnchorListOptions.getAnchors(editor),
  1396. link: links
  1397. },
  1398. optNode: Option.from(linkNode),
  1399. flags: { titleEnabled: Settings.shouldShowLinkTitle(editor) }
  1400. };
  1401. });
  1402. };
  1403. var DialogInfo = { collect: collect };
  1404. var handleSubmit = function (editor, info) {
  1405. return function (api) {
  1406. var data = api.getData();
  1407. if (!data.url.value) {
  1408. Utils.unlink(editor);
  1409. api.close();
  1410. return;
  1411. }
  1412. var getChangedValue = function (key) {
  1413. return Option.from(data[key]).filter(function (value) {
  1414. return !info.anchor[key].is(value);
  1415. });
  1416. };
  1417. var changedData = {
  1418. href: data.url.value,
  1419. text: getChangedValue('text'),
  1420. target: getChangedValue('target'),
  1421. rel: getChangedValue('rel'),
  1422. class: getChangedValue('linkClass'),
  1423. title: getChangedValue('title')
  1424. };
  1425. var attachState = {
  1426. href: data.url.value,
  1427. attach: data.url.meta !== undefined && data.url.meta.attach ? data.url.meta.attach : function () {
  1428. }
  1429. };
  1430. DialogConfirms.preprocess(editor, changedData).get(function (pData) {
  1431. Utils.link(editor, attachState, pData);
  1432. });
  1433. api.close();
  1434. };
  1435. };
  1436. var collectData = function (editor) {
  1437. var anchorNode = Utils.getAnchorElement(editor);
  1438. return DialogInfo.collect(editor, anchorNode);
  1439. };
  1440. var getInitialData = function (info, defaultTarget) {
  1441. return {
  1442. url: {
  1443. value: info.anchor.url.getOr(''),
  1444. meta: {
  1445. attach: function () {
  1446. },
  1447. text: info.anchor.url.fold(function () {
  1448. return '';
  1449. }, function () {
  1450. return info.anchor.text.getOr('');
  1451. }),
  1452. original: { value: info.anchor.url.getOr('') }
  1453. }
  1454. },
  1455. text: info.anchor.text.getOr(''),
  1456. title: info.anchor.title.getOr(''),
  1457. anchor: info.anchor.url.getOr(''),
  1458. link: info.anchor.url.getOr(''),
  1459. rel: info.anchor.rel.getOr(''),
  1460. target: info.anchor.target.or(defaultTarget).getOr(''),
  1461. linkClass: info.anchor.linkClass.getOr('')
  1462. };
  1463. };
  1464. var makeDialog = function (settings, onSubmit, editor) {
  1465. var urlInput = [{
  1466. name: 'url',
  1467. type: 'urlinput',
  1468. filetype: 'file',
  1469. label: 'URL'
  1470. }];
  1471. var displayText = settings.anchor.text.map(function () {
  1472. return {
  1473. name: 'text',
  1474. type: 'input',
  1475. label: 'Text to display'
  1476. };
  1477. }).toArray();
  1478. var titleText = settings.flags.titleEnabled ? [{
  1479. name: 'title',
  1480. type: 'input',
  1481. label: 'Title'
  1482. }] : [];
  1483. var defaultTarget = Option.from(Settings.getDefaultLinkTarget(editor));
  1484. var initialData = getInitialData(settings, defaultTarget);
  1485. var dialogDelta = DialogChanges.init(initialData, settings);
  1486. var catalogs = settings.catalogs;
  1487. var body = {
  1488. type: 'panel',
  1489. items: flatten([
  1490. urlInput,
  1491. displayText,
  1492. titleText,
  1493. cat([
  1494. catalogs.anchor.map(ListOptions.createUi('anchor', 'Anchors')),
  1495. catalogs.rels.map(ListOptions.createUi('rel', 'Rel')),
  1496. catalogs.targets.map(ListOptions.createUi('target', 'Open link in...')),
  1497. catalogs.link.map(ListOptions.createUi('link', 'Link list')),
  1498. catalogs.classes.map(ListOptions.createUi('linkClass', 'Class'))
  1499. ])
  1500. ])
  1501. };
  1502. return {
  1503. title: 'Insert/Edit Link',
  1504. size: 'normal',
  1505. body: body,
  1506. buttons: [
  1507. {
  1508. type: 'cancel',
  1509. name: 'cancel',
  1510. text: 'Cancel'
  1511. },
  1512. {
  1513. type: 'submit',
  1514. name: 'save',
  1515. text: 'Save',
  1516. primary: true
  1517. }
  1518. ],
  1519. initialData: initialData,
  1520. onChange: function (api, _a) {
  1521. var name = _a.name;
  1522. dialogDelta.onChange(api.getData, { name: name }).each(function (newData) {
  1523. api.setData(newData);
  1524. });
  1525. },
  1526. onSubmit: onSubmit
  1527. };
  1528. };
  1529. var open$1 = function (editor) {
  1530. var data = collectData(editor);
  1531. data.map(function (info) {
  1532. var onSubmit = handleSubmit(editor, info);
  1533. return makeDialog(info, onSubmit, editor);
  1534. }).get(function (spec) {
  1535. editor.windowManager.open(spec);
  1536. });
  1537. };
  1538. var Dialog = { open: open$1 };
  1539. var getLink = function (editor, elm) {
  1540. return editor.dom.getParent(elm, 'a[href]');
  1541. };
  1542. var getSelectedLink = function (editor) {
  1543. return getLink(editor, editor.selection.getStart());
  1544. };
  1545. var hasOnlyAltModifier = function (e) {
  1546. return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false;
  1547. };
  1548. var gotoLink = function (editor, a) {
  1549. if (a) {
  1550. var href = Utils.getHref(a);
  1551. if (/^#/.test(href)) {
  1552. var targetEl = editor.$(href);
  1553. if (targetEl.length) {
  1554. editor.selection.scrollIntoView(targetEl[0], true);
  1555. }
  1556. } else {
  1557. OpenUrl.open(a.href);
  1558. }
  1559. }
  1560. };
  1561. var openDialog = function (editor) {
  1562. return function () {
  1563. Dialog.open(editor);
  1564. };
  1565. };
  1566. var gotoSelectedLink = function (editor) {
  1567. return function () {
  1568. gotoLink(editor, getSelectedLink(editor));
  1569. };
  1570. };
  1571. var leftClickedOnAHref = function (editor) {
  1572. return function (elm) {
  1573. var sel, rng, node;
  1574. if (Settings.hasContextToolbar(editor) && Utils.isLink(elm)) {
  1575. sel = editor.selection;
  1576. rng = sel.getRng();
  1577. node = rng.startContainer;
  1578. if (node.nodeType === 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) {
  1579. return true;
  1580. }
  1581. }
  1582. return false;
  1583. };
  1584. };
  1585. var setupGotoLinks = function (editor) {
  1586. editor.on('click', function (e) {
  1587. var link = getLink(editor, e.target);
  1588. if (link && global$2.metaKeyPressed(e)) {
  1589. e.preventDefault();
  1590. gotoLink(editor, link);
  1591. }
  1592. });
  1593. editor.on('keydown', function (e) {
  1594. var link = getSelectedLink(editor);
  1595. if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) {
  1596. e.preventDefault();
  1597. gotoLink(editor, link);
  1598. }
  1599. });
  1600. };
  1601. var toggleActiveState = function (editor) {
  1602. return function (api) {
  1603. var nodeChangeHandler = function (e) {
  1604. return api.setActive(!editor.readonly && !!Utils.getAnchorElement(editor, e.element));
  1605. };
  1606. editor.on('NodeChange', nodeChangeHandler);
  1607. return function () {
  1608. return editor.off('NodeChange', nodeChangeHandler);
  1609. };
  1610. };
  1611. };
  1612. var toggleEnabledState = function (editor) {
  1613. return function (api) {
  1614. api.setDisabled(!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart())));
  1615. var nodeChangeHandler = function (e) {
  1616. return api.setDisabled(!Utils.hasLinks(e.parents));
  1617. };
  1618. editor.on('NodeChange', nodeChangeHandler);
  1619. return function () {
  1620. return editor.off('NodeChange', nodeChangeHandler);
  1621. };
  1622. };
  1623. };
  1624. var Actions = {
  1625. openDialog: openDialog,
  1626. gotoSelectedLink: gotoSelectedLink,
  1627. leftClickedOnAHref: leftClickedOnAHref,
  1628. setupGotoLinks: setupGotoLinks,
  1629. toggleActiveState: toggleActiveState,
  1630. toggleEnabledState: toggleEnabledState
  1631. };
  1632. var register = function (editor) {
  1633. editor.addCommand('mceLink', function () {
  1634. if (Settings.useQuickLink(editor)) {
  1635. editor.fire('contexttoolbar-show', { toolbarKey: 'quicklink' });
  1636. } else {
  1637. Actions.openDialog(editor)();
  1638. }
  1639. });
  1640. };
  1641. var Commands = { register: register };
  1642. var setup = function (editor) {
  1643. editor.addShortcut('Meta+K', '', function () {
  1644. editor.execCommand('mceLink');
  1645. });
  1646. };
  1647. var Keyboard = { setup: setup };
  1648. var setupButtons = function (editor) {
  1649. editor.ui.registry.addToggleButton('link', {
  1650. icon: 'link',
  1651. tooltip: 'Insert/edit link',
  1652. onAction: Actions.openDialog(editor),
  1653. onSetup: Actions.toggleActiveState(editor)
  1654. });
  1655. editor.ui.registry.addButton('openlink', {
  1656. icon: 'new-tab',
  1657. tooltip: 'Open link',
  1658. onAction: Actions.gotoSelectedLink(editor),
  1659. onSetup: Actions.toggleEnabledState(editor)
  1660. });
  1661. editor.ui.registry.addButton('unlink', {
  1662. icon: 'unlink',
  1663. tooltip: 'Remove link',
  1664. onAction: function () {
  1665. return Utils.unlink(editor);
  1666. },
  1667. onSetup: Actions.toggleEnabledState(editor)
  1668. });
  1669. };
  1670. var setupMenuItems = function (editor) {
  1671. editor.ui.registry.addMenuItem('openlink', {
  1672. text: 'Open link',
  1673. icon: 'new-tab',
  1674. onAction: Actions.gotoSelectedLink(editor),
  1675. onSetup: Actions.toggleEnabledState(editor)
  1676. });
  1677. editor.ui.registry.addMenuItem('link', {
  1678. icon: 'link',
  1679. text: 'Link...',
  1680. shortcut: 'Meta+K',
  1681. onAction: Actions.openDialog(editor)
  1682. });
  1683. editor.ui.registry.addMenuItem('unlink', {
  1684. icon: 'unlink',
  1685. text: 'Remove link',
  1686. onAction: function () {
  1687. return Utils.unlink(editor);
  1688. },
  1689. onSetup: Actions.toggleEnabledState(editor)
  1690. });
  1691. };
  1692. var setupContextMenu = function (editor) {
  1693. var inLink = 'link unlink openlink';
  1694. var noLink = 'link';
  1695. editor.ui.registry.addContextMenu('link', {
  1696. update: function (element) {
  1697. return Utils.hasLinks(editor.dom.getParents(element, 'a')) ? inLink : noLink;
  1698. }
  1699. });
  1700. };
  1701. var setupContextToolbars = function (editor) {
  1702. var collapseSelectionToEnd = function (editor) {
  1703. editor.selection.collapse(false);
  1704. };
  1705. var onSetupLink = function (buttonApi) {
  1706. var node = editor.selection.getNode();
  1707. buttonApi.setDisabled(!Utils.getAnchorElement(editor, node));
  1708. return function () {
  1709. };
  1710. };
  1711. editor.ui.registry.addContextForm('quicklink', {
  1712. launch: {
  1713. type: 'contextformtogglebutton',
  1714. icon: 'link',
  1715. tooltip: 'Link',
  1716. onSetup: Actions.toggleActiveState(editor)
  1717. },
  1718. label: 'Link',
  1719. predicate: function (node) {
  1720. return !!Utils.getAnchorElement(editor, node) && Settings.hasContextToolbar(editor);
  1721. },
  1722. initValue: function () {
  1723. var elm = Utils.getAnchorElement(editor);
  1724. return !!elm ? Utils.getHref(elm) : '';
  1725. },
  1726. commands: [
  1727. {
  1728. type: 'contextformtogglebutton',
  1729. icon: 'link',
  1730. tooltip: 'Link',
  1731. primary: true,
  1732. onSetup: function (buttonApi) {
  1733. var node = editor.selection.getNode();
  1734. buttonApi.setActive(!!Utils.getAnchorElement(editor, node));
  1735. return Actions.toggleActiveState(editor)(buttonApi);
  1736. },
  1737. onAction: function (formApi) {
  1738. var anchor = Utils.getAnchorElement(editor);
  1739. var value = formApi.getValue();
  1740. if (!anchor) {
  1741. var attachState = {
  1742. href: value,
  1743. attach: function () {
  1744. }
  1745. };
  1746. var onlyText = Utils.isOnlyTextSelected(editor.selection.getContent());
  1747. var text = onlyText ? Option.some(Utils.getAnchorText(editor.selection, anchor)).filter(function (t) {
  1748. return t.length > 0;
  1749. }).or(Option.from(value)) : Option.none();
  1750. Utils.link(editor, attachState, {
  1751. href: value,
  1752. text: text,
  1753. title: Option.none(),
  1754. rel: Option.none(),
  1755. target: Option.none(),
  1756. class: Option.none()
  1757. });
  1758. formApi.hide();
  1759. } else {
  1760. editor.dom.setAttrib(anchor, 'href', value);
  1761. collapseSelectionToEnd(editor);
  1762. formApi.hide();
  1763. }
  1764. }
  1765. },
  1766. {
  1767. type: 'contextformbutton',
  1768. icon: 'unlink',
  1769. tooltip: 'Remove link',
  1770. onSetup: onSetupLink,
  1771. onAction: function (formApi) {
  1772. Utils.unlink(editor);
  1773. formApi.hide();
  1774. }
  1775. },
  1776. {
  1777. type: 'contextformbutton',
  1778. icon: 'new-tab',
  1779. tooltip: 'Open link',
  1780. onSetup: onSetupLink,
  1781. onAction: function (formApi) {
  1782. Actions.gotoSelectedLink(editor)();
  1783. formApi.hide();
  1784. }
  1785. }
  1786. ]
  1787. });
  1788. };
  1789. var Controls = {
  1790. setupButtons: setupButtons,
  1791. setupMenuItems: setupMenuItems,
  1792. setupContextMenu: setupContextMenu,
  1793. setupContextToolbars: setupContextToolbars
  1794. };
  1795. function Plugin () {
  1796. global$1.add('link', function (editor) {
  1797. Controls.setupButtons(editor);
  1798. Controls.setupMenuItems(editor);
  1799. Controls.setupContextMenu(editor);
  1800. Controls.setupContextToolbars(editor);
  1801. Actions.setupGotoLinks(editor);
  1802. Commands.register(editor);
  1803. Keyboard.setup(editor);
  1804. });
  1805. }
  1806. Plugin();
  1807. }(window));