@ckeditor/ckeditor5-html-support 47.6.1 → 48.0.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/LICENSE.md +1 -1
- package/ckeditor5-metadata.json +6 -6
- package/{src → dist}/converters.d.ts +2 -2
- package/{src → dist}/datafilter.d.ts +3 -3
- package/{src → dist}/dataschema.d.ts +2 -2
- package/{src → dist}/emptyblock.d.ts +1 -1
- package/{src → dist}/fullpage.d.ts +1 -1
- package/{src → dist}/generalhtmlsupport.d.ts +3 -3
- package/{src → dist}/generalhtmlsupportconfig.d.ts +1 -1
- package/{src → dist}/htmlcomment.d.ts +2 -2
- package/{src → dist}/htmlpagedataprocessor.d.ts +1 -1
- package/dist/index-editor.css +29 -29
- package/dist/index.css +30 -40
- package/dist/index.css.map +1 -1
- package/dist/index.js +29 -8
- package/dist/index.js.map +1 -1
- package/{src → dist}/integrations/codeblock.d.ts +1 -1
- package/{src → dist}/integrations/customelement.d.ts +1 -1
- package/{src → dist}/integrations/dualcontent.d.ts +1 -1
- package/{src → dist}/integrations/heading.d.ts +2 -2
- package/{src → dist}/integrations/horizontalline.d.ts +1 -1
- package/{src → dist}/integrations/iframe.d.ts +1 -1
- package/{src → dist}/integrations/image.d.ts +1 -1
- package/{src → dist}/integrations/integrationutils.d.ts +1 -1
- package/{src → dist}/integrations/list.d.ts +1 -1
- package/{src → dist}/integrations/mediaembed.d.ts +1 -1
- package/{src → dist}/integrations/script.d.ts +1 -1
- package/{src → dist}/integrations/style.d.ts +1 -1
- package/{src → dist}/integrations/table.d.ts +1 -1
- package/{src → dist}/schemadefinitions.d.ts +2 -2
- package/{src → dist}/utils.d.ts +1 -1
- package/package.json +30 -53
- package/build/html-support.js +0 -5
- package/build/translations/af.js +0 -1
- package/build/translations/ar.js +0 -1
- package/build/translations/ast.js +0 -1
- package/build/translations/az.js +0 -1
- package/build/translations/be.js +0 -1
- package/build/translations/bg.js +0 -1
- package/build/translations/bn.js +0 -1
- package/build/translations/bs.js +0 -1
- package/build/translations/ca.js +0 -1
- package/build/translations/cs.js +0 -1
- package/build/translations/da.js +0 -1
- package/build/translations/de-ch.js +0 -1
- package/build/translations/de.js +0 -1
- package/build/translations/el.js +0 -1
- package/build/translations/en-au.js +0 -1
- package/build/translations/en-gb.js +0 -1
- package/build/translations/eo.js +0 -1
- package/build/translations/es-co.js +0 -1
- package/build/translations/es.js +0 -1
- package/build/translations/et.js +0 -1
- package/build/translations/eu.js +0 -1
- package/build/translations/fa.js +0 -1
- package/build/translations/fi.js +0 -1
- package/build/translations/fr.js +0 -1
- package/build/translations/gl.js +0 -1
- package/build/translations/gu.js +0 -1
- package/build/translations/he.js +0 -1
- package/build/translations/hi.js +0 -1
- package/build/translations/hr.js +0 -1
- package/build/translations/hu.js +0 -1
- package/build/translations/hy.js +0 -1
- package/build/translations/id.js +0 -1
- package/build/translations/it.js +0 -1
- package/build/translations/ja.js +0 -1
- package/build/translations/jv.js +0 -1
- package/build/translations/kk.js +0 -1
- package/build/translations/km.js +0 -1
- package/build/translations/kn.js +0 -1
- package/build/translations/ko.js +0 -1
- package/build/translations/ku.js +0 -1
- package/build/translations/lt.js +0 -1
- package/build/translations/lv.js +0 -1
- package/build/translations/ms.js +0 -1
- package/build/translations/nb.js +0 -1
- package/build/translations/ne.js +0 -1
- package/build/translations/nl.js +0 -1
- package/build/translations/no.js +0 -1
- package/build/translations/oc.js +0 -1
- package/build/translations/pl.js +0 -1
- package/build/translations/pt-br.js +0 -1
- package/build/translations/pt.js +0 -1
- package/build/translations/ro.js +0 -1
- package/build/translations/ru.js +0 -1
- package/build/translations/si.js +0 -1
- package/build/translations/sk.js +0 -1
- package/build/translations/sl.js +0 -1
- package/build/translations/sq.js +0 -1
- package/build/translations/sr-latn.js +0 -1
- package/build/translations/sr.js +0 -1
- package/build/translations/sv.js +0 -1
- package/build/translations/th.js +0 -1
- package/build/translations/ti.js +0 -1
- package/build/translations/tk.js +0 -1
- package/build/translations/tr.js +0 -1
- package/build/translations/tt.js +0 -1
- package/build/translations/ug.js +0 -1
- package/build/translations/uk.js +0 -1
- package/build/translations/ur.js +0 -1
- package/build/translations/uz.js +0 -1
- package/build/translations/vi.js +0 -1
- package/build/translations/zh-cn.js +0 -1
- package/build/translations/zh.js +0 -1
- package/lang/contexts.json +0 -3
- package/lang/translations/af.po +0 -16
- package/lang/translations/ar.po +0 -16
- package/lang/translations/ast.po +0 -16
- package/lang/translations/az.po +0 -16
- package/lang/translations/be.po +0 -16
- package/lang/translations/bg.po +0 -16
- package/lang/translations/bn.po +0 -16
- package/lang/translations/bs.po +0 -16
- package/lang/translations/ca.po +0 -16
- package/lang/translations/cs.po +0 -16
- package/lang/translations/da.po +0 -16
- package/lang/translations/de-ch.po +0 -16
- package/lang/translations/de.po +0 -16
- package/lang/translations/el.po +0 -16
- package/lang/translations/en-au.po +0 -16
- package/lang/translations/en-gb.po +0 -16
- package/lang/translations/en.po +0 -16
- package/lang/translations/eo.po +0 -16
- package/lang/translations/es-co.po +0 -16
- package/lang/translations/es.po +0 -16
- package/lang/translations/et.po +0 -16
- package/lang/translations/eu.po +0 -16
- package/lang/translations/fa.po +0 -16
- package/lang/translations/fi.po +0 -16
- package/lang/translations/fr.po +0 -16
- package/lang/translations/gl.po +0 -16
- package/lang/translations/gu.po +0 -16
- package/lang/translations/he.po +0 -16
- package/lang/translations/hi.po +0 -16
- package/lang/translations/hr.po +0 -16
- package/lang/translations/hu.po +0 -16
- package/lang/translations/hy.po +0 -16
- package/lang/translations/id.po +0 -16
- package/lang/translations/it.po +0 -16
- package/lang/translations/ja.po +0 -16
- package/lang/translations/jv.po +0 -16
- package/lang/translations/kk.po +0 -16
- package/lang/translations/km.po +0 -16
- package/lang/translations/kn.po +0 -16
- package/lang/translations/ko.po +0 -16
- package/lang/translations/ku.po +0 -16
- package/lang/translations/lt.po +0 -16
- package/lang/translations/lv.po +0 -16
- package/lang/translations/ms.po +0 -16
- package/lang/translations/nb.po +0 -16
- package/lang/translations/ne.po +0 -16
- package/lang/translations/nl.po +0 -16
- package/lang/translations/no.po +0 -16
- package/lang/translations/oc.po +0 -16
- package/lang/translations/pl.po +0 -16
- package/lang/translations/pt-br.po +0 -16
- package/lang/translations/pt.po +0 -16
- package/lang/translations/ro.po +0 -16
- package/lang/translations/ru.po +0 -16
- package/lang/translations/si.po +0 -16
- package/lang/translations/sk.po +0 -16
- package/lang/translations/sl.po +0 -16
- package/lang/translations/sq.po +0 -16
- package/lang/translations/sr-latn.po +0 -16
- package/lang/translations/sr.po +0 -16
- package/lang/translations/sv.po +0 -16
- package/lang/translations/th.po +0 -16
- package/lang/translations/ti.po +0 -16
- package/lang/translations/tk.po +0 -16
- package/lang/translations/tr.po +0 -16
- package/lang/translations/tt.po +0 -16
- package/lang/translations/ug.po +0 -16
- package/lang/translations/uk.po +0 -16
- package/lang/translations/ur.po +0 -16
- package/lang/translations/uz.po +0 -16
- package/lang/translations/vi.po +0 -16
- package/lang/translations/zh-cn.po +0 -16
- package/lang/translations/zh.po +0 -16
- package/src/augmentation.js +0 -5
- package/src/converters.js +0 -190
- package/src/datafilter.js +0 -837
- package/src/dataschema.js +0 -199
- package/src/emptyblock.js +0 -146
- package/src/fullpage.js +0 -184
- package/src/generalhtmlsupport.js +0 -257
- package/src/generalhtmlsupportconfig.js +0 -5
- package/src/htmlcomment.js +0 -225
- package/src/htmlpagedataprocessor.js +0 -70
- package/src/index.js +0 -31
- package/src/integrations/codeblock.js +0 -107
- package/src/integrations/customelement.js +0 -166
- package/src/integrations/dualcontent.js +0 -126
- package/src/integrations/heading.js +0 -72
- package/src/integrations/horizontalline.js +0 -80
- package/src/integrations/iframe.js +0 -76
- package/src/integrations/image.js +0 -195
- package/src/integrations/integrationutils.js +0 -21
- package/src/integrations/list.js +0 -185
- package/src/integrations/mediaembed.js +0 -125
- package/src/integrations/script.js +0 -66
- package/src/integrations/style.js +0 -66
- package/src/integrations/table.js +0 -209
- package/src/schemadefinitions.js +0 -979
- package/src/utils.js +0 -169
- package/theme/datafilter.css +0 -56
- /package/{src → dist}/augmentation.d.ts +0 -0
- /package/{src → dist}/index.d.ts +0 -0
package/src/dataschema.js
DELETED
|
@@ -1,199 +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 html-support/dataschema
|
|
7
|
-
*/
|
|
8
|
-
import { Plugin } from 'ckeditor5/src/core.js';
|
|
9
|
-
import { toArray } from 'ckeditor5/src/utils.js';
|
|
10
|
-
import { defaultConfig } from './schemadefinitions.js';
|
|
11
|
-
import { mergeWith } from 'es-toolkit/compat';
|
|
12
|
-
/**
|
|
13
|
-
* Holds representation of the extended HTML document type definitions to be used by the
|
|
14
|
-
* editor in HTML support.
|
|
15
|
-
*
|
|
16
|
-
* Data schema is represented by data schema definitions.
|
|
17
|
-
*
|
|
18
|
-
* To add new definition for block element,
|
|
19
|
-
* use {@link module:html-support/dataschema~DataSchema#registerBlockElement} method:
|
|
20
|
-
*
|
|
21
|
-
* ```ts
|
|
22
|
-
* dataSchema.registerBlockElement( {
|
|
23
|
-
* view: 'section',
|
|
24
|
-
* model: 'my-section',
|
|
25
|
-
* modelSchema: {
|
|
26
|
-
* inheritAllFrom: '$block'
|
|
27
|
-
* }
|
|
28
|
-
* } );
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* To add new definition for inline element,
|
|
32
|
-
* use {@link module:html-support/dataschema~DataSchema#registerInlineElement} method:
|
|
33
|
-
*
|
|
34
|
-
* ```
|
|
35
|
-
* dataSchema.registerInlineElement( {
|
|
36
|
-
* view: 'span',
|
|
37
|
-
* model: 'my-span',
|
|
38
|
-
* attributeProperties: {
|
|
39
|
-
* copyOnEnter: true
|
|
40
|
-
* }
|
|
41
|
-
* } );
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export class DataSchema extends Plugin {
|
|
45
|
-
/**
|
|
46
|
-
* A map of registered data schema definitions.
|
|
47
|
-
*/
|
|
48
|
-
_definitions = [];
|
|
49
|
-
/**
|
|
50
|
-
* @inheritDoc
|
|
51
|
-
*/
|
|
52
|
-
static get pluginName() {
|
|
53
|
-
return 'DataSchema';
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* @inheritDoc
|
|
57
|
-
*/
|
|
58
|
-
static get isOfficialPlugin() {
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* @inheritDoc
|
|
63
|
-
*/
|
|
64
|
-
init() {
|
|
65
|
-
for (const definition of defaultConfig.block) {
|
|
66
|
-
this.registerBlockElement(definition);
|
|
67
|
-
}
|
|
68
|
-
for (const definition of defaultConfig.inline) {
|
|
69
|
-
this.registerInlineElement(definition);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Add new data schema definition describing block element.
|
|
74
|
-
*/
|
|
75
|
-
registerBlockElement(definition) {
|
|
76
|
-
this._definitions.push({ ...definition, isBlock: true });
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Add new data schema definition describing inline element.
|
|
80
|
-
*/
|
|
81
|
-
registerInlineElement(definition) {
|
|
82
|
-
this._definitions.push({ ...definition, isInline: true });
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Updates schema definition describing block element with new properties.
|
|
86
|
-
*
|
|
87
|
-
* Creates new scheme if it doesn't exist.
|
|
88
|
-
* Array properties are concatenated with original values.
|
|
89
|
-
*
|
|
90
|
-
* @param definition Definition update.
|
|
91
|
-
*/
|
|
92
|
-
extendBlockElement(definition) {
|
|
93
|
-
this._extendDefinition({ ...definition, isBlock: true });
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Updates schema definition describing inline element with new properties.
|
|
97
|
-
*
|
|
98
|
-
* Creates new scheme if it doesn't exist.
|
|
99
|
-
* Array properties are concatenated with original values.
|
|
100
|
-
*
|
|
101
|
-
* @param definition Definition update.
|
|
102
|
-
*/
|
|
103
|
-
extendInlineElement(definition) {
|
|
104
|
-
this._extendDefinition({ ...definition, isInline: true });
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Returns all definitions matching the given view name.
|
|
108
|
-
*
|
|
109
|
-
* @param includeReferences Indicates if this method should also include definitions of referenced models.
|
|
110
|
-
*/
|
|
111
|
-
getDefinitionsForView(viewName, includeReferences = false) {
|
|
112
|
-
const definitions = new Set();
|
|
113
|
-
for (const definition of this._getMatchingViewDefinitions(viewName)) {
|
|
114
|
-
if (includeReferences) {
|
|
115
|
-
for (const reference of this._getReferences(definition.model)) {
|
|
116
|
-
definitions.add(reference);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
definitions.add(definition);
|
|
120
|
-
}
|
|
121
|
-
return definitions;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Returns definitions matching the given model name.
|
|
125
|
-
*/
|
|
126
|
-
getDefinitionsForModel(modelName) {
|
|
127
|
-
return this._definitions.filter(definition => definition.model == modelName);
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Returns definitions matching the given view name.
|
|
131
|
-
*/
|
|
132
|
-
_getMatchingViewDefinitions(viewName) {
|
|
133
|
-
return this._definitions.filter(def => def.view && testViewName(viewName, def.view));
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Resolves all definition references registered for the given data schema definition.
|
|
137
|
-
*
|
|
138
|
-
* @param modelName Data schema model name.
|
|
139
|
-
*/
|
|
140
|
-
*_getReferences(modelName) {
|
|
141
|
-
const inheritProperties = [
|
|
142
|
-
'inheritAllFrom',
|
|
143
|
-
'inheritTypesFrom',
|
|
144
|
-
'allowWhere',
|
|
145
|
-
'allowContentOf',
|
|
146
|
-
'allowAttributesOf'
|
|
147
|
-
];
|
|
148
|
-
const definitions = this._definitions.filter(definition => definition.model == modelName);
|
|
149
|
-
for (const { modelSchema } of definitions) {
|
|
150
|
-
if (!modelSchema) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
for (const property of inheritProperties) {
|
|
154
|
-
for (const referenceName of toArray(modelSchema[property] || [])) {
|
|
155
|
-
const definitions = this._definitions.filter(definition => definition.model == referenceName);
|
|
156
|
-
for (const definition of definitions) {
|
|
157
|
-
if (referenceName !== modelName) {
|
|
158
|
-
yield* this._getReferences(definition.model);
|
|
159
|
-
yield definition;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Updates schema definition with new properties.
|
|
168
|
-
*
|
|
169
|
-
* Creates new scheme if it doesn't exist.
|
|
170
|
-
* Array properties are concatenated with original values.
|
|
171
|
-
*
|
|
172
|
-
* @param definition Definition update.
|
|
173
|
-
*/
|
|
174
|
-
_extendDefinition(definition) {
|
|
175
|
-
const currentDefinitions = Array.from(this._definitions.entries())
|
|
176
|
-
.filter(([, currentDefinition]) => currentDefinition.model == definition.model);
|
|
177
|
-
if (currentDefinitions.length == 0) {
|
|
178
|
-
this._definitions.push(definition);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
for (const [idx, currentDefinition] of currentDefinitions) {
|
|
182
|
-
this._definitions[idx] = mergeWith({}, currentDefinition, definition, (target, source) => {
|
|
183
|
-
return Array.isArray(target) ? target.concat(source) : undefined;
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Test view name against the given pattern.
|
|
190
|
-
*/
|
|
191
|
-
function testViewName(pattern, viewName) {
|
|
192
|
-
if (typeof pattern === 'string') {
|
|
193
|
-
return pattern === viewName;
|
|
194
|
-
}
|
|
195
|
-
if (pattern instanceof RegExp) {
|
|
196
|
-
return pattern.test(viewName);
|
|
197
|
-
}
|
|
198
|
-
return false;
|
|
199
|
-
}
|
package/src/emptyblock.js
DELETED
|
@@ -1,146 +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
|
-
import { Plugin } from 'ckeditor5/src/core.js';
|
|
6
|
-
const EMPTY_BLOCK_MODEL_ATTRIBUTE = 'htmlEmptyBlock';
|
|
7
|
-
/**
|
|
8
|
-
* This plugin allows for preserving empty block elements in the editor content
|
|
9
|
-
* instead of automatically filling them with block fillers (` `).
|
|
10
|
-
*
|
|
11
|
-
* This is useful when you want to:
|
|
12
|
-
*
|
|
13
|
-
* * Preserve empty block elements exactly as they were in the source HTML.
|
|
14
|
-
* * Allow for styling empty blocks with CSS (block fillers can interfere with height/margin).
|
|
15
|
-
* * Maintain compatibility with external systems that expect empty blocks to remain empty.
|
|
16
|
-
*
|
|
17
|
-
* Known limitations:
|
|
18
|
-
*
|
|
19
|
-
* * Empty blocks may not work correctly with revision history features.
|
|
20
|
-
* * Keyboard navigation through the document might behave unexpectedly, especially when
|
|
21
|
-
* navigating through structures like lists and tables.
|
|
22
|
-
*
|
|
23
|
-
* For example, this allows for HTML like:
|
|
24
|
-
*
|
|
25
|
-
* ```html
|
|
26
|
-
* <p></p>
|
|
27
|
-
* <p class="spacer"></p>
|
|
28
|
-
* <td></td>
|
|
29
|
-
* ```
|
|
30
|
-
* to remain empty instead of being converted to:
|
|
31
|
-
*
|
|
32
|
-
* ```html
|
|
33
|
-
* <p> </p>
|
|
34
|
-
* <p class="spacer"> </p>
|
|
35
|
-
* <td> </td>
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
export class EmptyBlock extends Plugin {
|
|
39
|
-
/**
|
|
40
|
-
* @inheritDoc
|
|
41
|
-
*/
|
|
42
|
-
static get pluginName() {
|
|
43
|
-
return 'EmptyBlock';
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* @inheritDoc
|
|
47
|
-
*/
|
|
48
|
-
static get isOfficialPlugin() {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* @inheritDoc
|
|
53
|
-
*/
|
|
54
|
-
afterInit() {
|
|
55
|
-
const { model, conversion, plugins, config } = this.editor;
|
|
56
|
-
const schema = model.schema;
|
|
57
|
-
const preserveEmptyBlocksInEditingView = config.get('htmlSupport.preserveEmptyBlocksInEditingView');
|
|
58
|
-
schema.extend('$block', { allowAttributes: [EMPTY_BLOCK_MODEL_ATTRIBUTE] });
|
|
59
|
-
schema.extend('$container', { allowAttributes: [EMPTY_BLOCK_MODEL_ATTRIBUTE] });
|
|
60
|
-
if (schema.isRegistered('tableCell')) {
|
|
61
|
-
schema.extend('tableCell', { allowAttributes: [EMPTY_BLOCK_MODEL_ATTRIBUTE] });
|
|
62
|
-
}
|
|
63
|
-
if (preserveEmptyBlocksInEditingView) {
|
|
64
|
-
conversion.for('downcast').add(createEmptyBlockDowncastConverter());
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
conversion.for('dataDowncast').add(createEmptyBlockDowncastConverter());
|
|
68
|
-
}
|
|
69
|
-
conversion.for('upcast').add(createEmptyBlockUpcastConverter(schema));
|
|
70
|
-
if (plugins.has('ClipboardPipeline')) {
|
|
71
|
-
this._registerClipboardPastingHandler();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Handle clipboard paste events:
|
|
76
|
-
*
|
|
77
|
-
* * It does not affect *copying* content from the editor, only *pasting*.
|
|
78
|
-
* * When content is pasted from another editor instance with `<p></p>`,
|
|
79
|
-
* the ` ` filler is added, so the getData result is `<p> </p>`.
|
|
80
|
-
* * When content is pasted from the same editor instance with `<p></p>`,
|
|
81
|
-
* the ` ` filler is not added, so the getData result is `<p></p>`.
|
|
82
|
-
*/
|
|
83
|
-
_registerClipboardPastingHandler() {
|
|
84
|
-
const clipboardPipeline = this.editor.plugins.get('ClipboardPipeline');
|
|
85
|
-
this.listenTo(clipboardPipeline, 'contentInsertion', (evt, data) => {
|
|
86
|
-
if (data.sourceEditorId === this.editor.id) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
this.editor.model.change(writer => {
|
|
90
|
-
for (const { item } of writer.createRangeIn(data.content)) {
|
|
91
|
-
if (item.is('element') && item.hasAttribute(EMPTY_BLOCK_MODEL_ATTRIBUTE)) {
|
|
92
|
-
writer.removeAttribute(EMPTY_BLOCK_MODEL_ATTRIBUTE, item);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Creates a downcast converter for handling empty blocks.
|
|
101
|
-
* This converter prevents filler elements from being added to elements marked as empty blocks.
|
|
102
|
-
*/
|
|
103
|
-
function createEmptyBlockDowncastConverter() {
|
|
104
|
-
return (dispatcher) => {
|
|
105
|
-
dispatcher.on(`attribute:${EMPTY_BLOCK_MODEL_ATTRIBUTE}`, (evt, data, conversionApi) => {
|
|
106
|
-
const { mapper, consumable } = conversionApi;
|
|
107
|
-
const { item } = data;
|
|
108
|
-
if (!consumable.consume(item, evt.name)) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const viewElement = mapper.toViewElement(item);
|
|
112
|
-
if (viewElement && data.attributeNewValue) {
|
|
113
|
-
viewElement.getFillerOffset = () => null;
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Creates an upcast converter for handling empty blocks.
|
|
120
|
-
* The converter detects empty elements and marks them with the empty block attribute.
|
|
121
|
-
*/
|
|
122
|
-
function createEmptyBlockUpcastConverter(schema) {
|
|
123
|
-
return (dispatcher) => {
|
|
124
|
-
dispatcher.on('element', (evt, data, conversionApi) => {
|
|
125
|
-
const { viewItem, modelRange } = data;
|
|
126
|
-
if (!viewItem.is('element') || !viewItem.isEmpty || viewItem.getCustomProperty('$hasBlockFiller')) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
// Handle element itself.
|
|
130
|
-
const modelElement = modelRange && modelRange.start.nodeAfter;
|
|
131
|
-
if (!modelElement || !schema.checkAttribute(modelElement, EMPTY_BLOCK_MODEL_ATTRIBUTE)) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
conversionApi.writer.setAttribute(EMPTY_BLOCK_MODEL_ATTRIBUTE, true, modelElement);
|
|
135
|
-
// Handle an auto-paragraphed bogus paragraph inside empty element.
|
|
136
|
-
if (modelElement.childCount != 1) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const firstModelChild = modelElement.getChild(0);
|
|
140
|
-
if (firstModelChild.is('element', 'paragraph') &&
|
|
141
|
-
schema.checkAttribute(firstModelChild, EMPTY_BLOCK_MODEL_ATTRIBUTE)) {
|
|
142
|
-
conversionApi.writer.setAttribute(EMPTY_BLOCK_MODEL_ATTRIBUTE, true, firstModelChild);
|
|
143
|
-
}
|
|
144
|
-
}, { priority: 'lowest' });
|
|
145
|
-
};
|
|
146
|
-
}
|
package/src/fullpage.js
DELETED
|
@@ -1,184 +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 html-support/fullpage
|
|
7
|
-
*/
|
|
8
|
-
import { Plugin } from 'ckeditor5/src/core.js';
|
|
9
|
-
import { logWarning, global } from 'ckeditor5/src/utils.js';
|
|
10
|
-
import { ViewUpcastWriter } from 'ckeditor5/src/engine.js';
|
|
11
|
-
import { HtmlPageDataProcessor } from './htmlpagedataprocessor.js';
|
|
12
|
-
/**
|
|
13
|
-
* The full page editing feature. It preserves the whole HTML page in the editor data.
|
|
14
|
-
*/
|
|
15
|
-
export class FullPage extends Plugin {
|
|
16
|
-
/**
|
|
17
|
-
* @inheritDoc
|
|
18
|
-
*/
|
|
19
|
-
static get pluginName() {
|
|
20
|
-
return 'FullPage';
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* @inheritDoc
|
|
24
|
-
* @internal
|
|
25
|
-
*/
|
|
26
|
-
static get licenseFeatureCode() {
|
|
27
|
-
return 'FPH';
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* @inheritDoc
|
|
31
|
-
*/
|
|
32
|
-
static get isOfficialPlugin() {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* @inheritDoc
|
|
37
|
-
*/
|
|
38
|
-
static get isPremiumPlugin() {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* @inheritDoc
|
|
43
|
-
*/
|
|
44
|
-
constructor(editor) {
|
|
45
|
-
super(editor);
|
|
46
|
-
editor.config.define('htmlSupport.fullPage', {
|
|
47
|
-
allowRenderStylesFromHead: false,
|
|
48
|
-
sanitizeCss: rawCss => {
|
|
49
|
-
/**
|
|
50
|
-
* When using the Full page with the `config.htmlSupport.fullPage.allowRenderStylesFromHead` set to `true`,
|
|
51
|
-
* it is strongly recommended to define a sanitize function that will clean up the CSS
|
|
52
|
-
* which is present in the `<head>` in editors content in order to avoid XSS vulnerability.
|
|
53
|
-
*
|
|
54
|
-
* For a detailed overview, check the {@glink features/html/full-page-html Full page HTML feature} documentation.
|
|
55
|
-
*
|
|
56
|
-
* @error css-full-page-provide-sanitize-function
|
|
57
|
-
*/
|
|
58
|
-
logWarning('css-full-page-provide-sanitize-function');
|
|
59
|
-
return {
|
|
60
|
-
css: rawCss,
|
|
61
|
-
hasChanged: false
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
editor.data.processor = new HtmlPageDataProcessor(editor.data.viewDocument);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* @inheritDoc
|
|
69
|
-
*/
|
|
70
|
-
init() {
|
|
71
|
-
const editor = this.editor;
|
|
72
|
-
const properties = ['$fullPageDocument', '$fullPageDocType', '$fullPageXmlDeclaration', '$fullPageHeadStyles'];
|
|
73
|
-
editor.model.schema.extend('$root', {
|
|
74
|
-
allowAttributes: properties
|
|
75
|
-
});
|
|
76
|
-
// Apply custom properties from view document fragment to the model root attributes.
|
|
77
|
-
editor.data.on('toModel', (evt, [viewElementOrFragment]) => {
|
|
78
|
-
const root = editor.model.document.getRoot();
|
|
79
|
-
editor.model.change(writer => {
|
|
80
|
-
for (const name of properties) {
|
|
81
|
-
const value = viewElementOrFragment.getCustomProperty(name);
|
|
82
|
-
if (value) {
|
|
83
|
-
writer.setAttribute(name, value, root);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
if (isAllowedRenderStylesFromHead(editor)) {
|
|
88
|
-
this._renderStylesFromHead(root);
|
|
89
|
-
}
|
|
90
|
-
}, { priority: 'low' });
|
|
91
|
-
// Apply root attributes to the view document fragment.
|
|
92
|
-
editor.data.on('toView', (evt, [modelElementOrFragment]) => {
|
|
93
|
-
if (!modelElementOrFragment.is('rootElement')) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const root = modelElementOrFragment;
|
|
97
|
-
const viewFragment = evt.return;
|
|
98
|
-
if (!root.hasAttribute('$fullPageDocument')) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const writer = new ViewUpcastWriter(viewFragment.document);
|
|
102
|
-
for (const name of properties) {
|
|
103
|
-
const value = root.getAttribute(name);
|
|
104
|
-
if (value) {
|
|
105
|
-
writer.setCustomProperty(name, value, viewFragment);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}, { priority: 'low' });
|
|
109
|
-
// Clear root attributes related to full page editing on editor content reset.
|
|
110
|
-
editor.data.on('set', () => {
|
|
111
|
-
const root = editor.model.document.getRoot();
|
|
112
|
-
editor.model.change(writer => {
|
|
113
|
-
for (const name of properties) {
|
|
114
|
-
if (root.hasAttribute(name)) {
|
|
115
|
-
writer.removeAttribute(name, root);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}, { priority: 'high' });
|
|
120
|
-
// Make sure that document is returned even if there is no content in the page body.
|
|
121
|
-
editor.data.on('get', (evt, args) => {
|
|
122
|
-
if (!args[0]) {
|
|
123
|
-
args[0] = {};
|
|
124
|
-
}
|
|
125
|
-
args[0].trim = false;
|
|
126
|
-
}, { priority: 'high' });
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* @inheritDoc
|
|
130
|
-
*/
|
|
131
|
-
destroy() {
|
|
132
|
-
super.destroy();
|
|
133
|
-
if (isAllowedRenderStylesFromHead(this.editor)) {
|
|
134
|
-
this._removeStyleElementsFromDom();
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Checks if in the document exists any `<style>` elements injected by the plugin and removes them,
|
|
139
|
-
* so these could be re-rendered later.
|
|
140
|
-
* There is used `data-full-page-style-id` attribute to recognize styles injected by the feature.
|
|
141
|
-
*/
|
|
142
|
-
_removeStyleElementsFromDom() {
|
|
143
|
-
const existingStyleElements = Array.from(global.document.querySelectorAll(`[data-full-page-style-id="${this.editor.id}"]`));
|
|
144
|
-
for (const style of existingStyleElements) {
|
|
145
|
-
style.remove();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Extracts `<style>` elements from the full page data and renders them in the main document `<head>`.
|
|
150
|
-
* CSS content is sanitized before rendering.
|
|
151
|
-
*/
|
|
152
|
-
_renderStyleElementsInDom(root) {
|
|
153
|
-
const editor = this.editor;
|
|
154
|
-
// Get `<style>` elements list from the `<head>` from the full page data.
|
|
155
|
-
const styleElements = root.getAttribute('$fullPageHeadStyles');
|
|
156
|
-
if (!styleElements) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const sanitizeCss = editor.config.get('htmlSupport.fullPage.sanitizeCss');
|
|
160
|
-
// Add `data-full-page-style-id` attribute to the `<style>` element and render it in `<head>` in the main document.
|
|
161
|
-
for (const style of styleElements) {
|
|
162
|
-
style.setAttribute('data-full-page-style-id', editor.id);
|
|
163
|
-
// Sanitize the CSS content before rendering it in the editor.
|
|
164
|
-
const sanitizedCss = sanitizeCss(style.innerText);
|
|
165
|
-
if (sanitizedCss.hasChanged) {
|
|
166
|
-
style.innerText = sanitizedCss.css;
|
|
167
|
-
}
|
|
168
|
-
global.document.head.append(style);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Removes existing `<style>` elements injected by the plugin and renders new ones from the full page data.
|
|
173
|
-
*/
|
|
174
|
-
_renderStylesFromHead(root) {
|
|
175
|
-
this._removeStyleElementsFromDom();
|
|
176
|
-
this._renderStyleElementsInDom(root);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Normalize the Full page configuration option `allowRenderStylesFromHead`.
|
|
181
|
-
*/
|
|
182
|
-
function isAllowedRenderStylesFromHead(editor) {
|
|
183
|
-
return editor.config.get('htmlSupport.fullPage.allowRenderStylesFromHead');
|
|
184
|
-
}
|