1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | import { Plugin } from 'ckeditor5/src/core';
|
9 | import ImageStyleCommand from './imagestylecommand';
|
10 | import ImageUtils from '../imageutils';
|
11 | import utils from './utils';
|
12 | import { viewToModelStyleAttribute, modelToViewStyleAttribute } from './converters';
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | export default class ImageStyleEditing extends Plugin {
|
18 | |
19 |
|
20 |
|
21 | static get pluginName() {
|
22 | return 'ImageStyleEditing';
|
23 | }
|
24 | |
25 |
|
26 |
|
27 | static get requires() {
|
28 | return [ImageUtils];
|
29 | }
|
30 | |
31 |
|
32 |
|
33 | init() {
|
34 | const { normalizeStyles, getDefaultStylesConfiguration } = utils;
|
35 | const editor = this.editor;
|
36 | const isBlockPluginLoaded = editor.plugins.has('ImageBlockEditing');
|
37 | const isInlinePluginLoaded = editor.plugins.has('ImageInlineEditing');
|
38 | editor.config.define('image.styles', getDefaultStylesConfiguration(isBlockPluginLoaded, isInlinePluginLoaded));
|
39 | this.normalizedStyles = normalizeStyles({
|
40 | configuredStyles: editor.config.get('image.styles'),
|
41 | isBlockPluginLoaded,
|
42 | isInlinePluginLoaded
|
43 | });
|
44 | this._setupConversion(isBlockPluginLoaded, isInlinePluginLoaded);
|
45 | this._setupPostFixer();
|
46 |
|
47 | editor.commands.add('imageStyle', new ImageStyleCommand(editor, this.normalizedStyles));
|
48 | }
|
49 | |
50 |
|
51 |
|
52 |
|
53 |
|
54 | _setupConversion(isBlockPluginLoaded, isInlinePluginLoaded) {
|
55 | const editor = this.editor;
|
56 | const schema = editor.model.schema;
|
57 | const modelToViewConverter = modelToViewStyleAttribute(this.normalizedStyles);
|
58 | const viewToModelConverter = viewToModelStyleAttribute(this.normalizedStyles);
|
59 | editor.editing.downcastDispatcher.on('attribute:imageStyle', modelToViewConverter);
|
60 | editor.data.downcastDispatcher.on('attribute:imageStyle', modelToViewConverter);
|
61 |
|
62 |
|
63 | if (isBlockPluginLoaded) {
|
64 | schema.extend('imageBlock', { allowAttributes: 'imageStyle' });
|
65 |
|
66 | editor.data.upcastDispatcher.on('element:figure', viewToModelConverter, { priority: 'low' });
|
67 | }
|
68 | if (isInlinePluginLoaded) {
|
69 | schema.extend('imageInline', { allowAttributes: 'imageStyle' });
|
70 |
|
71 | editor.data.upcastDispatcher.on('element:img', viewToModelConverter, { priority: 'low' });
|
72 | }
|
73 | }
|
74 | |
75 |
|
76 |
|
77 | _setupPostFixer() {
|
78 | const editor = this.editor;
|
79 | const document = editor.model.document;
|
80 | const imageUtils = editor.plugins.get(ImageUtils);
|
81 | const stylesMap = new Map(this.normalizedStyles.map(style => [style.name, style]));
|
82 |
|
83 | document.registerPostFixer(writer => {
|
84 | let changed = false;
|
85 | for (const change of document.differ.getChanges()) {
|
86 | if (change.type == 'insert' || change.type == 'attribute' && change.attributeKey == 'imageStyle') {
|
87 | let element = change.type == 'insert' ? change.position.nodeAfter : change.range.start.nodeAfter;
|
88 | if (element && element.is('element', 'paragraph') && element.childCount > 0) {
|
89 | element = element.getChild(0);
|
90 | }
|
91 | if (!imageUtils.isImage(element)) {
|
92 | continue;
|
93 | }
|
94 | const imageStyle = element.getAttribute('imageStyle');
|
95 | if (!imageStyle) {
|
96 | continue;
|
97 | }
|
98 | const imageStyleDefinition = stylesMap.get(imageStyle);
|
99 | if (!imageStyleDefinition || !imageStyleDefinition.modelElements.includes(element.name)) {
|
100 | writer.removeAttribute('imageStyle', element);
|
101 | changed = true;
|
102 | }
|
103 | }
|
104 | }
|
105 | return changed;
|
106 | });
|
107 | }
|
108 | }
|