@ckeditor/ckeditor5-core 47.6.1 → 48.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/LICENSE.md +1 -1
  2. package/{src → dist}/editor/editorconfig.d.ts +295 -20
  3. package/dist/editor/utils/normalizerootsconfig.d.ts +50 -0
  4. package/dist/index-content.css +10 -10
  5. package/dist/index-editor.css +5 -5
  6. package/dist/index.css +10 -16
  7. package/dist/index.css.map +1 -1
  8. package/{src → dist}/index.d.ts +2 -1
  9. package/dist/index.js +161 -6
  10. package/dist/index.js.map +1 -1
  11. package/package.json +23 -43
  12. package/lang/contexts.json +0 -38
  13. package/lang/translations/af.po +0 -156
  14. package/lang/translations/ar.po +0 -156
  15. package/lang/translations/ast.po +0 -156
  16. package/lang/translations/az.po +0 -156
  17. package/lang/translations/be.po +0 -156
  18. package/lang/translations/bg.po +0 -156
  19. package/lang/translations/bn.po +0 -156
  20. package/lang/translations/bs.po +0 -156
  21. package/lang/translations/ca.po +0 -156
  22. package/lang/translations/cs.po +0 -156
  23. package/lang/translations/da.po +0 -156
  24. package/lang/translations/de-ch.po +0 -156
  25. package/lang/translations/de.po +0 -156
  26. package/lang/translations/el.po +0 -156
  27. package/lang/translations/en-au.po +0 -156
  28. package/lang/translations/en-gb.po +0 -156
  29. package/lang/translations/en.po +0 -156
  30. package/lang/translations/eo.po +0 -156
  31. package/lang/translations/es-co.po +0 -156
  32. package/lang/translations/es.po +0 -156
  33. package/lang/translations/et.po +0 -156
  34. package/lang/translations/eu.po +0 -156
  35. package/lang/translations/fa.po +0 -156
  36. package/lang/translations/fi.po +0 -156
  37. package/lang/translations/fr.po +0 -156
  38. package/lang/translations/gl.po +0 -156
  39. package/lang/translations/gu.po +0 -156
  40. package/lang/translations/he.po +0 -156
  41. package/lang/translations/hi.po +0 -156
  42. package/lang/translations/hr.po +0 -156
  43. package/lang/translations/hu.po +0 -156
  44. package/lang/translations/hy.po +0 -156
  45. package/lang/translations/id.po +0 -156
  46. package/lang/translations/it.po +0 -156
  47. package/lang/translations/ja.po +0 -156
  48. package/lang/translations/jv.po +0 -156
  49. package/lang/translations/kk.po +0 -156
  50. package/lang/translations/km.po +0 -156
  51. package/lang/translations/kn.po +0 -156
  52. package/lang/translations/ko.po +0 -156
  53. package/lang/translations/ku.po +0 -156
  54. package/lang/translations/lt.po +0 -156
  55. package/lang/translations/lv.po +0 -156
  56. package/lang/translations/ms.po +0 -156
  57. package/lang/translations/nb.po +0 -156
  58. package/lang/translations/ne.po +0 -156
  59. package/lang/translations/nl.po +0 -156
  60. package/lang/translations/no.po +0 -156
  61. package/lang/translations/oc.po +0 -156
  62. package/lang/translations/pl.po +0 -156
  63. package/lang/translations/pt-br.po +0 -156
  64. package/lang/translations/pt.po +0 -156
  65. package/lang/translations/ro.po +0 -156
  66. package/lang/translations/ru.po +0 -156
  67. package/lang/translations/si.po +0 -156
  68. package/lang/translations/sk.po +0 -156
  69. package/lang/translations/sl.po +0 -156
  70. package/lang/translations/sq.po +0 -156
  71. package/lang/translations/sr-latn.po +0 -156
  72. package/lang/translations/sr.po +0 -156
  73. package/lang/translations/sv.po +0 -156
  74. package/lang/translations/th.po +0 -156
  75. package/lang/translations/ti.po +0 -156
  76. package/lang/translations/tk.po +0 -156
  77. package/lang/translations/tr.po +0 -156
  78. package/lang/translations/tt.po +0 -156
  79. package/lang/translations/ug.po +0 -156
  80. package/lang/translations/uk.po +0 -156
  81. package/lang/translations/ur.po +0 -156
  82. package/lang/translations/uz.po +0 -156
  83. package/lang/translations/vi.po +0 -156
  84. package/lang/translations/zh-cn.po +0 -156
  85. package/lang/translations/zh.po +0 -156
  86. package/src/accessibility.js +0 -332
  87. package/src/augmentation.js +0 -5
  88. package/src/command.js +0 -221
  89. package/src/commandcollection.js +0 -87
  90. package/src/context.js +0 -315
  91. package/src/contextplugin.js +0 -59
  92. package/src/editingkeystrokehandler.js +0 -61
  93. package/src/editor/editor.js +0 -1010
  94. package/src/editor/editorconfig.js +0 -5
  95. package/src/editor/utils/attachtoform.js +0 -57
  96. package/src/editor/utils/editorusagedata.js +0 -127
  97. package/src/editor/utils/elementapimixin.js +0 -42
  98. package/src/editor/utils/securesourceelement.js +0 -35
  99. package/src/index.js +0 -22
  100. package/src/multicommand.js +0 -79
  101. package/src/pendingactions.js +0 -127
  102. package/src/plugin.js +0 -132
  103. package/src/plugincollection.js +0 -506
  104. package/src/typings.js +0 -5
  105. package/theme/core.css +0 -21
  106. /package/{src → dist}/accessibility.d.ts +0 -0
  107. /package/{src → dist}/augmentation.d.ts +0 -0
  108. /package/{src → dist}/command.d.ts +0 -0
  109. /package/{src → dist}/commandcollection.d.ts +0 -0
  110. /package/{src → dist}/context.d.ts +0 -0
  111. /package/{src → dist}/contextplugin.d.ts +0 -0
  112. /package/{src → dist}/editingkeystrokehandler.d.ts +0 -0
  113. /package/{src → dist}/editor/editor.d.ts +0 -0
  114. /package/{src → dist}/editor/utils/attachtoform.d.ts +0 -0
  115. /package/{src → dist}/editor/utils/editorusagedata.d.ts +0 -0
  116. /package/{src → dist}/editor/utils/elementapimixin.d.ts +0 -0
  117. /package/{src → dist}/editor/utils/securesourceelement.d.ts +0 -0
  118. /package/{src → dist}/multicommand.d.ts +0 -0
  119. /package/{src → dist}/pendingactions.d.ts +0 -0
  120. /package/{src → dist}/plugin.d.ts +0 -0
  121. /package/{src → dist}/plugincollection.d.ts +0 -0
  122. /package/{src → dist}/typings.d.ts +0 -0
