UNPKG

5.38 kBJavaScriptView Raw
1/**
2 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4 */
5/**
6 * @module image/imagesizeattributes
7 */
8import { Plugin } from 'ckeditor5/src/core.js';
9import ImageUtils from './imageutils.js';
10import { widthAndHeightStylesAreBothSet, getSizeValueIfInPx } from './image/utils.js';
11/**
12 * This plugin enables `width` and `height` attributes in inline and block image elements.
13 */
14export default class ImageSizeAttributes extends Plugin {
15 /**
16 * @inheritDoc
17 */
18 static get requires() {
19 return [ImageUtils];
20 }
21 /**
22 * @inheritDoc
23 */
24 static get pluginName() {
25 return 'ImageSizeAttributes';
26 }
27 /**
28 * @inheritDoc
29 */
30 afterInit() {
31 this._registerSchema();
32 this._registerConverters('imageBlock');
33 this._registerConverters('imageInline');
34 }
35 /**
36 * Registers the `width` and `height` attributes for inline and block images.
37 */
38 _registerSchema() {
39 if (this.editor.plugins.has('ImageBlockEditing')) {
40 this.editor.model.schema.extend('imageBlock', { allowAttributes: ['width', 'height'] });
41 }
42 if (this.editor.plugins.has('ImageInlineEditing')) {
43 this.editor.model.schema.extend('imageInline', { allowAttributes: ['width', 'height'] });
44 }
45 }
46 /**
47 * Registers converters for `width` and `height` attributes.
48 */
49 _registerConverters(imageType) {
50 const editor = this.editor;
51 const imageUtils = editor.plugins.get('ImageUtils');
52 const viewElementName = imageType === 'imageBlock' ? 'figure' : 'img';
53 editor.conversion.for('upcast')
54 .attributeToAttribute({
55 view: {
56 name: viewElementName,
57 styles: {
58 width: /.+/
59 }
60 },
61 model: {
62 key: 'width',
63 value: (viewElement) => {
64 if (widthAndHeightStylesAreBothSet(viewElement)) {
65 return getSizeValueIfInPx(viewElement.getStyle('width'));
66 }
67 return null;
68 }
69 }
70 })
71 .attributeToAttribute({
72 view: {
73 name: viewElementName,
74 key: 'width'
75 },
76 model: 'width'
77 })
78 .attributeToAttribute({
79 view: {
80 name: viewElementName,
81 styles: {
82 height: /.+/
83 }
84 },
85 model: {
86 key: 'height',
87 value: (viewElement) => {
88 if (widthAndHeightStylesAreBothSet(viewElement)) {
89 return getSizeValueIfInPx(viewElement.getStyle('height'));
90 }
91 return null;
92 }
93 }
94 })
95 .attributeToAttribute({
96 view: {
97 name: viewElementName,
98 key: 'height'
99 },
100 model: 'height'
101 });
102 // Dedicated converters to propagate attributes to the <img> element.
103 editor.conversion.for('editingDowncast').add(dispatcher => {
104 attachDowncastConverter(dispatcher, 'width', 'width', true);
105 attachDowncastConverter(dispatcher, 'height', 'height', true);
106 });
107 editor.conversion.for('dataDowncast').add(dispatcher => {
108 attachDowncastConverter(dispatcher, 'width', 'width', false);
109 attachDowncastConverter(dispatcher, 'height', 'height', false);
110 });
111 function attachDowncastConverter(dispatcher, modelAttributeName, viewAttributeName, setRatioForInlineImage) {
112 dispatcher.on(`attribute:${modelAttributeName}:${imageType}`, (evt, data, conversionApi) => {
113 if (!conversionApi.consumable.consume(data.item, evt.name)) {
114 return;
115 }
116 const viewWriter = conversionApi.writer;
117 const viewElement = conversionApi.mapper.toViewElement(data.item);
118 const img = imageUtils.findViewImgElement(viewElement);
119 if (data.attributeNewValue !== null) {
120 viewWriter.setAttribute(viewAttributeName, data.attributeNewValue, img);
121 }
122 else {
123 viewWriter.removeAttribute(viewAttributeName, img);
124 }
125 // Do not set aspect-ratio for pictures. See https://github.com/ckeditor/ckeditor5/issues/14579.
126 if (data.item.hasAttribute('sources')) {
127 return;
128 }
129 const isResized = data.item.hasAttribute('resizedWidth');
130 // Do not set aspect ratio for inline images which are not resized (data pipeline).
131 if (imageType === 'imageInline' && !isResized && !setRatioForInlineImage) {
132 return;
133 }
134 const width = data.item.getAttribute('width');
135 const height = data.item.getAttribute('height');
136 if (width && height) {
137 viewWriter.setStyle('aspect-ratio', `${width}/${height}`, img);
138 }
139 });
140 }
141 }
142}