ckeditor5-elements-schema 0.0.0-stage → 49.0.0-alpha.4

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -2
  3. package/dist/augmentation.d.ts +25 -0
  4. package/dist/augmentation.d.ts.map +1 -0
  5. package/dist/augmentation.js +2 -0
  6. package/dist/augmentation.js.map +1 -0
  7. package/dist/commands/elementBlockCommand.d.ts +46 -0
  8. package/dist/commands/elementBlockCommand.d.ts.map +1 -0
  9. package/dist/commands/elementBlockCommand.js +71 -0
  10. package/dist/commands/elementBlockCommand.js.map +1 -0
  11. package/dist/commands/elementContainerCommand.d.ts +36 -0
  12. package/dist/commands/elementContainerCommand.d.ts.map +1 -0
  13. package/dist/commands/elementContainerCommand.js +67 -0
  14. package/dist/commands/elementContainerCommand.js.map +1 -0
  15. package/dist/commands/elementInlineCommand.d.ts +87 -0
  16. package/dist/commands/elementInlineCommand.d.ts.map +1 -0
  17. package/dist/commands/elementInlineCommand.js +253 -0
  18. package/dist/commands/elementInlineCommand.js.map +1 -0
  19. package/dist/commands/elementInsertCommand.d.ts +33 -0
  20. package/dist/commands/elementInsertCommand.d.ts.map +1 -0
  21. package/dist/commands/elementInsertCommand.js +61 -0
  22. package/dist/commands/elementInsertCommand.js.map +1 -0
  23. package/dist/commands/elementSchemaCommand.d.ts +62 -0
  24. package/dist/commands/elementSchemaCommand.d.ts.map +1 -0
  25. package/dist/commands/elementSchemaCommand.js +107 -0
  26. package/dist/commands/elementSchemaCommand.js.map +1 -0
  27. package/dist/conversion/convertElementSchema.d.ts +17 -0
  28. package/dist/conversion/convertElementSchema.d.ts.map +1 -0
  29. package/dist/conversion/convertElementSchema.js +55 -0
  30. package/dist/conversion/convertElementSchema.js.map +1 -0
  31. package/dist/conversion/inlineTextElement.d.ts +24 -0
  32. package/dist/conversion/inlineTextElement.d.ts.map +1 -0
  33. package/dist/conversion/inlineTextElement.js +28 -0
  34. package/dist/conversion/inlineTextElement.js.map +1 -0
  35. package/dist/definition/canHold.d.ts +10 -0
  36. package/dist/definition/canHold.d.ts.map +1 -0
  37. package/dist/definition/canHold.js +22 -0
  38. package/dist/definition/canHold.js.map +1 -0
  39. package/dist/definition/compileElementSchema.d.ts +41 -0
  40. package/dist/definition/compileElementSchema.d.ts.map +1 -0
  41. package/dist/definition/compileElementSchema.js +60 -0
  42. package/dist/definition/compileElementSchema.js.map +1 -0
  43. package/dist/definition/elementSchemaError.d.ts +12 -0
  44. package/dist/definition/elementSchemaError.d.ts.map +1 -0
  45. package/dist/definition/elementSchemaError.js +16 -0
  46. package/dist/definition/elementSchemaError.js.map +1 -0
  47. package/dist/definition/readDefinition.d.ts +18 -0
  48. package/dist/definition/readDefinition.d.ts.map +1 -0
  49. package/dist/definition/readDefinition.js +60 -0
  50. package/dist/definition/readDefinition.js.map +1 -0
  51. package/dist/definition/suggest.d.ts +5 -0
  52. package/dist/definition/suggest.d.ts.map +1 -0
  53. package/dist/definition/suggest.js +27 -0
  54. package/dist/definition/suggest.js.map +1 -0
  55. package/dist/definition/types.d.ts +105 -0
  56. package/dist/definition/types.d.ts.map +1 -0
  57. package/dist/definition/types.js +2 -0
  58. package/dist/definition/types.js.map +1 -0
  59. package/dist/definition/validateElementSchema.d.ts +26 -0
  60. package/dist/definition/validateElementSchema.d.ts.map +1 -0
  61. package/dist/definition/validateElementSchema.js +145 -0
  62. package/dist/definition/validateElementSchema.js.map +1 -0
  63. package/dist/elementSchema.d.ts +47 -0
  64. package/dist/elementSchema.d.ts.map +1 -0
  65. package/dist/elementSchema.js +108 -0
  66. package/dist/elementSchema.js.map +1 -0
  67. package/dist/elementSchemaCommands.d.ts +83 -0
  68. package/dist/elementSchemaCommands.d.ts.map +1 -0
  69. package/dist/elementSchemaCommands.js +137 -0
  70. package/dist/elementSchemaCommands.js.map +1 -0
  71. package/dist/index.d.ts +18 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +22 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/typing/twoStepCaretMovement.d.ts +11 -0
  76. package/dist/typing/twoStepCaretMovement.d.ts.map +1 -0
  77. package/dist/typing/twoStepCaretMovement.js +76 -0
  78. package/dist/typing/twoStepCaretMovement.js.map +1 -0
  79. package/dist/validate.d.ts +12 -0
  80. package/dist/validate.d.ts.map +1 -0
  81. package/dist/validate.js +11 -0
  82. package/dist/validate.js.map +1 -0
  83. package/package.json +49 -3
  84. package/src/augmentation.ts +28 -0
  85. package/src/commands/elementBlockCommand.ts +87 -0
  86. package/src/commands/elementContainerCommand.ts +83 -0
  87. package/src/commands/elementInlineCommand.ts +311 -0
  88. package/src/commands/elementInsertCommand.ts +74 -0
  89. package/src/commands/elementSchemaCommand.ts +140 -0
  90. package/src/conversion/convertElementSchema.ts +65 -0
  91. package/src/conversion/inlineTextElement.ts +31 -0
  92. package/src/definition/canHold.ts +29 -0
  93. package/src/definition/compileElementSchema.ts +88 -0
  94. package/src/definition/elementSchemaError.ts +21 -0
  95. package/src/definition/readDefinition.ts +98 -0
  96. package/src/definition/suggest.ts +38 -0
  97. package/src/definition/types.ts +123 -0
  98. package/src/definition/validateElementSchema.ts +238 -0
  99. package/src/elementSchema.ts +133 -0
  100. package/src/elementSchemaCommands.ts +202 -0
  101. package/src/index.ts +30 -0
  102. package/src/typing/twoStepCaretMovement.ts +119 -0
  103. package/src/validate.ts +20 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ivan Kildyushov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,71 @@
