6 LexicalEditor, LexicalNode,
10 import type {EditorConfig} from "lexical/LexicalEditor";
11 import {el} from "../helpers";
12 import {EditorDecoratorAdapter} from "../ui/framework/decorator";
14 export interface ImageNodeOptions {
20 export type SerializedImageNode = Spread<{
25 }, SerializedLexicalNode>
27 export class ImageNode extends DecoratorNode<EditorDecoratorAdapter> {
34 static getType(): string {
38 static clone(node: ImageNode): ImageNode {
39 return new ImageNode(node.__src, {
42 height: node.__height,
46 constructor(src: string, options: ImageNodeOptions, key?: string) {
50 this.__alt = options.alt;
53 this.__width = options.width;
56 this.__height = options.height;
60 setAltText(altText: string): void {
61 const self = this.getWritable();
65 getAltText(): string {
66 const self = this.getLatest();
70 setHeight(height: number): void {
71 const self = this.getWritable();
72 self.__height = height;
76 const self = this.getLatest();
80 setWidth(width: number): void {
81 const self = this.getWritable();
86 const self = this.getLatest();
94 decorate(editor: LexicalEditor, config: EditorConfig): EditorDecoratorAdapter {
101 createDOM(_config: EditorConfig, _editor: LexicalEditor) {
102 const element = document.createElement('img');
103 element.setAttribute('src', this.__src);
106 element.setAttribute('width', String(this.__width));
109 element.setAttribute('height', String(this.__height));
112 element.setAttribute('alt', this.__alt);
114 return el('span', {class: 'editor-image-wrap'}, [
119 updateDOM(prevNode: ImageNode, dom: HTMLElement) {
120 const image = dom.querySelector('img');
121 if (!image) return false;
123 if (prevNode.__src !== this.__src) {
124 image.setAttribute('src', this.__src);
127 if (prevNode.__width !== this.__width) {
129 image.setAttribute('width', String(this.__width));
131 image.removeAttribute('width');
135 if (prevNode.__height !== this.__height) {
137 image.setAttribute('height', String(this.__height));
139 image.removeAttribute('height');
143 if (prevNode.__alt !== this.__alt) {
145 image.setAttribute('alt', String(this.__alt));
147 image.removeAttribute('alt');
154 static importDOM(): DOMConversionMap|null {
156 img(node: HTMLElement): DOMConversion|null {
158 conversion: (element: HTMLElement): DOMConversionOutput|null => {
160 const src = element.getAttribute('src') || '';
161 const options: ImageNodeOptions = {
162 alt: element.getAttribute('alt') || '',
163 height: Number.parseInt(element.getAttribute('height') || '0'),
164 width: Number.parseInt(element.getAttribute('width') || '0'),
168 node: new ImageNode(src, options),
177 exportJSON(): SerializedImageNode {
183 height: this.__height,
188 static importJSON(serializedNode: SerializedImageNode): ImageNode {
189 return $createImageNode(serializedNode.src, {
190 alt: serializedNode.alt,
191 width: serializedNode.width,
192 height: serializedNode.height,
197 export function $createImageNode(src: string, options: ImageNodeOptions = {}): ImageNode {
198 return new ImageNode(src, options);
201 export function $isImageNode(node: LexicalNode | null | undefined) {
202 return node instanceof ImageNode;