plugin.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /**
  2. * TinyMCE version 8.0.2 (2025-08-14)
  3. */
  4. (function () {
  5. 'use strict';
  6. var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');
  7. const fireInsertCustomChar = (editor, chr) => {
  8. return editor.dispatch('insertCustomChar', { chr });
  9. };
  10. const insertChar = (editor, chr) => {
  11. const evtChr = fireInsertCustomChar(editor, chr).chr;
  12. editor.execCommand('mceInsertContent', false, evtChr);
  13. };
  14. /* eslint-disable @typescript-eslint/no-wrapper-object-types */
  15. const hasProto = (v, constructor, predicate) => {
  16. var _a;
  17. if (predicate(v, constructor.prototype)) {
  18. return true;
  19. }
  20. else {
  21. // String-based fallback time
  22. return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
  23. }
  24. };
  25. const typeOf = (x) => {
  26. const t = typeof x;
  27. if (x === null) {
  28. return 'null';
  29. }
  30. else if (t === 'object' && Array.isArray(x)) {
  31. return 'array';
  32. }
  33. else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
  34. return 'string';
  35. }
  36. else {
  37. return t;
  38. }
  39. };
  40. const isType = (type) => (value) => typeOf(value) === type;
  41. const isSimpleType = (type) => (value) => typeof value === type;
  42. const eq = (t) => (a) => t === a;
  43. const isArray$1 = isType('array');
  44. const isNull = eq(null);
  45. const isUndefined = eq(undefined);
  46. const isNullable = (a) => a === null || a === undefined;
  47. const isNonNullable = (a) => !isNullable(a);
  48. const isFunction = isSimpleType('function');
  49. const constant = (value) => {
  50. return () => {
  51. return value;
  52. };
  53. };
  54. const never = constant(false);
  55. /**
  56. * The `Optional` type represents a value (of any type) that potentially does
  57. * not exist. Any `Optional<T>` can either be a `Some<T>` (in which case the
  58. * value does exist) or a `None` (in which case the value does not exist). This
  59. * module defines a whole lot of FP-inspired utility functions for dealing with
  60. * `Optional` objects.
  61. *
  62. * Comparison with null or undefined:
  63. * - We don't get fancy null coalescing operators with `Optional`
  64. * - We do get fancy helper functions with `Optional`
  65. * - `Optional` support nesting, and allow for the type to still be nullable (or
  66. * another `Optional`)
  67. * - There is no option to turn off strict-optional-checks like there is for
  68. * strict-null-checks
  69. */
  70. class Optional {
  71. // The internal representation has a `tag` and a `value`, but both are
  72. // private: able to be console.logged, but not able to be accessed by code
  73. constructor(tag, value) {
  74. this.tag = tag;
  75. this.value = value;
  76. }
  77. // --- Identities ---
  78. /**
  79. * Creates a new `Optional<T>` that **does** contain a value.
  80. */
  81. static some(value) {
  82. return new Optional(true, value);
  83. }
  84. /**
  85. * Create a new `Optional<T>` that **does not** contain a value. `T` can be
  86. * any type because we don't actually have a `T`.
  87. */
  88. static none() {
  89. return Optional.singletonNone;
  90. }
  91. /**
  92. * Perform a transform on an `Optional` type. Regardless of whether this
  93. * `Optional` contains a value or not, `fold` will return a value of type `U`.
  94. * If this `Optional` does not contain a value, the `U` will be created by
  95. * calling `onNone`. If this `Optional` does contain a value, the `U` will be
  96. * created by calling `onSome`.
  97. *
  98. * For the FP enthusiasts in the room, this function:
  99. * 1. Could be used to implement all of the functions below
  100. * 2. Forms a catamorphism
  101. */
  102. fold(onNone, onSome) {
  103. if (this.tag) {
  104. return onSome(this.value);
  105. }
  106. else {
  107. return onNone();
  108. }
  109. }
  110. /**
  111. * Determine if this `Optional` object contains a value.
  112. */
  113. isSome() {
  114. return this.tag;
  115. }
  116. /**
  117. * Determine if this `Optional` object **does not** contain a value.
  118. */
  119. isNone() {
  120. return !this.tag;
  121. }
  122. // --- Functor (name stolen from Haskell / maths) ---
  123. /**
  124. * Perform a transform on an `Optional` object, **if** there is a value. If
  125. * you provide a function to turn a T into a U, this is the function you use
  126. * to turn an `Optional<T>` into an `Optional<U>`. If this **does** contain
  127. * a value then the output will also contain a value (that value being the
  128. * output of `mapper(this.value)`), and if this **does not** contain a value
  129. * then neither will the output.
  130. */
  131. map(mapper) {
  132. if (this.tag) {
  133. return Optional.some(mapper(this.value));
  134. }
  135. else {
  136. return Optional.none();
  137. }
  138. }
  139. // --- Monad (name stolen from Haskell / maths) ---
  140. /**
  141. * Perform a transform on an `Optional` object, **if** there is a value.
  142. * Unlike `map`, here the transform itself also returns an `Optional`.
  143. */
  144. bind(binder) {
  145. if (this.tag) {
  146. return binder(this.value);
  147. }
  148. else {
  149. return Optional.none();
  150. }
  151. }
  152. // --- Traversable (name stolen from Haskell / maths) ---
  153. /**
  154. * For a given predicate, this function finds out if there **exists** a value
  155. * inside this `Optional` object that meets the predicate. In practice, this
  156. * means that for `Optional`s that do not contain a value it returns false (as
  157. * no predicate-meeting value exists).
  158. */
  159. exists(predicate) {
  160. return this.tag && predicate(this.value);
  161. }
  162. /**
  163. * For a given predicate, this function finds out if **all** the values inside
  164. * this `Optional` object meet the predicate. In practice, this means that
  165. * for `Optional`s that do not contain a value it returns true (as all 0
  166. * objects do meet the predicate).
  167. */
  168. forall(predicate) {
  169. return !this.tag || predicate(this.value);
  170. }
  171. filter(predicate) {
  172. if (!this.tag || predicate(this.value)) {
  173. return this;
  174. }
  175. else {
  176. return Optional.none();
  177. }
  178. }
  179. // --- Getters ---
  180. /**
  181. * Get the value out of the inside of the `Optional` object, using a default
  182. * `replacement` value if the provided `Optional` object does not contain a
  183. * value.
  184. */
  185. getOr(replacement) {
  186. return this.tag ? this.value : replacement;
  187. }
  188. /**
  189. * Get the value out of the inside of the `Optional` object, using a default
  190. * `replacement` value if the provided `Optional` object does not contain a
  191. * value. Unlike `getOr`, in this method the `replacement` object is also
  192. * `Optional` - meaning that this method will always return an `Optional`.
  193. */
  194. or(replacement) {
  195. return this.tag ? this : replacement;
  196. }
  197. /**
  198. * Get the value out of the inside of the `Optional` object, using a default
  199. * `replacement` value if the provided `Optional` object does not contain a
  200. * value. Unlike `getOr`, in this method the `replacement` value is
  201. * "thunked" - that is to say that you don't pass a value to `getOrThunk`, you
  202. * pass a function which (if called) will **return** the `value` you want to
  203. * use.
  204. */
  205. getOrThunk(thunk) {
  206. return this.tag ? this.value : thunk();
  207. }
  208. /**
  209. * Get the value out of the inside of the `Optional` object, using a default
  210. * `replacement` value if the provided Optional object does not contain a
  211. * value.
  212. *
  213. * Unlike `or`, in this method the `replacement` value is "thunked" - that is
  214. * to say that you don't pass a value to `orThunk`, you pass a function which
  215. * (if called) will **return** the `value` you want to use.
  216. *
  217. * Unlike `getOrThunk`, in this method the `replacement` value is also
  218. * `Optional`, meaning that this method will always return an `Optional`.
  219. */
  220. orThunk(thunk) {
  221. return this.tag ? this : thunk();
  222. }
  223. /**
  224. * Get the value out of the inside of the `Optional` object, throwing an
  225. * exception if the provided `Optional` object does not contain a value.
  226. *
  227. * WARNING:
  228. * You should only be using this function if you know that the `Optional`
  229. * object **is not** empty (otherwise you're throwing exceptions in production
  230. * code, which is bad).
  231. *
  232. * In tests this is more acceptable.
  233. *
  234. * Prefer other methods to this, such as `.each`.
  235. */
  236. getOrDie(message) {
  237. if (!this.tag) {
  238. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  239. }
  240. else {
  241. return this.value;
  242. }
  243. }
  244. // --- Interop with null and undefined ---
  245. /**
  246. * Creates an `Optional` value from a nullable (or undefined-able) input.
  247. * Null, or undefined, is converted to `None`, and anything else is converted
  248. * to `Some`.
  249. */
  250. static from(value) {
  251. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  252. }
  253. /**
  254. * Converts an `Optional` to a nullable type, by getting the value if it
  255. * exists, or returning `null` if it does not.
  256. */
  257. getOrNull() {
  258. return this.tag ? this.value : null;
  259. }
  260. /**
  261. * Converts an `Optional` to an undefined-able type, by getting the value if
  262. * it exists, or returning `undefined` if it does not.
  263. */
  264. getOrUndefined() {
  265. return this.value;
  266. }
  267. // --- Utilities ---
  268. /**
  269. * If the `Optional` contains a value, perform an action on that value.
  270. * Unlike the rest of the methods on this type, `.each` has side-effects. If
  271. * you want to transform an `Optional<T>` **into** something, then this is not
  272. * the method for you. If you want to use an `Optional<T>` to **do**
  273. * something, then this is the method for you - provided you're okay with not
  274. * doing anything in the case where the `Optional` doesn't have a value inside
  275. * it. If you're not sure whether your use-case fits into transforming
  276. * **into** something or **doing** something, check whether it has a return
  277. * value. If it does, you should be performing a transform.
  278. */
  279. each(worker) {
  280. if (this.tag) {
  281. worker(this.value);
  282. }
  283. }
  284. /**
  285. * Turn the `Optional` object into an array that contains all of the values
  286. * stored inside the `Optional`. In practice, this means the output will have
  287. * either 0 or 1 elements.
  288. */
  289. toArray() {
  290. return this.tag ? [this.value] : [];
  291. }
  292. /**
  293. * Turn the `Optional` object into a string for debugging or printing. Not
  294. * recommended for production code, but good for debugging. Also note that
  295. * these days an `Optional` object can be logged to the console directly, and
  296. * its inner value (if it exists) will be visible.
  297. */
  298. toString() {
  299. return this.tag ? `some(${this.value})` : 'none()';
  300. }
  301. }
  302. // Sneaky optimisation: every instance of Optional.none is identical, so just
  303. // reuse the same object
  304. Optional.singletonNone = new Optional(false);
  305. const nativeSlice = Array.prototype.slice;
  306. const nativePush = Array.prototype.push;
  307. const map = (xs, f) => {
  308. // pre-allocating array size when it's guaranteed to be known
  309. // http://jsperf.com/push-allocated-vs-dynamic/22
  310. const len = xs.length;
  311. const r = new Array(len);
  312. for (let i = 0; i < len; i++) {
  313. const x = xs[i];
  314. r[i] = f(x, i);
  315. }
  316. return r;
  317. };
  318. // Unwound implementing other functions in terms of each.
  319. // The code size is roughly the same, and it should allow for better optimisation.
  320. // const each = function<T, U>(xs: T[], f: (x: T, i?: number, xs?: T[]) => void): void {
  321. const each = (xs, f) => {
  322. for (let i = 0, len = xs.length; i < len; i++) {
  323. const x = xs[i];
  324. f(x, i);
  325. }
  326. };
  327. const findUntil = (xs, pred, until) => {
  328. for (let i = 0, len = xs.length; i < len; i++) {
  329. const x = xs[i];
  330. if (pred(x, i)) {
  331. return Optional.some(x);
  332. }
  333. else if (until(x, i)) {
  334. break;
  335. }
  336. }
  337. return Optional.none();
  338. };
  339. const find = (xs, pred) => {
  340. return findUntil(xs, pred, never);
  341. };
  342. const flatten = (xs) => {
  343. // Note, this is possible because push supports multiple arguments:
  344. // http://jsperf.com/concat-push/6
  345. // Note that in the past, concat() would silently work (very slowly) for array-like objects.
  346. // With this change it will throw an error.
  347. const r = [];
  348. for (let i = 0, len = xs.length; i < len; ++i) {
  349. // Ensure that each value is an array itself
  350. if (!isArray$1(xs[i])) {
  351. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  352. }
  353. nativePush.apply(r, xs[i]);
  354. }
  355. return r;
  356. };
  357. const bind = (xs, f) => flatten(map(xs, f));
  358. isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
  359. const Cell = (initial) => {
  360. let value = initial;
  361. const get = () => {
  362. return value;
  363. };
  364. const set = (v) => {
  365. value = v;
  366. };
  367. return {
  368. get,
  369. set
  370. };
  371. };
  372. const contains = (str, substr, start = 0, end) => {
  373. const idx = str.indexOf(substr, start);
  374. if (idx !== -1) {
  375. return isUndefined(end) ? true : idx + substr.length <= end;
  376. }
  377. else {
  378. return false;
  379. }
  380. };
  381. const fromCodePoint = String.fromCodePoint;
  382. // Run a function fn after rate ms. If another invocation occurs
  383. // during the time it is waiting, reschedule the function again
  384. // with the new arguments.
  385. const last = (fn, rate) => {
  386. let timer = null;
  387. const cancel = () => {
  388. if (!isNull(timer)) {
  389. clearTimeout(timer);
  390. timer = null;
  391. }
  392. };
  393. const throttle = (...args) => {
  394. cancel();
  395. timer = setTimeout(() => {
  396. timer = null;
  397. fn.apply(null, args);
  398. }, rate);
  399. };
  400. return {
  401. cancel,
  402. throttle
  403. };
  404. };
  405. var global = tinymce.util.Tools.resolve('tinymce.util.Tools');
  406. const option = (name) => (editor) => editor.options.get(name);
  407. const register$2 = (editor) => {
  408. const registerOption = editor.options.register;
  409. const charMapProcessor = (value) => isFunction(value) || isArray$1(value);
  410. registerOption('charmap', {
  411. processor: charMapProcessor,
  412. });
  413. registerOption('charmap_append', {
  414. processor: charMapProcessor
  415. });
  416. };
  417. const getCharMap$1 = option('charmap');
  418. const getCharMapAppend = option('charmap_append');
  419. const isArray = global.isArray;
  420. const UserDefined = 'User Defined';
  421. const getDefaultCharMap = () => {
  422. return [
  423. // TODO: Merge categories with TBIO
  424. // {
  425. // name: 'Unknown',
  426. // characters : [
  427. // [160, 'no-break space'],
  428. // [173, 'soft hyphen'],
  429. // [34, 'quotation mark']
  430. // ]
  431. // },
  432. { name: 'Currency',
  433. characters: [
  434. [36, 'dollar sign'],
  435. [162, 'cent sign'],
  436. [8364, 'euro sign'],
  437. [163, 'pound sign'],
  438. [165, 'yen sign'],
  439. [164, 'currency sign'],
  440. [8352, 'euro-currency sign'],
  441. [8353, 'colon sign'],
  442. [8354, 'cruzeiro sign'],
  443. [8355, 'french franc sign'],
  444. [8356, 'lira sign'],
  445. [8357, 'mill sign'],
  446. [8358, 'naira sign'],
  447. [8359, 'peseta sign'],
  448. [8360, 'rupee sign'],
  449. [8361, 'won sign'],
  450. [8362, 'new sheqel sign'],
  451. [8363, 'dong sign'],
  452. [8365, 'kip sign'],
  453. [8366, 'tugrik sign'],
  454. [8367, 'drachma sign'],
  455. [8368, 'german penny symbol'],
  456. [8369, 'peso sign'],
  457. [8370, 'guarani sign'],
  458. [8371, 'austral sign'],
  459. [8372, 'hryvnia sign'],
  460. [8373, 'cedi sign'],
  461. [8374, 'livre tournois sign'],
  462. [8375, 'spesmilo sign'],
  463. [8376, 'tenge sign'],
  464. [8377, 'indian rupee sign'],
  465. [8378, 'turkish lira sign'],
  466. [8379, 'nordic mark sign'],
  467. [8380, 'manat sign'],
  468. [8381, 'ruble sign'],
  469. [20870, 'yen character'],
  470. [20803, 'yuan character'],
  471. [22291, 'yuan character, in hong kong and taiwan'],
  472. [22278, 'yen/yuan character variant one']
  473. ]
  474. },
  475. { name: 'Text',
  476. characters: [
  477. [169, 'copyright sign'],
  478. [174, 'registered sign'],
  479. [8482, 'trade mark sign'],
  480. [8240, 'per mille sign'],
  481. [181, 'micro sign'],
  482. [183, 'middle dot'],
  483. [8226, 'bullet'],
  484. [8230, 'three dot leader'],
  485. [8242, 'minutes / feet'],
  486. [8243, 'seconds / inches'],
  487. [167, 'section sign'],
  488. [182, 'paragraph sign'],
  489. [223, 'sharp s / ess-zed']
  490. ]
  491. },
  492. { name: 'Quotations',
  493. characters: [
  494. [8249, 'single left-pointing angle quotation mark'],
  495. [8250, 'single right-pointing angle quotation mark'],
  496. [171, 'left pointing guillemet'],
  497. [187, 'right pointing guillemet'],
  498. [8216, 'left single quotation mark'],
  499. [8217, 'right single quotation mark'],
  500. [8220, 'left double quotation mark'],
  501. [8221, 'right double quotation mark'],
  502. [8218, 'single low-9 quotation mark'],
  503. [8222, 'double low-9 quotation mark'],
  504. [60, 'less-than sign'],
  505. [62, 'greater-than sign'],
  506. [8804, 'less-than or equal to'],
  507. [8805, 'greater-than or equal to'],
  508. [8211, 'en dash'],
  509. [8212, 'em dash'],
  510. [175, 'macron'],
  511. [8254, 'overline'],
  512. [164, 'currency sign'],
  513. [166, 'broken bar'],
  514. [168, 'diaeresis'],
  515. [161, 'inverted exclamation mark'],
  516. [191, 'turned question mark'],
  517. [710, 'circumflex accent'],
  518. [732, 'small tilde'],
  519. [176, 'degree sign'],
  520. [8722, 'minus sign'],
  521. [177, 'plus-minus sign'],
  522. [247, 'division sign'],
  523. [8260, 'fraction slash'],
  524. [215, 'multiplication sign'],
  525. [185, 'superscript one'],
  526. [178, 'superscript two'],
  527. [179, 'superscript three'],
  528. [188, 'fraction one quarter'],
  529. [189, 'fraction one half'],
  530. [190, 'fraction three quarters']
  531. ]
  532. },
  533. {
  534. name: 'Mathematical',
  535. characters: [
  536. [402, 'function / florin'],
  537. [8747, 'integral'],
  538. [8721, 'n-ary sumation'],
  539. [8734, 'infinity'],
  540. [8730, 'square root'],
  541. [8764, 'similar to'],
  542. [8773, 'approximately equal to'],
  543. [8776, 'almost equal to'],
  544. [8800, 'not equal to'],
  545. [8801, 'identical to'],
  546. [8712, 'element of'],
  547. [8713, 'not an element of'],
  548. [8715, 'contains as member'],
  549. [8719, 'n-ary product'],
  550. [8743, 'logical and'],
  551. [8744, 'logical or'],
  552. [172, 'not sign'],
  553. [8745, 'intersection'],
  554. [8746, 'union'],
  555. [8706, 'partial differential'],
  556. [8704, 'for all'],
  557. [8707, 'there exists'],
  558. [8709, 'diameter'],
  559. [8711, 'backward difference'],
  560. [8727, 'asterisk operator'],
  561. [8733, 'proportional to'],
  562. [8736, 'angle']
  563. ]
  564. },
  565. // TODO: Merge categories with TBIO
  566. // {
  567. // name: 'Undefined',
  568. // characters: [
  569. // [180, 'acute accent'],
  570. // [184, 'cedilla'],
  571. // [170, 'feminine ordinal indicator'],
  572. // [186, 'masculine ordinal indicator'],
  573. // [8224, 'dagger'],
  574. // [8225, 'double dagger']
  575. // ]
  576. // },
  577. {
  578. name: 'Extended Latin',
  579. characters: [
  580. [192, 'A - grave'],
  581. [193, 'A - acute'],
  582. [194, 'A - circumflex'],
  583. [195, 'A - tilde'],
  584. [196, 'A - diaeresis'],
  585. [197, 'A - ring above'],
  586. [256, 'A - macron'],
  587. [198, 'ligature AE'],
  588. [199, 'C - cedilla'],
  589. [200, 'E - grave'],
  590. [201, 'E - acute'],
  591. [202, 'E - circumflex'],
  592. [203, 'E - diaeresis'],
  593. [274, 'E - macron'],
  594. [204, 'I - grave'],
  595. [205, 'I - acute'],
  596. [206, 'I - circumflex'],
  597. [207, 'I - diaeresis'],
  598. [298, 'I - macron'],
  599. [208, 'ETH'],
  600. [209, 'N - tilde'],
  601. [210, 'O - grave'],
  602. [211, 'O - acute'],
  603. [212, 'O - circumflex'],
  604. [213, 'O - tilde'],
  605. [214, 'O - diaeresis'],
  606. [216, 'O - slash'],
  607. [332, 'O - macron'],
  608. [338, 'ligature OE'],
  609. [352, 'S - caron'],
  610. [217, 'U - grave'],
  611. [218, 'U - acute'],
  612. [219, 'U - circumflex'],
  613. [220, 'U - diaeresis'],
  614. [362, 'U - macron'],
  615. [221, 'Y - acute'],
  616. [376, 'Y - diaeresis'],
  617. [562, 'Y - macron'],
  618. [222, 'THORN'],
  619. [224, 'a - grave'],
  620. [225, 'a - acute'],
  621. [226, 'a - circumflex'],
  622. [227, 'a - tilde'],
  623. [228, 'a - diaeresis'],
  624. [229, 'a - ring above'],
  625. [257, 'a - macron'],
  626. [230, 'ligature ae'],
  627. [231, 'c - cedilla'],
  628. [232, 'e - grave'],
  629. [233, 'e - acute'],
  630. [234, 'e - circumflex'],
  631. [235, 'e - diaeresis'],
  632. [275, 'e - macron'],
  633. [236, 'i - grave'],
  634. [237, 'i - acute'],
  635. [238, 'i - circumflex'],
  636. [239, 'i - diaeresis'],
  637. [299, 'i - macron'],
  638. [240, 'eth'],
  639. [241, 'n - tilde'],
  640. [242, 'o - grave'],
  641. [243, 'o - acute'],
  642. [244, 'o - circumflex'],
  643. [245, 'o - tilde'],
  644. [246, 'o - diaeresis'],
  645. [248, 'o slash'],
  646. [333, 'o macron'],
  647. [339, 'ligature oe'],
  648. [353, 's - caron'],
  649. [249, 'u - grave'],
  650. [250, 'u - acute'],
  651. [251, 'u - circumflex'],
  652. [252, 'u - diaeresis'],
  653. [363, 'u - macron'],
  654. [253, 'y - acute'],
  655. [254, 'thorn'],
  656. [255, 'y - diaeresis'],
  657. [563, 'y - macron'],
  658. [913, 'Alpha'],
  659. [914, 'Beta'],
  660. [915, 'Gamma'],
  661. [916, 'Delta'],
  662. [917, 'Epsilon'],
  663. [918, 'Zeta'],
  664. [919, 'Eta'],
  665. [920, 'Theta'],
  666. [921, 'Iota'],
  667. [922, 'Kappa'],
  668. [923, 'Lambda'],
  669. [924, 'Mu'],
  670. [925, 'Nu'],
  671. [926, 'Xi'],
  672. [927, 'Omicron'],
  673. [928, 'Pi'],
  674. [929, 'Rho'],
  675. [931, 'Sigma'],
  676. [932, 'Tau'],
  677. [933, 'Upsilon'],
  678. [934, 'Phi'],
  679. [935, 'Chi'],
  680. [936, 'Psi'],
  681. [937, 'Omega'],
  682. [945, 'alpha'],
  683. [946, 'beta'],
  684. [947, 'gamma'],
  685. [948, 'delta'],
  686. [949, 'epsilon'],
  687. [950, 'zeta'],
  688. [951, 'eta'],
  689. [952, 'theta'],
  690. [953, 'iota'],
  691. [954, 'kappa'],
  692. [955, 'lambda'],
  693. [956, 'mu'],
  694. [957, 'nu'],
  695. [958, 'xi'],
  696. [959, 'omicron'],
  697. [960, 'pi'],
  698. [961, 'rho'],
  699. [962, 'final sigma'],
  700. [963, 'sigma'],
  701. [964, 'tau'],
  702. [965, 'upsilon'],
  703. [966, 'phi'],
  704. [967, 'chi'],
  705. [968, 'psi'],
  706. [969, 'omega']
  707. ]
  708. },
  709. {
  710. name: 'Symbols',
  711. characters: [
  712. [8501, 'alef symbol'],
  713. [982, 'pi symbol'],
  714. [8476, 'real part symbol'],
  715. [978, 'upsilon - hook symbol'],
  716. [8472, 'Weierstrass p'],
  717. [8465, 'imaginary part']
  718. ]
  719. },
  720. {
  721. name: 'Arrows',
  722. characters: [
  723. [8592, 'leftwards arrow'],
  724. [8593, 'upwards arrow'],
  725. [8594, 'rightwards arrow'],
  726. [8595, 'downwards arrow'],
  727. [8596, 'left right arrow'],
  728. [8629, 'carriage return'],
  729. [8656, 'leftwards double arrow'],
  730. [8657, 'upwards double arrow'],
  731. [8658, 'rightwards double arrow'],
  732. [8659, 'downwards double arrow'],
  733. [8660, 'left right double arrow'],
  734. [8756, 'therefore'],
  735. [8834, 'subset of'],
  736. [8835, 'superset of'],
  737. [8836, 'not a subset of'],
  738. [8838, 'subset of or equal to'],
  739. [8839, 'superset of or equal to'],
  740. [8853, 'circled plus'],
  741. [8855, 'circled times'],
  742. [8869, 'perpendicular'],
  743. [8901, 'dot operator'],
  744. [8968, 'left ceiling'],
  745. [8969, 'right ceiling'],
  746. [8970, 'left floor'],
  747. [8971, 'right floor'],
  748. [9001, 'left-pointing angle bracket'],
  749. [9002, 'right-pointing angle bracket'],
  750. [9674, 'lozenge'],
  751. [9824, 'black spade suit'],
  752. [9827, 'black club suit'],
  753. [9829, 'black heart suit'],
  754. [9830, 'black diamond suit'],
  755. [8194, 'en space'],
  756. [8195, 'em space'],
  757. [8201, 'thin space'],
  758. [8204, 'zero width non-joiner'],
  759. [8205, 'zero width joiner'],
  760. [8206, 'left-to-right mark'],
  761. [8207, 'right-to-left mark']
  762. ]
  763. }
  764. ];
  765. };
  766. const charmapFilter = (charmap) => {
  767. return global.grep(charmap, (item) => {
  768. return isArray(item) && item.length === 2;
  769. });
  770. };
  771. const getCharsFromOption = (optionValue) => {
  772. if (isArray(optionValue)) {
  773. return charmapFilter(optionValue);
  774. }
  775. if (typeof optionValue === 'function') {
  776. return optionValue();
  777. }
  778. return [];
  779. };
  780. const extendCharMap = (editor, charmap) => {
  781. const userCharMap = getCharMap$1(editor);
  782. if (userCharMap) {
  783. charmap = [{ name: UserDefined, characters: getCharsFromOption(userCharMap) }];
  784. }
  785. const userCharMapAppend = getCharMapAppend(editor);
  786. if (userCharMapAppend) {
  787. const userDefinedGroup = global.grep(charmap, (cg) => cg.name === UserDefined);
  788. if (userDefinedGroup.length) {
  789. userDefinedGroup[0].characters = [...userDefinedGroup[0].characters, ...getCharsFromOption(userCharMapAppend)];
  790. return charmap;
  791. }
  792. return charmap.concat({ name: UserDefined, characters: getCharsFromOption(userCharMapAppend) });
  793. }
  794. return charmap;
  795. };
  796. const getCharMap = (editor) => {
  797. const groups = extendCharMap(editor, getDefaultCharMap());
  798. return groups.length > 1 ? [
  799. {
  800. name: 'All',
  801. characters: bind(groups, (g) => g.characters)
  802. }
  803. ].concat(groups) : groups;
  804. };
  805. const get = (editor) => {
  806. const getCharMap$1 = () => {
  807. return getCharMap(editor);
  808. };
  809. const insertChar$1 = (chr) => {
  810. insertChar(editor, chr);
  811. };
  812. return {
  813. getCharMap: getCharMap$1,
  814. insertChar: insertChar$1
  815. };
  816. };
  817. const charMatches = (charCode, name, lowerCasePattern) => {
  818. if (contains(fromCodePoint(charCode).toLowerCase(), lowerCasePattern)) {
  819. return true;
  820. }
  821. else {
  822. return contains(name.toLowerCase(), lowerCasePattern) || contains(name.toLowerCase().replace(/\s+/g, ''), lowerCasePattern);
  823. }
  824. };
  825. const scan = (group, pattern) => {
  826. const matches = [];
  827. const lowerCasePattern = pattern.toLowerCase();
  828. each(group.characters, (g) => {
  829. if (charMatches(g[0], g[1], lowerCasePattern)) {
  830. matches.push(g);
  831. }
  832. });
  833. return map(matches, (m) => ({
  834. text: m[1],
  835. value: fromCodePoint(m[0]),
  836. icon: fromCodePoint(m[0])
  837. }));
  838. };
  839. const patternName = 'pattern';
  840. const open = (editor, charMap) => {
  841. const makeGroupItems = () => [
  842. {
  843. label: 'Search',
  844. type: 'input',
  845. name: patternName
  846. },
  847. {
  848. type: 'collection',
  849. name: 'results'
  850. // TODO TINY-3229 implement collection columns properly
  851. // columns: 'auto'
  852. }
  853. ];
  854. const makeTabs = () => map(charMap, (charGroup) => ({
  855. title: charGroup.name,
  856. name: charGroup.name,
  857. items: makeGroupItems()
  858. }));
  859. const makePanel = () => ({ type: 'panel', items: makeGroupItems() });
  860. const makeTabPanel = () => ({ type: 'tabpanel', tabs: makeTabs() });
  861. const currentTab = charMap.length === 1 ? Cell(UserDefined) : Cell('All');
  862. const scanAndSet = (dialogApi, pattern) => {
  863. find(charMap, (group) => group.name === currentTab.get()).each((f) => {
  864. const items = scan(f, pattern);
  865. dialogApi.setData({
  866. results: items
  867. });
  868. });
  869. };
  870. const SEARCH_DELAY = 40;
  871. const updateFilter = last((dialogApi) => {
  872. const pattern = dialogApi.getData().pattern;
  873. scanAndSet(dialogApi, pattern);
  874. }, SEARCH_DELAY);
  875. const body = charMap.length === 1 ? makePanel() : makeTabPanel();
  876. const initialData = {
  877. pattern: '',
  878. results: scan(charMap[0], '')
  879. };
  880. const bridgeSpec = {
  881. title: 'Special Character',
  882. size: 'normal',
  883. body,
  884. buttons: [
  885. {
  886. type: 'cancel',
  887. name: 'close',
  888. text: 'Close',
  889. primary: true
  890. }
  891. ],
  892. initialData,
  893. onAction: (api, details) => {
  894. if (details.name === 'results') {
  895. insertChar(editor, details.value);
  896. api.close();
  897. }
  898. },
  899. onTabChange: (dialogApi, details) => {
  900. currentTab.set(details.newTabName);
  901. updateFilter.throttle(dialogApi);
  902. },
  903. onChange: (dialogApi, changeData) => {
  904. if (changeData.name === patternName) {
  905. updateFilter.throttle(dialogApi);
  906. }
  907. }
  908. };
  909. const dialogApi = editor.windowManager.open(bridgeSpec);
  910. dialogApi.focus(patternName);
  911. };
  912. const register$1 = (editor, charMap) => {
  913. editor.addCommand('mceShowCharmap', () => {
  914. open(editor, charMap);
  915. });
  916. };
  917. const init = (editor, all) => {
  918. editor.ui.registry.addAutocompleter('charmap', {
  919. trigger: ':',
  920. columns: 'auto',
  921. minChars: 2,
  922. fetch: (pattern, _maxResults) => new Promise((resolve, _reject) => {
  923. resolve(scan(all, pattern));
  924. }),
  925. onAction: (autocompleteApi, rng, value) => {
  926. editor.selection.setRng(rng);
  927. editor.insertContent(value);
  928. autocompleteApi.hide();
  929. }
  930. });
  931. };
  932. const onSetupEditable = (editor) => (api) => {
  933. const nodeChanged = () => {
  934. api.setEnabled(editor.selection.isEditable());
  935. };
  936. editor.on('NodeChange', nodeChanged);
  937. nodeChanged();
  938. return () => {
  939. editor.off('NodeChange', nodeChanged);
  940. };
  941. };
  942. const register = (editor) => {
  943. const onAction = () => editor.execCommand('mceShowCharmap');
  944. editor.ui.registry.addButton('charmap', {
  945. icon: 'insert-character',
  946. tooltip: 'Special character',
  947. onAction,
  948. onSetup: onSetupEditable(editor)
  949. });
  950. editor.ui.registry.addMenuItem('charmap', {
  951. icon: 'insert-character',
  952. text: 'Special character...',
  953. onAction,
  954. onSetup: onSetupEditable(editor)
  955. });
  956. };
  957. var Plugin = () => {
  958. global$1.add('charmap', (editor) => {
  959. register$2(editor);
  960. const charMap = getCharMap(editor);
  961. register$1(editor, charMap);
  962. register(editor);
  963. init(editor, charMap[0]);
  964. return get(editor);
  965. });
  966. };
  967. Plugin();
  968. /** *****
  969. * DO NOT EXPORT ANYTHING
  970. *
  971. * IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
  972. *******/
  973. })();