1
- # Temporary Holding Version
1
+ # ckeditor5-elements-schema
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Element schema for CKEditor 5 Elements: `ElementSchema` declares elements in the model schema from a simple definition,
4
+ e.g. a JSON file, with three types of elements (`empty`, `block`, `container`), and rejects definitions that are
5
+ contradictory.
6
+
7
+ ## Installation
8
+
9
+ This package is part of `ckeditor5-elements`. Install the whole package to use it:
10
+
11
+ ```sh
12
+ npm install ckeditor5 ckeditor5-elements
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```json
18
+ {
19
+ "note": { "type": "container", "allowAttributes": ["type"] },
20
+ "title": { "type": "block", "allowIn": ["note"] },
21
+ "badge": { "type": "empty", "isInline": true, "allowAttributes": ["color"] }
22
+ }
23
+ ```
24
+
25
+ ```ts
26
+ import { ElementSchema } from 'ckeditor5-elements';
27
+ import schema from './schema.json';
28
+
29
+ // In the editor config:
30
+ plugins: [..., ElementSchema],
31
+ elementSchema: schema,
32
+ elementSchemaConverters: true // Optional: converts the elements one to one, as `div` and `span`
33
+ ```
34
+
35
+ The `empty` and `container` elements can be selected as a whole, by a click and by the arrow keys, when `ElementSelectable`
36
+ (from `ckeditor5-elements-interaction`) is loaded too.
37
+
38
+ `ElementSchemaCommands` gives elements of the schema a command, a toolbar button and a keystroke, by their kind: an
39
+ inline `block` wraps text, as CKEditor's bold; a `block` renames blocks, as a heading; a `container` wraps blocks, as a
40
+ block quote; an `empty` element and an inline `container` are inserted, as a horizontal line. At the ends of inline
41
+ elements with text, the arrow keys move in two steps, as CKEditor's two-step caret movement does.
42
+
43
+ ```json
44
+ { "bold": { "type": "block", "isInline": true }, "divider": { "type": "empty" } }
45
+ ```
46
+
47
+ ```ts
48
+ import { IconBold, IconHorizontalLine } from 'ckeditor5';
49
+ import { ElementSchema, ElementSchemaCommands } from 'ckeditor5-elements';
50
+
51
+ // In the editor config:
52
+ plugins: [..., ElementSchema, ElementSchemaCommands],
53
+ toolbar: ['bold', 'divider'],
54
+ elementSchema: schema,
55
+ elementSchemaCommands: {
56
+ bold: { title: 'Bold', icon: IconBold, keystroke: 'Ctrl+B', view: 'strong' },
57
+ divider: { title: 'Divider', icon: IconHorizontalLine, view: 'hr' }
58
+ }
59
+ ```
60
+
61
+ `validateElementSchema(schema)` checks a definition without an editor, e.g. in a test or in CI. In Node.js, import it from
62
+ `ckeditor5-elements/validate-schema`: the main entry loads CKEditor, which needs a browser.
63
+
64
+ See the guide of the documentation: [Element schema](https://ivankild.github.io/ckeditor5-elements/guide/schema),
65
+ [Converters](https://ivankild.github.io/ckeditor5-elements/guide/schema-converters),
66
+ [Commands and buttons](https://ivankild.github.io/ckeditor5-elements/guide/schema-commands) and
67
+ [Examples](https://ivankild.github.io/ckeditor5-elements/guide/schema-examples).
68
+
69
+ ## License
70
+
71
+ MIT
@@ -0,0 +1,25 @@
1
+ import type { ElementSchema, ElementSchemaCommands, ElementSchemaCommandsConfig, ElementSchemaInput } from './index.js';
2
+ declare module 'ckeditor5' {
3
+ interface PluginsMap {
4
+ [ElementSchema.pluginName]: ElementSchema;
5
+ [ElementSchemaCommands.pluginName]: ElementSchemaCommands;
6
+ }
7
+ interface EditorConfig {
8
+ /**
9
+ * The elements to declare in the model schema: an object, e.g. a JSON file. See {@link ElementSchema}.
10
+ */
11
+ elementSchema?: ElementSchemaInput;
12
+ /**
13
+ * Whether to declare the converters of the elements of `elementSchema`, one to one: `div` or `span` with the name as
14
+ * the class, and the attributes as `data-*` attributes, in the data and in the editing view; `editingTag` of an
15
+ * element sets another tag for the editing view. See {@link ElementSchema}. Default: `false`.
16
+ */
17
+ elementSchemaConverters?: boolean;
18
+ /**
19
+ * The commands and the buttons of elements of the schema, as CKEditor's bold, heading, block quote or horizontal
20
+ * line, by the name of the command. See {@link ElementSchemaCommands}.
21
+ */
22
+ elementSchemaCommands?: ElementSchemaCommandsConfig;
23
+ }
24
+ }
25
+ //# sourceMappingURL=augmentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"augmentation.d.ts","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExH,OAAO,QAAQ,WAAW,CAAC;IAC1B,UAAU,UAAU;QACnB,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC;QAC1C,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC;KAC1D;IAED,UAAU,YAAY;QACrB;;WAEG;QACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;QAEnC;;;;WAIG;QACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAElC;;;WAGG;QACH,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;KACpD;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=augmentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"augmentation.js","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import type { ElementOrPosition } from 'ckeditor5-elements-core';
2
+ import ElementSchemaCommand from './elementSchemaCommand.js';
3
+ /**
4
+ * Turns blocks into the element, as CKEditor's heading command does, e.g. a `title` that is a `block` of the element
5
+ * schema: the selected blocks, or the block of the target, are renamed, and keep their content.
6
+ *
7
+ * ```ts
8
+ * editor.execute('title'); // The blocks of the selection.
9
+ * editor.commands.get('title').executeFor(paragraph);
10
+ * ```
11
+ *
12
+ * When all the blocks are the element already, it turns them back into paragraphs (the {@link defaultElement}). The
13
+ * blocks that cannot be renamed, e.g. where the element is not allowed, are left as they are.
14
+ *
15
+ * It is "on" when all the blocks are the element.
16
+ */
17
+ export default class ElementBlockCommand extends ElementSchemaCommand {
18
+ isToggleable: boolean;
19
+ /**
20
+ * The element the blocks are turned back into.
21
+ */
22
+ defaultElement: string;
23
+ /**
24
+ * Renames the blocks of the target: to the element, or back to the {@link defaultElement} when they are all the
25
+ * element.
26
+ */
27
+ execute(elementOrPosition?: ElementOrPosition): void;
28
+ /**
29
+ * Enabled when the target can be edited, and one of its blocks can be renamed.
30
+ */
31
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
32
+ /**
33
+ * "On" when all the blocks of the target are the element.
34
+ */
35
+ protected _isOnFor(elementOrPosition?: ElementOrPosition): boolean;
36
+ /**
37
+ * Returns the name the blocks get: the element, or the {@link defaultElement} when they are the element already.
38
+ */
39
+ private _getNewName;
40
+ /**
41
+ * Whether a block can be renamed: it is not an object, nor the name already, and the schema allows it with its
42
+ * content.
43
+ */
44
+ private _canRename;
45
+ }
46
+ //# sourceMappingURL=elementBlockCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementBlockCommand.d.ts","sourceRoot":"","sources":["../../src/commands/elementBlockCommand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,oBAAoB;IACpD,YAAY,UAAQ;IAEpC;;OAEG;IACI,cAAc,SAAe;IAEpC;;;OAGG;IACa,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAcpE;;OAEG;cACgB,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAShF;;OAEG;cACgB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAM3E;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;;OAGG;IACH,OAAO,CAAC,UAAU;CAUlB"}
@@ -0,0 +1,71 @@
1
+ import ElementSchemaCommand from './elementSchemaCommand.js';
2
+ /**
3
+ * Turns blocks into the element, as CKEditor's heading command does, e.g. a `title` that is a `block` of the element
4
+ * schema: the selected blocks, or the block of the target, are renamed, and keep their content.
5
+ *
6
+ * ```ts
7
+ * editor.execute('title'); // The blocks of the selection.
8
+ * editor.commands.get('title').executeFor(paragraph);
9
+ * ```
10
+ *
11
+ * When all the blocks are the element already, it turns them back into paragraphs (the {@link defaultElement}). The
12
+ * blocks that cannot be renamed, e.g. where the element is not allowed, are left as they are.
13
+ *
14
+ * It is "on" when all the blocks are the element.
15
+ */
16
+ export default class ElementBlockCommand extends ElementSchemaCommand {
17
+ isToggleable = true;
18
+ /**
19
+ * The element the blocks are turned back into.
20
+ */
21
+ defaultElement = 'paragraph';
22
+ /**
23
+ * Renames the blocks of the target: to the element, or back to the {@link defaultElement} when they are all the
24
+ * element.
25
+ */
26
+ execute(elementOrPosition) {
27
+ const name = this._getNewName(elementOrPosition);
28
+ const schema = this.editor.model.schema;
29
+ this.editor.model.change(writer => {
30
+ for (const block of this._getBlocks(elementOrPosition)) {
31
+ if (this._canRename(block, name)) {
32
+ writer.rename(block, name);
33
+ schema.removeDisallowedAttributes([block], writer);
34
+ }
35
+ }
36
+ });
37
+ }
38
+ /**
39
+ * Enabled when the target can be edited, and one of its blocks can be renamed.
40
+ */
41
+ _isEnabledFor(elementOrPosition) {
42
+ const name = this._getNewName(elementOrPosition);
43
+ return (super._isEnabledFor(elementOrPosition) &&
44
+ this._getBlocks(elementOrPosition).some(block => this._canRename(block, name)));
45
+ }
46
+ /**
47
+ * "On" when all the blocks of the target are the element.
48
+ */
49
+ _isOnFor(elementOrPosition) {
50
+ const blocks = this._getBlocks(elementOrPosition);
51
+ return blocks.length > 0 && blocks.every(block => this.isElement(block));
52
+ }
53
+ /**
54
+ * Returns the name the blocks get: the element, or the {@link defaultElement} when they are the element already.
55
+ */
56
+ _getNewName(elementOrPosition) {
57
+ return this._isOnFor(elementOrPosition) ? this.defaultElement : this.elementName;
58
+ }
59
+ /**
60
+ * Whether a block can be renamed: it is not an object, nor the name already, and the schema allows it with its
61
+ * content.
62
+ */
63
+ _canRename(block, name) {
64
+ const schema = this.editor.model.schema;
65
+ return (block.name !== name &&
66
+ !schema.isObject(block) &&
67
+ schema.isRegistered(name) &&
68
+ this._canHold(this.editor.model.createPositionBefore(block), block.getChildren(), name));
69
+ }
70
+ }
71
+ //# sourceMappingURL=elementBlockCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementBlockCommand.js","sourceRoot":"","sources":["../../src/commands/elementBlockCommand.ts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,oBAAoB;IACpD,YAAY,GAAG,IAAI,CAAC;IAEpC;;OAEG;IACI,cAAc,GAAG,WAAW,CAAC;IAEpC;;;OAGG;IACa,OAAO,CAAC,iBAAqC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAExC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACxD,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;oBAClC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAC3B,MAAM,CAAC,0BAA0B,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;gBACpD,CAAC;YACF,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACgB,aAAa,CAAC,iBAAqC;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEjD,OAAO,CACN,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAC9E,CAAC;IACH,CAAC;IAED;;OAEG;IACgB,QAAQ,CAAC,iBAAqC;QAChE,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAElD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,iBAAqC;QACxD,OAAO,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAClF,CAAC;IAED;;;OAGG;IACK,UAAU,CAAC,KAAmB,EAAE,IAAY;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAExC,OAAO,CACN,KAAK,CAAC,IAAI,KAAK,IAAI;YACnB,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CACvF,CAAC;IACH,CAAC;CACD"}
@@ -0,0 +1,36 @@
1
+ import type { ElementOrPosition } from 'ckeditor5-elements-core';
2
+ import ElementSchemaCommand from './elementSchemaCommand.js';
3
+ /**
4
+ * Wraps blocks with the element, as CKEditor's block quote command does, e.g. a `callout` that is a `container` of the
5
+ * element schema: the selected blocks, or the block-level element of the target, go in a new element.
6
+ *
7
+ * ```ts
8
+ * editor.execute('callout'); // The blocks of the selection.
9
+ * editor.commands.get('callout').executeFor(paragraph);
10
+ * ```
11
+ *
12
+ * In the element, it unwraps it: the whole element, not only the selected blocks.
13
+ *
14
+ * It is "on" when the target is in the element.
15
+ */
16
+ export default class ElementContainerCommand extends ElementSchemaCommand {
17
+ isToggleable: boolean;
18
+ /**
19
+ * Unwraps the element the target is in, or wraps the blocks of the target with a new one.
20
+ */
21
+ execute(elementOrPosition?: ElementOrPosition): void;
22
+ /**
23
+ * Enabled when the target can be edited, and the element it is in can be unwrapped, or its blocks can be wrapped.
24
+ */
25
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
26
+ /**
27
+ * "On" when the target is in the element.
28
+ */
29
+ protected _isOnFor(elementOrPosition?: ElementOrPosition): boolean;
30
+ /**
31
+ * Returns the range to wrap: from the first block of the target to the last, as siblings: the blocks themselves, or
32
+ * their ancestors in the parent they share. `null` when the schema does not allow the element there.
33
+ */
34
+ private _getWrapRange;
35
+ }
36
+ //# sourceMappingURL=elementContainerCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementContainerCommand.d.ts","sourceRoot":"","sources":["../../src/commands/elementContainerCommand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,oBAAoB;IACxD,YAAY,UAAQ;IAEpC;;OAEG;IACa,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAapE;;OAEG;cACgB,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAShF;;OAEG;cACgB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAI3E;;;OAGG;IACH,OAAO,CAAC,aAAa;CAuBrB"}
@@ -0,0 +1,67 @@
1
+ import ElementSchemaCommand from './elementSchemaCommand.js';
2
+ /**
3
+ * Wraps blocks with the element, as CKEditor's block quote command does, e.g. a `callout` that is a `container` of the
4
+ * element schema: the selected blocks, or the block-level element of the target, go in a new element.
5
+ *
6
+ * ```ts
7
+ * editor.execute('callout'); // The blocks of the selection.
8
+ * editor.commands.get('callout').executeFor(paragraph);
9
+ * ```
10
+ *
11
+ * In the element, it unwraps it: the whole element, not only the selected blocks.
12
+ *
13
+ * It is "on" when the target is in the element.
14
+ */
15
+ export default class ElementContainerCommand extends ElementSchemaCommand {
16
+ isToggleable = true;
17
+ /**
18
+ * Unwraps the element the target is in, or wraps the blocks of the target with a new one.
19
+ */
20
+ execute(elementOrPosition) {
21
+ const element = this._findElement(elementOrPosition);
22
+ const range = element ? null : this._getWrapRange(elementOrPosition);
23
+ this.editor.model.change(writer => {
24
+ if (element) {
25
+ writer.unwrap(element);
26
+ }
27
+ else if (range) {
28
+ writer.wrap(range, this.elementName);
29
+ }
30
+ });
31
+ }
32
+ /**
33
+ * Enabled when the target can be edited, and the element it is in can be unwrapped, or its blocks can be wrapped.
34
+ */
35
+ _isEnabledFor(elementOrPosition) {
36
+ const element = this._findElement(elementOrPosition);
37
+ return (super._isEnabledFor(elementOrPosition) &&
38
+ (element ? this._canUnwrap(element) : !!this._getWrapRange(elementOrPosition)));
39
+ }
40
+ /**
41
+ * "On" when the target is in the element.
42
+ */
43
+ _isOnFor(elementOrPosition) {
44
+ return !!this._findElement(elementOrPosition);
45
+ }
46
+ /**
47
+ * Returns the range to wrap: from the first block of the target to the last, as siblings: the blocks themselves, or
48
+ * their ancestors in the parent they share. `null` when the schema does not allow the element there.
49
+ */
50
+ _getWrapRange(elementOrPosition) {
51
+ const model = this.editor.model;
52
+ const blocks = this._getBlocks(elementOrPosition);
53
+ const first = blocks[0];
54
+ const last = blocks.at(-1);
55
+ if (!first || !last) {
56
+ return null;
57
+ }
58
+ const parent = first === last ? first.parent : first.getCommonAncestor(last);
59
+ const [start, end] = [first, last].map(block => block.getAncestors({ includeSelf: true }).find((node) => node.parent === parent));
60
+ if (!start || !end) {
61
+ return null;
62
+ }
63
+ const range = model.createRange(model.createPositionBefore(start), model.createPositionAfter(end));
64
+ return this._canHold(range.start, range.getItems({ shallow: true })) ? range : null;
65
+ }
66
+ }
67
+ //# sourceMappingURL=elementContainerCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementContainerCommand.js","sourceRoot":"","sources":["../../src/commands/elementContainerCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { type ModelElement } from 'ckeditor5';
2
+ import type { ElementOrPosition } from 'ckeditor5-elements-core';
3
+ import ElementSchemaCommand from './elementSchemaCommand.js';
4
+ /**
5
+ * Toggles an inline element with text, as CKEditor's `bold` toggles an attribute of text, but with an element, e.g. a
6
+ * `bold` that is an inline `block` of the element schema.
7
+ *
8
+ * ```ts
9
+ * editor.execute('bold'); // The selection.
10
+ * editor.commands.get('bold').executeFor(element); // An element, e.g. of a context menu.
11
+ * ```
12
+ *
13
+ * * On selected text, it wraps the text with the element, in each block, and merges it with the elements next to it.
14
+ * When all the text is in the element already, it unwraps the elements: the whole ones, not only the selected part.
15
+ * * On the cursor, it inserts an empty element with the cursor in it. In the element, it moves the cursor out of it, at
16
+ * its start or end, or it unwraps it.
17
+ * * On an element (selected, or given), it unwraps the element it is in, or wraps it.
18
+ *
19
+ * It is "on" ({@link isOn}) when the target is in the element: for selected text, when all of it is.
20
+ */
21
+ export default class ElementInlineCommand extends ElementSchemaCommand {
22
+ isToggleable: boolean;
23
+ /**
24
+ * Puts the target in the element, or out of it: by default, the selection, also selected text.
25
+ */
26
+ execute(elementOrPosition?: ElementOrPosition): void;
27
+ /**
28
+ * Enabled when the target can be edited, and is in the element, or the element can be there.
29
+ */
30
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
31
+ /**
32
+ * "On" when the target is in the element: for selected text, when all of it is.
33
+ */
34
+ protected _isOnFor(elementOrPosition?: ElementOrPosition): boolean;
35
+ /**
36
+ * Whether all the text of the ranges is in the element: there are elements, and nothing to wrap.
37
+ */
38
+ private _isOnRanges;
39
+ /**
40
+ * Returns the elements of the command that a node is, or is in, in its line of text: the node and its ancestors, up to
41
+ * the first that is not inline, e.g. the paragraph. The inner first.
42
+ */
43
+ private _getElementsAround;
44
+ /**
45
+ * Returns the closest element of the command that the target is, or is in, in its line of text.
46
+ */
47
+ protected _findElement(elementOrPosition?: ElementOrPosition): ModelElement | null;
48
+ /**
49
+ * Returns the elements of the command in ranges, and around their ends.
50
+ */
51
+ private _getElementsIn;
52
+ /**
53
+ * Returns the ranges to wrap with the element to put the text of ranges in it: in each parent the element is allowed
54
+ * in, the runs of nodes it can hold, which are not in the element already. The other elements are looked into, e.g.
55
+ * the paragraphs of a selection across blocks.
56
+ */
57
+ private _getWrapRanges;
58
+ /**
59
+ * Wraps the text of ranges with new elements, merged with the ones next to them, and keeps the selection on the text.
60
+ */
61
+ private _wrapRanges;
62
+ /**
63
+ * Unwraps the elements in ranges and around their ends, and keeps the selection on the text.
64
+ */
65
+ private _unwrapRanges;
66
+ /**
67
+ * Changes the content of the selected ranges, and selects the same text then: the ends of the ranges stick to the
68
+ * text, so they follow it into the elements and out of them.
69
+ */
70
+ private _keepSelection;
71
+ /**
72
+ * Merges a new element with the elements of the command next to it that have no attributes, as it has none.
73
+ */
74
+ private _mergeWithSiblings;
75
+ /**
76
+ * Puts the target out of the element it is in: a cursor at the start or the end of the element goes before or after
77
+ * it, so that what is typed next is out of it; otherwise the element is unwrapped. A selected element that is
78
+ * unwrapped leaves its content selected.
79
+ */
80
+ private _leave;
81
+ /**
82
+ * Puts the target in a new element: at a position, an empty element with the cursor in it; an element, e.g. a
83
+ * selected inline object, is wrapped, and selected.
84
+ */
85
+ private _insert;
86
+ }
87
+ //# sourceMappingURL=elementInlineCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementInlineCommand.d.ts","sourceRoot":"","sources":["../../src/commands/elementInlineCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,YAAY,EAIjB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,oBAAoB;IACrD,YAAY,UAAQ;IAEpC;;OAEG;IACa,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAuBpE;;OAEG;cACgB,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAqBhF;;OAEG;cACgB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAO3E;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;cACgB,YAAY,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,YAAY,GAAG,IAAI;IAM3F;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IA8CtB;;OAEG;IACH,OAAO,CAAC,WAAW;IAcnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAqBd;;;OAGG;IACH,OAAO,CAAC,OAAO;CAWf"}