@ckeditor/ckeditor5-paragraph 48.2.0 → 48.3.0-alpha.1

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.
package/dist/index.js CHANGED
@@ -2,292 +2,298 @@
2
2
  * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
4
  */
5
- import { Command, Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
6
- import { first } from '@ckeditor/ckeditor5-utils/dist/index.js';
7
- import { ButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
8
- import { IconParagraph } from '@ckeditor/ckeditor5-icons/dist/index.js';
5
+ import { Command, Plugin } from "@ckeditor/ckeditor5-core";
6
+ import { first } from "@ckeditor/ckeditor5-utils";
7
+ import { ButtonView } from "@ckeditor/ckeditor5-ui";
8
+ import { IconParagraph } from "@ckeditor/ckeditor5-icons";
9
9
 
10
10
  /**
11
- * The paragraph command.
12
- */ class ParagraphCommand extends Command {
13
- constructor(editor){
14
- super(editor);
15
- // Since this command may pass selection in execution block, it should be checked directly.
16
- this._isEnabledBasedOnSelection = false;
17
- }
18
- /**
19
- * @inheritDoc
20
- */ refresh() {
21
- const model = this.editor.model;
22
- const document = model.document;
23
- const block = first(document.selection.getSelectedBlocks());
24
- this.value = !!block && block.is('element', 'paragraph');
25
- this.isEnabled = !!block && checkCanBecomeParagraph(block, model.schema);
26
- }
27
- /**
28
- * Executes the command. All the blocks (see {@link module:engine/model/schema~ModelSchema}) in the selection
29
- * will be turned to paragraphs.
30
- *
31
- * @fires execute
32
- * @param options Options for the executed command.
33
- * @param options.selection The selection that the command should be applied to. By default,
34
- * if not provided, the command is applied to the {@link module:engine/model/document~ModelDocument#selection}.
35
- */ execute(options = {}) {
36
- const model = this.editor.model;
37
- const document = model.document;
38
- const selection = options.selection || document.selection;
39
- // Don't execute command if selection is in non-editable place.
40
- if (!model.canEditAt(selection)) {
41
- return;
42
- }
43
- model.change((writer)=>{
44
- const blocks = selection.getSelectedBlocks();
45
- for (const block of blocks){
46
- if (!block.is('element', 'paragraph') && checkCanBecomeParagraph(block, model.schema)) {
47
- writer.rename(block, 'paragraph');
48
- }
49
- }
50
- });
51
- }
52
- }
11
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
12
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
13
+ */
14
+ /**
15
+ * @module paragraph/paragraphcommand
16
+ */
53
17
  /**
54
- * Checks whether the given block can be replaced by a paragraph.
55
- *
56
- * @param block A block to be tested.
57
- * @param schema The schema of the document.
58
- */ function checkCanBecomeParagraph(block, schema) {
59
- return schema.checkChild(block.parent, 'paragraph') && !schema.isObject(block);
18
+ * The paragraph command.
19
+ */
20
+ var ParagraphCommand = class extends Command {
21
+ constructor(editor) {
22
+ super(editor);
23
+ this._isEnabledBasedOnSelection = false;
24
+ }
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ refresh() {
29
+ const model = this.editor.model;
30
+ const document = model.document;
31
+ const block = first(document.selection.getSelectedBlocks());
32
+ this.value = !!block && block.is("element", "paragraph");
33
+ this.isEnabled = !!block && checkCanBecomeParagraph(block, model.schema);
34
+ }
35
+ /**
36
+ * Executes the command. All the blocks (see {@link module:engine/model/schema~ModelSchema}) in the selection
37
+ * will be turned to paragraphs.
38
+ *
39
+ * @fires execute
40
+ * @param options Options for the executed command.
41
+ * @param options.selection The selection that the command should be applied to. By default,
42
+ * if not provided, the command is applied to the {@link module:engine/model/document~ModelDocument#selection}.
43
+ */
44
+ execute(options = {}) {
45
+ const model = this.editor.model;
46
+ const document = model.document;
47
+ const selection = options.selection || document.selection;
48
+ if (!model.canEditAt(selection)) return;
49
+ model.change((writer) => {
50
+ const blocks = selection.getSelectedBlocks();
51
+ for (const block of blocks) if (!block.is("element", "paragraph") && checkCanBecomeParagraph(block, model.schema)) writer.rename(block, "paragraph");
52
+ });
53
+ }
54
+ };
55
+ /**
56
+ * Checks whether the given block can be replaced by a paragraph.
57
+ *
58
+ * @param block A block to be tested.
59
+ * @param schema The schema of the document.
60
+ */
61
+ function checkCanBecomeParagraph(block, schema) {
62
+ return schema.checkChild(block.parent, "paragraph") && !schema.isObject(block);
60
63
  }
61
64
 
62
65
  /**
63
- * The insert paragraph command. It inserts a new paragraph at a specific
64
- * {@link module:engine/model/position~ModelPosition document position}.
65
- *
66
- * ```ts
67
- * // Insert a new paragraph before an element in the document.
68
- * editor.execute( 'insertParagraph', {
69
- * position: editor.model.createPositionBefore( element )
70
- * } );
71
- * ```
72
- *
73
- * If a paragraph is disallowed in the context of the specific position, the command
74
- * will attempt to split position ancestors to find a place where it is possible
75
- * to insert a paragraph.
76
- *
77
- * **Note**: This command moves the selection to the inserted paragraph.
78
- */ class InsertParagraphCommand extends Command {
79
- constructor(editor){
80
- super(editor);
81
- // Since this command passes position in execution block instead of selection, it should be checked directly.
82
- this._isEnabledBasedOnSelection = false;
83
- }
84
- /**
85
- * Executes the command.
86
- *
87
- * @param options Options for the executed command.
88
- * @param options.position The model position at which the new paragraph will be inserted.
89
- * @param options.attributes Attributes keys and values to set on a inserted paragraph.
90
- * @fires execute
91
- */ execute(options) {
92
- const model = this.editor.model;
93
- const attributes = options.attributes;
94
- let position = options.position;
95
- // Don't execute command if position is in non-editable place.
96
- if (!model.canEditAt(position)) {
97
- return null;
98
- }
99
- return model.change((writer)=>{
100
- position = this._findPositionToInsertParagraph(position, writer);
101
- if (!position) {
102
- return null;
103
- }
104
- const paragraph = writer.createElement('paragraph');
105
- if (attributes) {
106
- model.schema.setAllowedAttributes(paragraph, attributes, writer);
107
- }
108
- model.insertContent(paragraph, position);
109
- writer.setSelection(paragraph, 'in');
110
- return writer.createPositionAt(paragraph, 0);
111
- });
112
- }
113
- /**
114
- * Returns the best position to insert a new paragraph.
115
- */ _findPositionToInsertParagraph(position, writer) {
116
- const model = this.editor.model;
117
- if (model.schema.checkChild(position, 'paragraph')) {
118
- return position;
119
- }
120
- const allowedParent = model.schema.findAllowedParent(position, 'paragraph');
121
- // It could be there's no ancestor limit that would allow paragraph.
122
- // In theory, "paragraph" could be disallowed even in the "$root".
123
- if (!allowedParent) {
124
- return null;
125
- }
126
- const positionParent = position.parent;
127
- const isTextAllowed = model.schema.checkChild(positionParent, '$text');
128
- // At empty $block or at the end of $block.
129
- // <paragraph>[]</paragraph> ---> <paragraph></paragraph><paragraph>[]</paragraph>
130
- // <paragraph>foo[]</paragraph> ---> <paragraph>foo</paragraph><paragraph>[]</paragraph>
131
- if (positionParent.isEmpty || isTextAllowed && position.isAtEnd) {
132
- return model.createPositionAfter(positionParent);
133
- }
134
- // At the start of $block with text.
135
- // <paragraph>[]foo</paragraph> ---> <paragraph>[]</paragraph><paragraph>foo</paragraph>
136
- if (!positionParent.isEmpty && isTextAllowed && position.isAtStart) {
137
- return model.createPositionBefore(positionParent);
138
- }
139
- return writer.split(position, allowedParent).position;
140
- }
141
- }
66
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
67
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
68
+ */
69
+ /**
70
+ * @module paragraph/insertparagraphcommand
71
+ */
72
+ /**
73
+ * The insert paragraph command. It inserts a new paragraph at a specific
74
+ * {@link module:engine/model/position~ModelPosition document position}.
75
+ *
76
+ * ```ts
77
+ * // Insert a new paragraph before an element in the document.
78
+ * editor.execute( 'insertParagraph', {
79
+ * position: editor.model.createPositionBefore( element )
80
+ * } );
81
+ * ```
82
+ *
83
+ * If a paragraph is disallowed in the context of the specific position, the command
84
+ * will attempt to split position ancestors to find a place where it is possible
85
+ * to insert a paragraph.
86
+ *
87
+ * **Note**: This command moves the selection to the inserted paragraph.
88
+ */
89
+ var InsertParagraphCommand = class extends Command {
90
+ constructor(editor) {
91
+ super(editor);
92
+ this._isEnabledBasedOnSelection = false;
93
+ }
94
+ /**
95
+ * Executes the command.
96
+ *
97
+ * @param options Options for the executed command.
98
+ * @param options.position The model position at which the new paragraph will be inserted.
99
+ * @param options.attributes Attributes keys and values to set on a inserted paragraph.
100
+ * @fires execute
101
+ */
102
+ execute(options) {
103
+ const model = this.editor.model;
104
+ const attributes = options.attributes;
105
+ let position = options.position;
106
+ if (!model.canEditAt(position)) return null;
107
+ return model.change((writer) => {
108
+ position = this._findPositionToInsertParagraph(position, writer);
109
+ if (!position) return null;
110
+ const paragraph = writer.createElement("paragraph");
111
+ if (attributes) model.schema.setAllowedAttributes(paragraph, attributes, writer);
112
+ model.insertContent(paragraph, position);
113
+ writer.setSelection(paragraph, "in");
114
+ return writer.createPositionAt(paragraph, 0);
115
+ });
116
+ }
117
+ /**
118
+ * Returns the best position to insert a new paragraph.
119
+ */
120
+ _findPositionToInsertParagraph(position, writer) {
121
+ const model = this.editor.model;
122
+ if (model.schema.checkChild(position, "paragraph")) return position;
123
+ const allowedParent = model.schema.findAllowedParent(position, "paragraph");
124
+ if (!allowedParent) return null;
125
+ const positionParent = position.parent;
126
+ const isTextAllowed = model.schema.checkChild(positionParent, "$text");
127
+ if (positionParent.isEmpty || isTextAllowed && position.isAtEnd) return model.createPositionAfter(positionParent);
128
+ if (!positionParent.isEmpty && isTextAllowed && position.isAtStart) return model.createPositionBefore(positionParent);
129
+ return writer.split(position, allowedParent).position;
130
+ }
131
+ };
142
132
 
143
133
  /**
144
- * The paragraph feature for the editor.
145
- *
146
- * It introduces the `<paragraph>` element in the model which renders as a `<p>` element in the DOM and data.
147
- *
148
- * It also brings two editors commands:
149
- *
150
- * * The {@link module:paragraph/paragraphcommand~ParagraphCommand `'paragraph'`} command that converts all
151
- * blocks in the model selection into paragraphs.
152
- * * The {@link module:paragraph/insertparagraphcommand~InsertParagraphCommand `'insertParagraph'`} command
153
- * that inserts a new paragraph at a specified location in the model.
154
- */ class Paragraph extends Plugin {
155
- /**
156
- * @inheritDoc
157
- */ static get pluginName() {
158
- return 'Paragraph';
159
- }
160
- /**
161
- * @inheritDoc
162
- */ static get isOfficialPlugin() {
163
- return true;
164
- }
165
- /**
166
- * @inheritDoc
167
- */ init() {
168
- const editor = this.editor;
169
- const model = editor.model;
170
- editor.commands.add('paragraph', new ParagraphCommand(editor));
171
- editor.commands.add('insertParagraph', new InsertParagraphCommand(editor));
172
- // Schema.
173
- model.schema.register('paragraph', {
174
- inheritAllFrom: '$block'
175
- });
176
- editor.conversion.elementToElement({
177
- model: 'paragraph',
178
- view: 'p'
179
- });
180
- // Conversion for paragraph-like elements which has not been converted by any plugin.
181
- editor.conversion.for('upcast').elementToElement({
182
- model: (viewElement, { writer })=>{
183
- if (!Paragraph.paragraphLikeElements.has(viewElement.name)) {
184
- return null;
185
- }
186
- // Do not auto-paragraph empty elements.
187
- if (viewElement.isEmpty) {
188
- return null;
189
- }
190
- return writer.createElement('paragraph');
191
- },
192
- view: /.+/,
193
- converterPriority: 'low'
194
- });
195
- }
196
- /**
197
- * A list of element names which should be treated by the autoparagraphing algorithms as
198
- * paragraph-like. This means that e.g. the following content:
199
- *
200
- * ```html
201
- * <h1>Foo</h1>
202
- * <table>
203
- * <tr>
204
- * <td>X</td>
205
- * <td>
206
- * <ul>
207
- * <li>Y</li>
208
- * <li>Z</li>
209
- * </ul>
210
- * </td>
211
- * </tr>
212
- * </table>
213
- * ```
214
- *
215
- * contains five paragraph-like elements: `<h1>`, two `<td>`s and two `<li>`s.
216
- * Hence, if none of the features is going to convert those elements the above content will be automatically handled
217
- * by the paragraph feature and converted to:
218
- *
219
- * ```html
220
- * <p>Foo</p>
221
- * <p>X</p>
222
- * <p>Y</p>
223
- * <p>Z</p>
224
- * ```
225
- *
226
- * Note: The `<td>` containing two `<li>` elements was ignored as the innermost paragraph-like elements
227
- * have a priority upon conversion.
228
- */ static paragraphLikeElements = new Set([
229
- 'blockquote',
230
- 'dd',
231
- 'div',
232
- 'dt',
233
- 'h1',
234
- 'h2',
235
- 'h3',
236
- 'h4',
237
- 'h5',
238
- 'h6',
239
- 'li',
240
- 'p',
241
- 'td',
242
- 'th'
243
- ]);
244
- }
134
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
135
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
136
+ */
137
+ /**
138
+ * @module paragraph/paragraph
139
+ */
140
+ /**
141
+ * The paragraph feature for the editor.
142
+ *
143
+ * It introduces the `<paragraph>` element in the model which renders as a `<p>` element in the DOM and data.
144
+ *
145
+ * It also brings two editors commands:
146
+ *
147
+ * * The {@link module:paragraph/paragraphcommand~ParagraphCommand `'paragraph'`} command that converts all
148
+ * blocks in the model selection into paragraphs.
149
+ * * The {@link module:paragraph/insertparagraphcommand~InsertParagraphCommand `'insertParagraph'`} command
150
+ * that inserts a new paragraph at a specified location in the model.
151
+ */
152
+ var Paragraph = class Paragraph extends Plugin {
153
+ /**
154
+ * @inheritDoc
155
+ */
156
+ static get pluginName() {
157
+ return "Paragraph";
158
+ }
159
+ /**
160
+ * @inheritDoc
161
+ */
162
+ static get isOfficialPlugin() {
163
+ return true;
164
+ }
165
+ /**
166
+ * @inheritDoc
167
+ */
168
+ init() {
169
+ const editor = this.editor;
170
+ const model = editor.model;
171
+ editor.commands.add("paragraph", new ParagraphCommand(editor));
172
+ editor.commands.add("insertParagraph", new InsertParagraphCommand(editor));
173
+ model.schema.register("paragraph", { inheritAllFrom: "$block" });
174
+ editor.conversion.elementToElement({
175
+ model: "paragraph",
176
+ view: "p"
177
+ });
178
+ editor.conversion.for("upcast").elementToElement({
179
+ model: (viewElement, { writer }) => {
180
+ if (!Paragraph.paragraphLikeElements.has(viewElement.name)) return null;
181
+ if (viewElement.isEmpty) return null;
182
+ return writer.createElement("paragraph");
183
+ },
184
+ view: /.+/,
185
+ converterPriority: "low"
186
+ });
187
+ }
188
+ /**
189
+ * A list of element names which should be treated by the autoparagraphing algorithms as
190
+ * paragraph-like. This means that e.g. the following content:
191
+ *
192
+ * ```html
193
+ * <h1>Foo</h1>
194
+ * <table>
195
+ * <tr>
196
+ * <td>X</td>
197
+ * <td>
198
+ * <ul>
199
+ * <li>Y</li>
200
+ * <li>Z</li>
201
+ * </ul>
202
+ * </td>
203
+ * </tr>
204
+ * </table>
205
+ * ```
206
+ *
207
+ * contains five paragraph-like elements: `<h1>`, two `<td>`s and two `<li>`s.
208
+ * Hence, if none of the features is going to convert those elements the above content will be automatically handled
209
+ * by the paragraph feature and converted to:
210
+ *
211
+ * ```html
212
+ * <p>Foo</p>
213
+ * <p>X</p>
214
+ * <p>Y</p>
215
+ * <p>Z</p>
216
+ * ```
217
+ *
218
+ * Note: The `<td>` containing two `<li>` elements was ignored as the innermost paragraph-like elements
219
+ * have a priority upon conversion.
220
+ */
221
+ static paragraphLikeElements = new Set([
222
+ "blockquote",
223
+ "dd",
224
+ "div",
225
+ "dt",
226
+ "h1",
227
+ "h2",
228
+ "h3",
229
+ "h4",
230
+ "h5",
231
+ "h6",
232
+ "li",
233
+ "p",
234
+ "td",
235
+ "th"
236
+ ]);
237
+ };
245
238
 
246
239
  /**
247
- * This plugin defines the `'paragraph'` button. It can be used together with
248
- * {@link module:heading/headingbuttonsui~HeadingButtonsUI} to replace the standard heading dropdown.
249
- *
250
- * This plugin is not loaded automatically by the {@link module:paragraph/paragraph~Paragraph} plugin. It must
251
- * be added manually.
252
- *
253
- * ```ts
254
- * ClassicEditor
255
- * .create( {
256
- * plugins: [ ..., Heading, Paragraph, HeadingButtonsUI, ParagraphButtonUI ]
257
- * toolbar: [ 'paragraph', 'heading1', 'heading2', 'heading3' ]
258
- * } )
259
- * .then( ... )
260
- * .catch( ... );
261
- * ```
262
- */ class ParagraphButtonUI extends Plugin {
263
- /**
264
- * @inheritDoc
265
- */ static get requires() {
266
- return [
267
- Paragraph
268
- ];
269
- }
270
- /**
271
- * @inheritDoc
272
- */ init() {
273
- const editor = this.editor;
274
- const t = editor.t;
275
- editor.ui.componentFactory.add('paragraph', (locale)=>{
276
- const view = new ButtonView(locale);
277
- const command = editor.commands.get('paragraph');
278
- view.label = t('Paragraph');
279
- view.icon = IconParagraph;
280
- view.tooltip = true;
281
- view.isToggleable = true;
282
- view.bind('isEnabled').to(command);
283
- view.bind('isOn').to(command, 'value');
284
- view.on('execute', ()=>{
285
- editor.execute('paragraph');
286
- });
287
- return view;
288
- });
289
- }
290
- }
240
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
241
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
242
+ */
243
+ /**
244
+ * @module paragraph/paragraphbuttonui
245
+ */
246
+ /**
247
+ * This plugin defines the `'paragraph'` button. It can be used together with
248
+ * {@link module:heading/headingbuttonsui~HeadingButtonsUI} to replace the standard heading dropdown.
249
+ *
250
+ * This plugin is not loaded automatically by the {@link module:paragraph/paragraph~Paragraph} plugin. It must
251
+ * be added manually.
252
+ *
253
+ * ```ts
254
+ * ClassicEditor
255
+ * .create( {
256
+ * plugins: [ ..., Heading, Paragraph, HeadingButtonsUI, ParagraphButtonUI ]
257
+ * toolbar: [ 'paragraph', 'heading1', 'heading2', 'heading3' ]
258
+ * } )
259
+ * .then( ... )
260
+ * .catch( ... );
261
+ * ```
262
+ */
263
+ var ParagraphButtonUI = class extends Plugin {
264
+ /**
265
+ * @inheritDoc
266
+ */
267
+ static get requires() {
268
+ return [Paragraph];
269
+ }
270
+ /**
271
+ * @inheritDoc
272
+ */
273
+ init() {
274
+ const editor = this.editor;
275
+ const t = editor.t;
276
+ editor.ui.componentFactory.add("paragraph", (locale) => {
277
+ const view = new ButtonView(locale);
278
+ const command = editor.commands.get("paragraph");
279
+ view.label = t("Paragraph");
280
+ view.icon = IconParagraph;
281
+ view.tooltip = true;
282
+ view.isToggleable = true;
283
+ view.bind("isEnabled").to(command);
284
+ view.bind("isOn").to(command, "value");
285
+ view.on("execute", () => {
286
+ editor.execute("paragraph");
287
+ });
288
+ return view;
289
+ });
290
+ }
291
+ };
292
+
293
+ /**
294
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
295
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
296
+ */
291
297
 
292
298
  export { InsertParagraphCommand, Paragraph, ParagraphButtonUI, ParagraphCommand };
293
- //# sourceMappingURL=index.js.map
299
+ //# sourceMappingURL=index.js.map