UNPKG

4.73 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 */
5import { first } from 'ckeditor5/src/utils.js';
6/**
7 * Creates a view element representing the inline image.
8 *
9 * ```html
10 * <span class="image-inline"><img></img></span>
11 * ```
12 *
13 * Note that `alt` and `src` attributes are converted separately, so they are not included.
14 *
15 * @internal
16 */
17export function createInlineImageViewElement(writer) {
18 return writer.createContainerElement('span', { class: 'image-inline' }, writer.createEmptyElement('img'));
19}
20/**
21 * Creates a view element representing the block image.
22 *
23 * ```html
24 * <figure class="image"><img></img></figure>
25 * ```
26 *
27 * Note that `alt` and `src` attributes are converted separately, so they are not included.
28 *
29 * @internal
30 */
31export function createBlockImageViewElement(writer) {
32 return writer.createContainerElement('figure', { class: 'image' }, [
33 writer.createEmptyElement('img'),
34 writer.createSlot('children')
35 ]);
36}
37/**
38 * A function returning a `MatcherPattern` for a particular type of View images.
39 *
40 * @internal
41 * @param matchImageType The type of created image.
42 */
43export function getImgViewElementMatcher(editor, matchImageType) {
44 const imageUtils = editor.plugins.get('ImageUtils');
45 const areBothImagePluginsLoaded = editor.plugins.has('ImageInlineEditing') && editor.plugins.has('ImageBlockEditing');
46 return element => {
47 // Check if the matched view element is an <img>.
48 if (!imageUtils.isInlineImageView(element)) {
49 return null;
50 }
51 // If just one of the plugins is loaded (block or inline), it will match all kinds of images.
52 if (!areBothImagePluginsLoaded) {
53 return getPositiveMatchPattern(element);
54 }
55 // The <img> can be standalone, wrapped in <figure>...</figure> (ImageBlock plugin) or
56 // wrapped in <figure><a>...</a></figure> (LinkImage plugin).
57 const imageType = element.getStyle('display') == 'block' || element.findAncestor(imageUtils.isBlockImageView) ?
58 'imageBlock' :
59 'imageInline';
60 if (imageType !== matchImageType) {
61 return null;
62 }
63 return getPositiveMatchPattern(element);
64 };
65 function getPositiveMatchPattern(element) {
66 const pattern = {
67 name: true
68 };
69 // This will trigger src consumption (See https://github.com/ckeditor/ckeditor5/issues/11530).
70 if (element.hasAttribute('src')) {
71 pattern.attributes = ['src'];
72 }
73 return pattern;
74 }
75}
76/**
77 * Considering the current model selection, it returns the name of the model image element
78 * (`'imageBlock'` or `'imageInline'`) that will make most sense from the UX perspective if a new
79 * image was inserted (also: uploaded, dropped, pasted) at that selection.
80 *
81 * The assumption is that inserting images into empty blocks or on other block widgets should
82 * produce block images. Inline images should be inserted in other cases, e.g. in paragraphs
83 * that already contain some text.
84 *
85 * @internal
86 */
87export function determineImageTypeForInsertionAtSelection(schema, selection) {
88 const firstBlock = first(selection.getSelectedBlocks());
89 // Insert a block image if the selection is not in/on block elements or it's on a block widget.
90 if (!firstBlock || schema.isObject(firstBlock)) {
91 return 'imageBlock';
92 }
93 // A block image should also be inserted into an empty block element
94 // (that is not an empty list item so the list won't get split).
95 if (firstBlock.isEmpty && firstBlock.name != 'listItem') {
96 return 'imageBlock';
97 }
98 // Otherwise insert an inline image.
99 return 'imageInline';
100}
101/**
102 * Returns parsed value of the size, but only if it contains unit: px.
103 */
104export function getSizeValueIfInPx(size) {
105 if (size && size.endsWith('px')) {
106 return parseInt(size);
107 }
108 return null;
109}
110/**
111 * Returns true if both styles (width and height) are set.
112 *
113 * If both image styles: width & height are set, they will override the image width & height attributes in the
114 * browser. In this case, the image looks the same as if these styles were applied to attributes instead of styles.
115 * That's why we can upcast these styles to width & height attributes instead of resizedWidth and resizedHeight.
116 */
117export function widthAndHeightStylesAreBothSet(viewElement) {
118 const widthStyle = getSizeValueIfInPx(viewElement.getStyle('width'));
119 const heightStyle = getSizeValueIfInPx(viewElement.getStyle('height'));
120 return !!(widthStyle && heightStyle);
121}