@@ -1,5 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- export {};
@@ -1,57 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/editor/utils/attachtoform
7
- */
8
- import { isFunction } from 'es-toolkit/compat';
9
- import { CKEditorError } from '@ckeditor/ckeditor5-utils';
10
- /**
11
- * Checks if the editor is initialized on a `<textarea>` element that belongs to a form. If yes, it updates the editor's element
12
- * content before submitting the form.
13
- *
14
- * This helper requires the {@link module:core/editor/utils/elementapimixin~ElementApi ElementApi interface}.
15
- *
16
- * @param editor Editor instance.
17
- */
18
- export function attachToForm(editor) {
19
- if (!isFunction(editor.updateSourceElement)) {
20
- /**
21
- * The editor passed to `attachToForm()` must implement the
22
- * {@link module:core/editor/utils/elementapimixin~ElementApi} interface.
23
- *
24
- * @error attachtoform-missing-elementapi-interface
25
- */
26
- throw new CKEditorError('attachtoform-missing-elementapi-interface', editor);
27
- }
28
- const sourceElement = editor.sourceElement;
29
- // Only when replacing a textarea which is inside of a form element.
30
- if (isTextArea(sourceElement) && sourceElement.form) {
31
- let originalSubmit;
32
- const form = sourceElement.form;
33
- const onSubmit = () => editor.updateSourceElement();
34
- // Replace the original form#submit() to call a custom submit function first.
35
- // Check if #submit is a function because the form might have an input named "submit".
36
- if (isFunction(form.submit)) {
37
- originalSubmit = form.submit;
38
- form.submit = () => {
39
- onSubmit();
40
- originalSubmit.apply(form);
41
- };
42
- }
43
- // Update the replaced textarea with data before each form#submit event.
44
- form.addEventListener('submit', onSubmit);
45
- // Remove the submit listener and revert the original submit method on
46
- // editor#destroy.
47
- editor.on('destroy', () => {
48
- form.removeEventListener('submit', onSubmit);
49
- if (originalSubmit) {
50
- form.submit = originalSubmit;
51
- }
52
- });
53
- }
54
- }
55
- function isTextArea(sourceElement) {
56
- return !!sourceElement && sourceElement.tagName.toLowerCase() === 'textarea';
57
- }
@@ -1,127 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/editor/utils/editorusagedata
7
- */
8
- import { env, global, uid } from '@ckeditor/ckeditor5-utils';
9
- /**
10
- * This part of the code is not executed in open-source implementations using a GPL key.
11
- * It only runs when a specific license key is provided. If you are uncertain whether
12
- * this applies to your installation, please contact our support team.
13
- *
14
- * @internal
15
- */
16
- export function getEditorUsageData(editor) {
17
- return {
18
- sessionId: getSessionId(),
19
- pageSessionId: getPageSessionID(),
20
- hostname: window.location.hostname,
21
- version: globalThis.CKEDITOR_VERSION,
22
- type: getEditorType(editor),
23
- plugins: getPluginsUsageData(editor.plugins),
24
- distribution: getDistributionUsageData(),
25
- env: getEnvUsageData(),
26
- integration: Object.create(null),
27
- menuBar: {
28
- isVisible: !!editor.config.get('menuBar.isVisible')
29
- },
30
- language: {
31
- ui: editor.locale.uiLanguage,
32
- content: editor.locale.contentLanguage
33
- },
34
- toolbar: {
35
- main: getToolbarUsageData(editor.config.get('toolbar')),
36
- block: getToolbarUsageData(editor.config.get('blockToolbar')),
37
- balloon: getToolbarUsageData(editor.config.get('balloonToolbar'))
38
- }
39
- };
40
- }
41
- function getEditorType(editor) {
42
- return Object.getPrototypeOf(editor).constructor.editorName;
43
- }
44
- function getPluginsUsageData(collection) {
45
- return Array
46
- .from(collection)
47
- .filter(([PluginConstructor]) => !!PluginConstructor.pluginName)
48
- .map(([PluginConstructor]) => {
49
- const { pluginName, isContextPlugin, isOfficialPlugin, isPremiumPlugin } = PluginConstructor;
50
- return {
51
- isContext: !!isContextPlugin,
52
- isOfficial: !!isOfficialPlugin,
53
- isPremium: !!isPremiumPlugin,
54
- name: pluginName
55
- };
56
- });
57
- }
58
- function getToolbarUsageData(toolbarConfig) {
59
- if (!toolbarConfig) {
60
- return undefined;
61
- }
62
- const normalizedToolbar = Array.isArray(toolbarConfig) ?
63
- { items: toolbarConfig } :
64
- toolbarConfig;
65
- const flattenToolbarConfigNames = extractToolbarConfigItemsNames(normalizedToolbar.items || []);
66
- const isMultiline = flattenToolbarConfigNames.includes('-');
67
- return {
68
- isMultiline,
69
- shouldNotGroupWhenFull: !!normalizedToolbar.shouldNotGroupWhenFull,
70
- items: stripToolbarSeparatorItems(flattenToolbarConfigNames)
71
- };
72
- function stripToolbarSeparatorItems(items) {
73
- return items.filter((item) => item !== '|' && item !== '-');
74
- }
75
- function extractToolbarConfigItemsNames(items) {
76
- return items.flatMap(item => {
77
- if (typeof item === 'string') {
78
- return [item];
79
- }
80
- return extractToolbarConfigItemsNames(item.items);
81
- });
82
- }
83
- }
84
- function getDistributionUsageData() {
85
- return {
86
- channel: (window[Symbol.for('cke distribution')] || 'sh')
87
- };
88
- }
89
- function getEnvUsageData() {
90
- let os = 'unknown';
91
- let browser = 'unknown';
92
- if (env.isMac) {
93
- os = 'mac';
94
- }
95
- else if (env.isWindows) {
96
- os = 'windows';
97
- }
98
- else if (env.isiOS) {
99
- os = 'ios';
100
- }
101
- else if (env.isAndroid) {
102
- os = 'android';
103
- }
104
- if (env.isGecko) {
105
- browser = 'gecko';
106
- }
107
- else if (env.isBlink) {
108
- browser = 'blink';
109
- }
110
- else if (env.isSafari) {
111
- browser = 'safari';
112
- }
113
- return {
114
- os,
115
- browser
116
- };
117
- }
118
- function getSessionId() {
119
- if (!localStorage.getItem('__ckeditor-session-id')) {
120
- localStorage.setItem('__ckeditor-session-id', uid());
121
- }
122
- return localStorage.getItem('__ckeditor-session-id');
123
- }
124
- function getPageSessionID() {
125
- global.window.CKEDITOR_PAGE_SESSION_ID = global.window.CKEDITOR_PAGE_SESSION_ID || uid();
126
- return global.window.CKEDITOR_PAGE_SESSION_ID;
127
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/editor/utils/elementapimixin
7
- */
8
- import { CKEditorError, setDataInElement } from '@ckeditor/ckeditor5-utils';
9
- /**
10
- * Implementation of the {@link module:core/editor/utils/elementapimixin~ElementApi}.
11
- */
12
- export function ElementApiMixin(base) {
13
- class Mixin extends base {
14
- sourceElement;
15
- updateSourceElement(data) {
16
- if (!this.sourceElement) {
17
- /**
18
- * Cannot update the source element of a detached editor.
19
- *
20
- * The {@link module:core/editor/utils/elementapimixin~ElementApi#updateSourceElement `updateSourceElement()`}
21
- * method cannot be called if you did not pass an element to `Editor.create()`.
22
- *
23
- * @error editor-missing-sourceelement
24
- */
25
- throw new CKEditorError('editor-missing-sourceelement', this);
26
- }
27
- const shouldUpdateSourceElement = this.config.get('updateSourceElementOnDestroy');
28
- const isSourceElementTextArea = this.sourceElement instanceof HTMLTextAreaElement;
29
- // The data returned by the editor might be unsafe, so we want to prevent rendering
30
- // unsafe content inside the source element different than <textarea>, which is considered
31
- // secure. This behavior could be changed by setting the `updateSourceElementOnDestroy`
32
- // configuration option to `true`.
33
- if (!shouldUpdateSourceElement && !isSourceElementTextArea) {
34
- setDataInElement(this.sourceElement, '');
35
- return;
36
- }
37
- const dataToSet = typeof data === 'string' ? data : this.data.get();
38
- setDataInElement(this.sourceElement, dataToSet);
39
- }
40
- }
41
- return Mixin;
42
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/editor/utils/securesourceelement
7
- */
8
- import { CKEditorError } from '@ckeditor/ckeditor5-utils';
9
- /**
10
- * Marks the source element on which the editor was initialized. This prevents other editor instances from using this element.
11
- *
12
- * Running multiple editor instances on the same source element causes various issues and it is
13
- * crucial this helper is called as soon as the source element is known to prevent collisions.
14
- *
15
- * @param editor Editor instance.
16
- * @param sourceElement Element to bind with the editor instance.
17
- */
18
- export function secureSourceElement(editor, sourceElement) {
19
- if (sourceElement.ckeditorInstance) {
20
- /**
21
- * A DOM element used to create the editor (e.g.
22
- * {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`})
23
- * has already been used to create another editor instance. Make sure each editor is
24
- * created with a unique DOM element.
25
- *
26
- * @error editor-source-element-already-used
27
- * @param {HTMLElement} element DOM element that caused the collision.
28
- */
29
- throw new CKEditorError('editor-source-element-already-used', editor);
30
- }
31
- sourceElement.ckeditorInstance = editor;
32
- editor.once('destroy', () => {
33
- delete sourceElement.ckeditorInstance;
34
- });
35
- }
package/src/index.js DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core
7
- */
8
- export { Plugin } from './plugin.js';
9
- export { Command } from './command.js';
10
- export { MultiCommand } from './multicommand.js';
11
- export { CommandCollection } from './commandcollection.js';
12
- export { Context } from './context.js';
13
- export { ContextPlugin } from './contextplugin.js';
14
- export { EditingKeystrokeHandler } from './editingkeystrokehandler.js';
15
- export { Editor } from './editor/editor.js';
16
- export { attachToForm } from './editor/utils/attachtoform.js';
17
- export { ElementApiMixin } from './editor/utils/elementapimixin.js';
18
- export { secureSourceElement } from './editor/utils/securesourceelement.js';
19
- export { PendingActions } from './pendingactions.js';
20
- export { Accessibility, DEFAULT_GROUP_ID as _DEFAULT_ACCESSIBILITY_GROUP_ID } from './accessibility.js';
21
- export { getEditorUsageData as _getEditorUsageData } from './editor/utils/editorusagedata.js';
22
- import './augmentation.js';
@@ -1,79 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/multicommand
7
- */
8
- import { Command } from './command.js';
9
- import { insertToPriorityArray } from '@ckeditor/ckeditor5-utils';
10
- /**
11
- * A CKEditor command that aggregates other commands.
12
- *
13
- * This command is used to proxy multiple commands. The multi-command is enabled when
14
- * at least one of its registered child commands is enabled.
15
- * When executing a multi-command, the first enabled command with highest priority will be executed.
16
- *
17
- * ```ts
18
- * const multiCommand = new MultiCommand( editor );
19
- *
20
- * const commandFoo = new Command( editor );
21
- * const commandBar = new Command( editor );
22
- *
23
- * // Register a child command.
24
- * multiCommand.registerChildCommand( commandFoo );
25
- * // Register a child command with a low priority.
26
- * multiCommand.registerChildCommand( commandBar, { priority: 'low' } );
27
- *
28
- * // Enable one of the commands.
29
- * commandBar.isEnabled = true;
30
- *
31
- * multiCommand.execute(); // Will execute commandBar.
32
- * ```
33
- */
34
- export class MultiCommand extends Command {
35
- /**
36
- * Registered child commands definitions.
37
- */
38
- _childCommandsDefinitions = [];
39
- /**
40
- * @inheritDoc
41
- */
42
- refresh() {
43
- // Override base command refresh(): the command's state is changed when one of child commands changes states.
44
- }
45
- /**
46
- * Executes the first enabled command which has the highest priority of all registered child commands.
47
- *
48
- * @returns The value returned by the {@link module:core/command~Command#execute `command.execute()`}.
49
- */
50
- execute(...args) {
51
- const command = this._getFirstEnabledCommand();
52
- return !!command && command.execute(args);
53
- }
54
- /**
55
- * Registers a child command.
56
- *
57
- * @param options An object with configuration options.
58
- * @param options.priority Priority of a command to register.
59
- */
60
- registerChildCommand(command, options = {}) {
61
- insertToPriorityArray(this._childCommandsDefinitions, { command, priority: options.priority || 'normal' });
62
- // Change multi-command enabled state when one of registered commands changes state.
63
- command.on('change:isEnabled', () => this._checkEnabled());
64
- this._checkEnabled();
65
- }
66
- /**
67
- * Checks if any of child commands is enabled.
68
- */
69
- _checkEnabled() {
70
- this.isEnabled = !!this._getFirstEnabledCommand();
71
- }
72
- /**
73
- * Returns a first enabled command with the highest priority or `undefined` if none of them is enabled.
74
- */
75
- _getFirstEnabledCommand() {
76
- const commandDefinition = this._childCommandsDefinitions.find(({ command }) => command.isEnabled);
77
- return commandDefinition && commandDefinition.command;
78
- }
79
- }
@@ -1,127 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/pendingactions
7
- */
8
- import { ContextPlugin } from './contextplugin.js';
9
- import { CKEditorError, Collection, ObservableMixin } from '@ckeditor/ckeditor5-utils';
10
- /**
11
- * The list of pending editor actions.
12
- *
13
- * This plugin should be used to synchronise plugins that execute long-lasting actions
14
- * (e.g. file upload) with the editor integration. It gives the developer who integrates the editor
15
- * an easy way to check if there are any actions pending whenever such information is needed.
16
- * All plugins that register a pending action also provide a message about the action that is ongoing
17
- * which can be displayed to the user. This lets them decide if they want to interrupt the action or wait.
18
- *
19
- * Adding and updating a pending action:
20
- *
21
- * ```ts
22
- * const pendingActions = editor.plugins.get( 'PendingActions' );
23
- * const action = pendingActions.add( 'Upload in progress: 0%.' );
24
- *
25
- * // You can update the message:
26
- * action.message = 'Upload in progress: 10%.';
27
- * ```
28
- *
29
- * Removing a pending action:
30
- *
31
- * ```ts
32
- * const pendingActions = editor.plugins.get( 'PendingActions' );
33
- * const action = pendingActions.add( 'Unsaved changes.' );
34
- *
35
- * pendingActions.remove( action );
36
- * ```
37
- *
38
- * Getting pending actions:
39
- *
40
- * ```ts
41
- * const pendingActions = editor.plugins.get( 'PendingActions' );
42
- *
43
- * const action1 = pendingActions.add( 'Action 1' );
44
- * const action2 = pendingActions.add( 'Action 2' );
45
- *
46
- * pendingActions.first; // Returns action1
47
- * Array.from( pendingActions ); // Returns [ action1, action2 ]
48
- * ```
49
- *
50
- * This plugin is used by features like {@link module:upload/filerepository~FileRepository} to register their ongoing actions
51
- * and by features like {@link module:autosave/autosave~Autosave} to detect whether there are any ongoing actions.
52
- * Read more about saving the data in the
53
- * {@glink getting-started/setup/getting-and-setting-data Saving and getting data} guide.
54
- */
55
- export class PendingActions extends ContextPlugin {
56
- /**
57
- * A list of pending actions.
58
- */
59
- _actions;
60
- /**
61
- * @inheritDoc
62
- */
63
- static get pluginName() {
64
- return 'PendingActions';
65
- }
66
- /**
67
- * @inheritDoc
68
- */
69
- static get isOfficialPlugin() {
70
- return true;
71
- }
72
- /**
73
- * @inheritDoc
74
- */
75
- init() {
76
- this.set('hasAny', false);
77
- this._actions = new Collection({ idProperty: '_id' });
78
- this._actions.delegate('add', 'remove').to(this);
79
- }
80
- /**
81
- * Adds an action to the list of pending actions.
82
- *
83
- * This method returns an action object with an observable message property.
84
- * The action object can be later used in the {@link #remove} method. It also allows you to change the message.
85
- *
86
- * @param message The action message.
87
- * @returns An observable object that represents a pending action.
88
- */
89
- add(message) {
90
- if (typeof message !== 'string') {
91
- /**
92
- * The message must be a string.
93
- *
94
- * @error pendingactions-add-invalid-message
95
- */
96
- throw new CKEditorError('pendingactions-add-invalid-message', this);
97
- }
98
- const action = new (ObservableMixin())();
99
- action.set('message', message);
100
- this._actions.add(action);
101
- this.hasAny = true;
102
- return action;
103
- }
104
- /**
105
- * Removes an action from the list of pending actions.
106
- *
107
- * @param action An action object.
108
- */
109
- remove(action) {
110
- this._actions.remove(action);
111
- this.hasAny = !!this._actions.length;
112
- }
113
- /**
114
- * Returns the first action from the list or null if the list is empty
115
- *
116
- * @returns The pending action object.
117
- */
118
- get first() {
119
- return this._actions.get(0);
120
- }
121
- /**
122
- * Iterable interface.
123
- */
124
- [Symbol.iterator]() {
125
- return this._actions[Symbol.iterator]();
126
- }
127
- }
package/src/plugin.js DELETED
@@ -1,132 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module core/plugin
7
- */
8
- /* eslint-disable @typescript-eslint/no-invalid-void-type */
9
- import { ObservableMixin } from '@ckeditor/ckeditor5-utils';
10
- /**
11
- * The base class for CKEditor plugin classes.
12
- */
13
- export class Plugin extends /* #__PURE__ */ ObservableMixin() {
14
- /**
15
- * The editor instance.
16
- *
17
- * Note that most editors implement the {@link module:core/editor/editor~Editor#ui} property.
18
- * However, editors with an external UI (i.e. Bootstrap-based) or a headless editor may not have this property or
19
- * throw an error when accessing it.
20
- *
21
- * Because of above, to make plugins more universal, it is recommended to split features into:
22
- * - The "editing" part that uses the {@link module:core/editor/editor~Editor} class without `ui` property.
23
- * - The "UI" part that uses the {@link module:core/editor/editor~Editor} class and accesses `ui` property.
24
- */
25
- editor;
26
- /**
27
- * Holds identifiers for {@link #forceDisabled} mechanism.
28
- */
29
- _disableStack = new Set();
30
- /**
31
- * @inheritDoc
32
- */
33
- constructor(editor) {
34
- super();
35
- this.editor = editor;
36
- this.set('isEnabled', true);
37
- }
38
- /**
39
- * Disables the plugin.
40
- *
41
- * Plugin may be disabled by multiple features or algorithms (at once). When disabling a plugin, unique id should be passed
42
- * (e.g. feature name). The same identifier should be used when {@link #clearForceDisabled enabling back} the plugin.
43
- * The plugin becomes enabled only after all features {@link #clearForceDisabled enabled it back}.
44
- *
45
- * Disabling and enabling a plugin:
46
- *
47
- * ```ts
48
- * plugin.isEnabled; // -> true
49
- * plugin.forceDisabled( 'MyFeature' );
50
- * plugin.isEnabled; // -> false
51
- * plugin.clearForceDisabled( 'MyFeature' );
52
- * plugin.isEnabled; // -> true
53
- * ```
54
- *
55
- * Plugin disabled by multiple features:
56
- *
57
- * ```ts
58
- * plugin.forceDisabled( 'MyFeature' );
59
- * plugin.forceDisabled( 'OtherFeature' );
60
- * plugin.clearForceDisabled( 'MyFeature' );
61
- * plugin.isEnabled; // -> false
62
- * plugin.clearForceDisabled( 'OtherFeature' );
63
- * plugin.isEnabled; // -> true
64
- * ```
65
- *
66
- * Multiple disabling with the same identifier is redundant:
67
- *
68
- * ```ts
69
- * plugin.forceDisabled( 'MyFeature' );
70
- * plugin.forceDisabled( 'MyFeature' );
71
- * plugin.clearForceDisabled( 'MyFeature' );
72
- * plugin.isEnabled; // -> true
73
- * ```
74
- *
75
- * **Note:** some plugins or algorithms may have more complex logic when it comes to enabling or disabling certain plugins,
76
- * so the plugin might be still disabled after {@link #clearForceDisabled} was used.
77
- *
78
- * @param id Unique identifier for disabling. Use the same id when {@link #clearForceDisabled enabling back} the plugin.
79
- */
80
- forceDisabled(id) {
81
- this._disableStack.add(id);
82
- if (this._disableStack.size == 1) {
83
- this.on('set:isEnabled', forceDisable, { priority: 'highest' });
84
- this.isEnabled = false;
85
- }
86
- }
87
- /**
88
- * Clears forced disable previously set through {@link #forceDisabled}. See {@link #forceDisabled}.
89
- *
90
- * @param id Unique identifier, equal to the one passed in {@link #forceDisabled} call.
91
- */
92
- clearForceDisabled(id) {
93
- this._disableStack.delete(id);
94
- if (this._disableStack.size == 0) {
95
- this.off('set:isEnabled', forceDisable);
96
- this.isEnabled = true;
97
- }
98
- }
99
- /**
100
- * @inheritDoc
101
- */
102
- destroy() {
103
- this.stopListening();
104
- }
105
- /**
106
- * @inheritDoc
107
- */
108
- static get isContextPlugin() {
109
- return false;
110
- }
111
- /**
112
- * @inheritDoc
113
- * @internal
114
- */
115
- static get isOfficialPlugin() {
116
- return false;
117
- }
118
- /**
119
- * @inheritDoc
120
- * @internal
121
- */
122
- static get isPremiumPlugin() {
123
- return false;
124
- }
125
- }
126
- /**
127
- * Helper function that forces plugin to be disabled.
128
- */
129
- function forceDisable(evt) {
130
- evt.return = false;
131
- evt.stop();
132
- }