plugin.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  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. /* eslint-disable @typescript-eslint/no-wrapper-object-types */
  8. const hasProto = (v, constructor, predicate) => {
  9. var _a;
  10. if (predicate(v, constructor.prototype)) {
  11. return true;
  12. }
  13. else {
  14. // String-based fallback time
  15. return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
  16. }
  17. };
  18. const typeOf = (x) => {
  19. const t = typeof x;
  20. if (x === null) {
  21. return 'null';
  22. }
  23. else if (t === 'object' && Array.isArray(x)) {
  24. return 'array';
  25. }
  26. else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
  27. return 'string';
  28. }
  29. else {
  30. return t;
  31. }
  32. };
  33. const isType = (type) => (value) => typeOf(value) === type;
  34. const isSimpleType = (type) => (value) => typeof value === type;
  35. const isString = isType('string');
  36. const isBoolean = isSimpleType('boolean');
  37. const isNullable = (a) => a === null || a === undefined;
  38. const isNonNullable = (a) => !isNullable(a);
  39. const isFunction = isSimpleType('function');
  40. const constant = (value) => {
  41. return () => {
  42. return value;
  43. };
  44. };
  45. const never = constant(false);
  46. /**
  47. * The `Optional` type represents a value (of any type) that potentially does
  48. * not exist. Any `Optional<T>` can either be a `Some<T>` (in which case the
  49. * value does exist) or a `None` (in which case the value does not exist). This
  50. * module defines a whole lot of FP-inspired utility functions for dealing with
  51. * `Optional` objects.
  52. *
  53. * Comparison with null or undefined:
  54. * - We don't get fancy null coalescing operators with `Optional`
  55. * - We do get fancy helper functions with `Optional`
  56. * - `Optional` support nesting, and allow for the type to still be nullable (or
  57. * another `Optional`)
  58. * - There is no option to turn off strict-optional-checks like there is for
  59. * strict-null-checks
  60. */
  61. class Optional {
  62. // The internal representation has a `tag` and a `value`, but both are
  63. // private: able to be console.logged, but not able to be accessed by code
  64. constructor(tag, value) {
  65. this.tag = tag;
  66. this.value = value;
  67. }
  68. // --- Identities ---
  69. /**
  70. * Creates a new `Optional<T>` that **does** contain a value.
  71. */
  72. static some(value) {
  73. return new Optional(true, value);
  74. }
  75. /**
  76. * Create a new `Optional<T>` that **does not** contain a value. `T` can be
  77. * any type because we don't actually have a `T`.
  78. */
  79. static none() {
  80. return Optional.singletonNone;
  81. }
  82. /**
  83. * Perform a transform on an `Optional` type. Regardless of whether this
  84. * `Optional` contains a value or not, `fold` will return a value of type `U`.
  85. * If this `Optional` does not contain a value, the `U` will be created by
  86. * calling `onNone`. If this `Optional` does contain a value, the `U` will be
  87. * created by calling `onSome`.
  88. *
  89. * For the FP enthusiasts in the room, this function:
  90. * 1. Could be used to implement all of the functions below
  91. * 2. Forms a catamorphism
  92. */
  93. fold(onNone, onSome) {
  94. if (this.tag) {
  95. return onSome(this.value);
  96. }
  97. else {
  98. return onNone();
  99. }
  100. }
  101. /**
  102. * Determine if this `Optional` object contains a value.
  103. */
  104. isSome() {
  105. return this.tag;
  106. }
  107. /**
  108. * Determine if this `Optional` object **does not** contain a value.
  109. */
  110. isNone() {
  111. return !this.tag;
  112. }
  113. // --- Functor (name stolen from Haskell / maths) ---
  114. /**
  115. * Perform a transform on an `Optional` object, **if** there is a value. If
  116. * you provide a function to turn a T into a U, this is the function you use
  117. * to turn an `Optional<T>` into an `Optional<U>`. If this **does** contain
  118. * a value then the output will also contain a value (that value being the
  119. * output of `mapper(this.value)`), and if this **does not** contain a value
  120. * then neither will the output.
  121. */
  122. map(mapper) {
  123. if (this.tag) {
  124. return Optional.some(mapper(this.value));
  125. }
  126. else {
  127. return Optional.none();
  128. }
  129. }
  130. // --- Monad (name stolen from Haskell / maths) ---
  131. /**
  132. * Perform a transform on an `Optional` object, **if** there is a value.
  133. * Unlike `map`, here the transform itself also returns an `Optional`.
  134. */
  135. bind(binder) {
  136. if (this.tag) {
  137. return binder(this.value);
  138. }
  139. else {
  140. return Optional.none();
  141. }
  142. }
  143. // --- Traversable (name stolen from Haskell / maths) ---
  144. /**
  145. * For a given predicate, this function finds out if there **exists** a value
  146. * inside this `Optional` object that meets the predicate. In practice, this
  147. * means that for `Optional`s that do not contain a value it returns false (as
  148. * no predicate-meeting value exists).
  149. */
  150. exists(predicate) {
  151. return this.tag && predicate(this.value);
  152. }
  153. /**
  154. * For a given predicate, this function finds out if **all** the values inside
  155. * this `Optional` object meet the predicate. In practice, this means that
  156. * for `Optional`s that do not contain a value it returns true (as all 0
  157. * objects do meet the predicate).
  158. */
  159. forall(predicate) {
  160. return !this.tag || predicate(this.value);
  161. }
  162. filter(predicate) {
  163. if (!this.tag || predicate(this.value)) {
  164. return this;
  165. }
  166. else {
  167. return Optional.none();
  168. }
  169. }
  170. // --- Getters ---
  171. /**
  172. * Get the value out of the inside of the `Optional` object, using a default
  173. * `replacement` value if the provided `Optional` object does not contain a
  174. * value.
  175. */
  176. getOr(replacement) {
  177. return this.tag ? this.value : replacement;
  178. }
  179. /**
  180. * Get the value out of the inside of the `Optional` object, using a default
  181. * `replacement` value if the provided `Optional` object does not contain a
  182. * value. Unlike `getOr`, in this method the `replacement` object is also
  183. * `Optional` - meaning that this method will always return an `Optional`.
  184. */
  185. or(replacement) {
  186. return this.tag ? this : 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` value is
  192. * "thunked" - that is to say that you don't pass a value to `getOrThunk`, you
  193. * pass a function which (if called) will **return** the `value` you want to
  194. * use.
  195. */
  196. getOrThunk(thunk) {
  197. return this.tag ? this.value : thunk();
  198. }
  199. /**
  200. * Get the value out of the inside of the `Optional` object, using a default
  201. * `replacement` value if the provided Optional object does not contain a
  202. * value.
  203. *
  204. * Unlike `or`, in this method the `replacement` value is "thunked" - that is
  205. * to say that you don't pass a value to `orThunk`, you pass a function which
  206. * (if called) will **return** the `value` you want to use.
  207. *
  208. * Unlike `getOrThunk`, in this method the `replacement` value is also
  209. * `Optional`, meaning that this method will always return an `Optional`.
  210. */
  211. orThunk(thunk) {
  212. return this.tag ? this : thunk();
  213. }
  214. /**
  215. * Get the value out of the inside of the `Optional` object, throwing an
  216. * exception if the provided `Optional` object does not contain a value.
  217. *
  218. * WARNING:
  219. * You should only be using this function if you know that the `Optional`
  220. * object **is not** empty (otherwise you're throwing exceptions in production
  221. * code, which is bad).
  222. *
  223. * In tests this is more acceptable.
  224. *
  225. * Prefer other methods to this, such as `.each`.
  226. */
  227. getOrDie(message) {
  228. if (!this.tag) {
  229. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  230. }
  231. else {
  232. return this.value;
  233. }
  234. }
  235. // --- Interop with null and undefined ---
  236. /**
  237. * Creates an `Optional` value from a nullable (or undefined-able) input.
  238. * Null, or undefined, is converted to `None`, and anything else is converted
  239. * to `Some`.
  240. */
  241. static from(value) {
  242. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  243. }
  244. /**
  245. * Converts an `Optional` to a nullable type, by getting the value if it
  246. * exists, or returning `null` if it does not.
  247. */
  248. getOrNull() {
  249. return this.tag ? this.value : null;
  250. }
  251. /**
  252. * Converts an `Optional` to an undefined-able type, by getting the value if
  253. * it exists, or returning `undefined` if it does not.
  254. */
  255. getOrUndefined() {
  256. return this.value;
  257. }
  258. // --- Utilities ---
  259. /**
  260. * If the `Optional` contains a value, perform an action on that value.
  261. * Unlike the rest of the methods on this type, `.each` has side-effects. If
  262. * you want to transform an `Optional<T>` **into** something, then this is not
  263. * the method for you. If you want to use an `Optional<T>` to **do**
  264. * something, then this is the method for you - provided you're okay with not
  265. * doing anything in the case where the `Optional` doesn't have a value inside
  266. * it. If you're not sure whether your use-case fits into transforming
  267. * **into** something or **doing** something, check whether it has a return
  268. * value. If it does, you should be performing a transform.
  269. */
  270. each(worker) {
  271. if (this.tag) {
  272. worker(this.value);
  273. }
  274. }
  275. /**
  276. * Turn the `Optional` object into an array that contains all of the values
  277. * stored inside the `Optional`. In practice, this means the output will have
  278. * either 0 or 1 elements.
  279. */
  280. toArray() {
  281. return this.tag ? [this.value] : [];
  282. }
  283. /**
  284. * Turn the `Optional` object into a string for debugging or printing. Not
  285. * recommended for production code, but good for debugging. Also note that
  286. * these days an `Optional` object can be logged to the console directly, and
  287. * its inner value (if it exists) will be visible.
  288. */
  289. toString() {
  290. return this.tag ? `some(${this.value})` : 'none()';
  291. }
  292. }
  293. // Sneaky optimisation: every instance of Optional.none is identical, so just
  294. // reuse the same object
  295. Optional.singletonNone = new Optional(false);
  296. /**
  297. * Adds two numbers, and wrap to a range.
  298. * If the result overflows to the right, snap to the left.
  299. * If the result overflows to the left, snap to the right.
  300. */
  301. // the division is meant to get a number between 0 and 1 for more information check this discussion: https://stackoverflow.com/questions/58285941/how-to-replace-math-random-with-crypto-getrandomvalues-and-keep-same-result
  302. const random = () => window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295;
  303. /**
  304. * Generate a unique identifier.
  305. *
  306. * The unique portion of the identifier only contains an underscore
  307. * and digits, so that it may safely be used within HTML attributes.
  308. *
  309. * The chance of generating a non-unique identifier has been minimized
  310. * by combining the current time, a random number and a one-up counter.
  311. *
  312. * generate :: String -> String
  313. */
  314. let unique = 0;
  315. const generate = (prefix) => {
  316. const date = new Date();
  317. const time = date.getTime();
  318. const random$1 = Math.floor(random() * 1000000000);
  319. unique++;
  320. return prefix + '_' + random$1 + unique + String(time);
  321. };
  322. const insertTable = (editor, columns, rows) => {
  323. editor.execCommand('mceInsertTable', false, { rows, columns });
  324. };
  325. const insertBlob = (editor, base64, blob) => {
  326. const blobCache = editor.editorUpload.blobCache;
  327. const blobInfo = blobCache.create(generate('mceu'), blob, base64);
  328. blobCache.add(blobInfo);
  329. editor.insertContent(editor.dom.createHTML('img', { src: blobInfo.blobUri() }));
  330. };
  331. const blobToBase64 = (blob) => {
  332. return new Promise((resolve) => {
  333. const reader = new FileReader();
  334. reader.onloadend = () => {
  335. resolve(reader.result.split(',')[1]);
  336. };
  337. reader.readAsDataURL(blob);
  338. });
  339. };
  340. var global = tinymce.util.Tools.resolve('tinymce.util.Delay');
  341. const pickFile = (editor) => new Promise((resolve) => {
  342. let resolved = false;
  343. const fileInput = document.createElement('input');
  344. fileInput.type = 'file';
  345. fileInput.accept = 'image/*';
  346. fileInput.style.position = 'fixed';
  347. fileInput.style.left = '0';
  348. fileInput.style.top = '0';
  349. fileInput.style.opacity = '0.001';
  350. document.body.appendChild(fileInput);
  351. const resolveFileInput = (value) => {
  352. var _a;
  353. if (!resolved) {
  354. (_a = fileInput.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(fileInput);
  355. resolved = true;
  356. resolve(value);
  357. }
  358. };
  359. const changeHandler = (e) => {
  360. resolveFileInput(Array.prototype.slice.call(e.target.files));
  361. };
  362. fileInput.addEventListener('input', changeHandler);
  363. fileInput.addEventListener('change', changeHandler);
  364. const cancelHandler = (e) => {
  365. const cleanup = () => {
  366. resolveFileInput([]);
  367. };
  368. if (!resolved) {
  369. if (e.type === 'focusin') {
  370. // Chrome will fire `focusin` before the input `change` event
  371. global.setEditorTimeout(editor, cleanup, 1000);
  372. }
  373. else {
  374. cleanup();
  375. }
  376. }
  377. editor.off('focusin remove', cancelHandler);
  378. };
  379. editor.on('focusin remove', cancelHandler);
  380. fileInput.click();
  381. });
  382. const register$1 = (editor) => {
  383. editor.on('PreInit', () => {
  384. if (!editor.queryCommandSupported('QuickbarInsertImage')) {
  385. editor.addCommand('QuickbarInsertImage', () => {
  386. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  387. pickFile(editor).then((files) => {
  388. if (files.length > 0) {
  389. const blob = files[0];
  390. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  391. blobToBase64(blob).then((base64) => {
  392. insertBlob(editor, base64, blob);
  393. });
  394. }
  395. });
  396. });
  397. }
  398. });
  399. };
  400. const option = (name) => (editor) => editor.options.get(name);
  401. const register = (editor) => {
  402. const registerOption = editor.options.register;
  403. const toolbarProcessor = (defaultValue) => (value) => {
  404. const valid = isBoolean(value) || isString(value);
  405. if (valid) {
  406. if (isBoolean(value)) {
  407. return { value: value ? defaultValue : '', valid };
  408. }
  409. else {
  410. return { value: value.trim(), valid };
  411. }
  412. }
  413. else {
  414. return { valid: false, message: 'Must be a boolean or string.' };
  415. }
  416. };
  417. const defaultSelectionToolbar = 'bold italic | quicklink h2 h3 blockquote';
  418. registerOption('quickbars_selection_toolbar', {
  419. processor: toolbarProcessor(defaultSelectionToolbar),
  420. default: defaultSelectionToolbar
  421. });
  422. const defaultInsertToolbar = 'quickimage quicktable';
  423. registerOption('quickbars_insert_toolbar', {
  424. processor: toolbarProcessor(defaultInsertToolbar),
  425. default: defaultInsertToolbar
  426. });
  427. const defaultImageToolbar = 'alignleft aligncenter alignright';
  428. registerOption('quickbars_image_toolbar', {
  429. processor: toolbarProcessor(defaultImageToolbar),
  430. default: defaultImageToolbar
  431. });
  432. };
  433. const getTextSelectionToolbarItems = option('quickbars_selection_toolbar');
  434. const getInsertToolbarItems = option('quickbars_insert_toolbar');
  435. const getImageToolbarItems = option('quickbars_image_toolbar');
  436. const setupButtons = (editor) => {
  437. editor.ui.registry.addButton('quickimage', {
  438. icon: 'image',
  439. tooltip: 'Insert image',
  440. onAction: () => editor.execCommand('QuickbarInsertImage')
  441. });
  442. editor.ui.registry.addButton('quicktable', {
  443. icon: 'table',
  444. tooltip: 'Insert table',
  445. onAction: () => {
  446. insertTable(editor, 2, 2);
  447. }
  448. });
  449. };
  450. const fromHtml = (html, scope) => {
  451. const doc = scope || document;
  452. const div = doc.createElement('div');
  453. div.innerHTML = html;
  454. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  455. const message = 'HTML does not have a single root node';
  456. // eslint-disable-next-line no-console
  457. console.error(message, html);
  458. throw new Error(message);
  459. }
  460. return fromDom(div.childNodes[0]);
  461. };
  462. const fromTag = (tag, scope) => {
  463. const doc = scope || document;
  464. const node = doc.createElement(tag);
  465. return fromDom(node);
  466. };
  467. const fromText = (text, scope) => {
  468. const doc = scope || document;
  469. const node = doc.createTextNode(text);
  470. return fromDom(node);
  471. };
  472. const fromDom = (node) => {
  473. // TODO: Consider removing this check, but left atm for safety
  474. if (node === null || node === undefined) {
  475. throw new Error('Node cannot be null or undefined');
  476. }
  477. return {
  478. dom: node
  479. };
  480. };
  481. const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
  482. // tslint:disable-next-line:variable-name
  483. const SugarElement = {
  484. fromHtml,
  485. fromTag,
  486. fromText,
  487. fromDom,
  488. fromPoint
  489. };
  490. const ELEMENT = 1;
  491. const is = (element, selector) => {
  492. const dom = element.dom;
  493. if (dom.nodeType !== ELEMENT) {
  494. return false;
  495. }
  496. else {
  497. const elem = dom;
  498. if (elem.matches !== undefined) {
  499. return elem.matches(selector);
  500. }
  501. else if (elem.msMatchesSelector !== undefined) {
  502. return elem.msMatchesSelector(selector);
  503. }
  504. else if (elem.webkitMatchesSelector !== undefined) {
  505. return elem.webkitMatchesSelector(selector);
  506. }
  507. else if (elem.mozMatchesSelector !== undefined) {
  508. // cast to any as mozMatchesSelector doesn't exist in TS DOM lib
  509. return elem.mozMatchesSelector(selector);
  510. }
  511. else {
  512. throw new Error('Browser lacks native selectors');
  513. } // unfortunately we can't throw this on startup :(
  514. }
  515. };
  516. const name = (element) => {
  517. const r = element.dom.nodeName;
  518. return r.toLowerCase();
  519. };
  520. const has$1 = (element, key) => {
  521. const dom = element.dom;
  522. // return false for non-element nodes, no point in throwing an error
  523. return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
  524. };
  525. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  526. if (is(scope, a)) {
  527. return Optional.some(scope);
  528. }
  529. else if (isFunction(isRoot) && isRoot(scope)) {
  530. return Optional.none();
  531. }
  532. else {
  533. return ancestor(scope, a, isRoot);
  534. }
  535. };
  536. const ancestor$1 = (scope, predicate, isRoot) => {
  537. let element = scope.dom;
  538. const stop = isFunction(isRoot) ? isRoot : never;
  539. while (element.parentNode) {
  540. element = element.parentNode;
  541. const el = SugarElement.fromDom(element);
  542. if (predicate(el)) {
  543. return Optional.some(el);
  544. }
  545. else if (stop(el)) {
  546. break;
  547. }
  548. }
  549. return Optional.none();
  550. };
  551. const closest$2 = (scope, predicate, isRoot) => {
  552. // This is required to avoid ClosestOrAncestor passing the predicate to itself
  553. const is = (s, test) => test(s);
  554. return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
  555. };
  556. const ancestor = (scope, selector, isRoot) => ancestor$1(scope, (e) => is(e, selector), isRoot);
  557. // Returns Some(closest ancestor element (sugared)) matching 'selector' up to isRoot, or None() otherwise
  558. const closest$1 = (scope, selector, isRoot) => {
  559. const is$1 = (element, selector) => is(element, selector);
  560. return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot);
  561. };
  562. // IE11 Can return undefined for a classList on elements such as math, so we make sure it's not undefined before attempting to use it.
  563. const supports = (element) => element.dom.classList !== undefined;
  564. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  565. const closest = (scope, predicate, isRoot) => closest$2(scope, predicate, isRoot).isSome();
  566. const addToEditor$1 = (editor) => {
  567. const insertToolbarItems = getInsertToolbarItems(editor);
  568. if (insertToolbarItems.length > 0) {
  569. editor.ui.registry.addContextToolbar('quickblock', {
  570. predicate: (node) => {
  571. const sugarNode = SugarElement.fromDom(node);
  572. const textBlockElementsMap = editor.schema.getTextBlockElements();
  573. const isRoot = (elem) => elem.dom === editor.getBody();
  574. return !has$1(sugarNode, 'data-mce-bogus') && closest$1(sugarNode, 'table,[data-mce-bogus="all"]', isRoot).fold(() => closest(sugarNode, (elem) => name(elem) in textBlockElementsMap && editor.dom.isEmpty(elem.dom), isRoot), never);
  575. },
  576. items: insertToolbarItems,
  577. position: 'line',
  578. scope: 'editor'
  579. });
  580. }
  581. };
  582. const addToEditor = (editor) => {
  583. const isEditable = (node) => editor.dom.isEditable(node);
  584. const isInEditableContext = (el) => isEditable(el.parentElement);
  585. const isImage = (node) => {
  586. const isImageFigure = node.nodeName === 'FIGURE' && /image/i.test(node.className);
  587. const isImage = node.nodeName === 'IMG' || isImageFigure;
  588. const isPagebreak = has(SugarElement.fromDom(node), 'mce-pagebreak');
  589. return isImage && isInEditableContext(node) && !isPagebreak;
  590. };
  591. const imageToolbarItems = getImageToolbarItems(editor);
  592. if (imageToolbarItems.length > 0) {
  593. editor.ui.registry.addContextToolbar('imageselection', {
  594. predicate: isImage,
  595. items: imageToolbarItems,
  596. position: 'node'
  597. });
  598. }
  599. const textToolbarItems = getTextSelectionToolbarItems(editor);
  600. if (textToolbarItems.length > 0) {
  601. editor.ui.registry.addContextToolbar('textselection', {
  602. predicate: (node) => !isImage(node) && !editor.selection.isCollapsed() && isEditable(node),
  603. items: textToolbarItems,
  604. position: 'selection',
  605. scope: 'editor'
  606. });
  607. }
  608. };
  609. var Plugin = () => {
  610. global$1.add('quickbars', (editor) => {
  611. register(editor);
  612. register$1(editor);
  613. setupButtons(editor);
  614. addToEditor$1(editor);
  615. addToEditor(editor);
  616. });
  617. };
  618. Plugin();
  619. /** *****
  620. * DO NOT EXPORT ANYTHING
  621. *
  622. * IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
  623. *******/
  624. })();