6 LexicalEditor, LexicalNode,
10 import type {EditorConfig} from "lexical/LexicalEditor";
11 import {EditorDecoratorAdapter} from "../ui/framework/decorator";
12 import {el} from "../utils/dom";
13 import {CommonBlockAlignment, extractAlignmentFromElement} from "./_common";
15 export interface ImageNodeOptions {
21 export type SerializedImageNode = Spread<{
26 alignment: CommonBlockAlignment;
27 }, SerializedLexicalNode>
29 export class ImageNode extends DecoratorNode<EditorDecoratorAdapter> {
34 __alignment: CommonBlockAlignment = '';
36 static getType(): string {
40 static clone(node: ImageNode): ImageNode {
41 return new ImageNode(node.__src, {
44 height: node.__height,
48 constructor(src: string, options: ImageNodeOptions, key?: string) {
52 this.__alt = options.alt;
55 this.__width = options.width;
58 this.__height = options.height;
62 setSrc(src: string): void {
63 const self = this.getWritable();
68 const self = this.getLatest();
72 setAltText(altText: string): void {
73 const self = this.getWritable();
77 getAltText(): string {
78 const self = this.getLatest();
82 setHeight(height: number): void {
83 const self = this.getWritable();
84 self.__height = height;
88 const self = this.getLatest();
92 setWidth(width: number): void {
93 const self = this.getWritable();
98 const self = this.getLatest();
102 setAlignment(alignment: CommonBlockAlignment) {
103 const self = this.getWritable();
104 self.__alignment = alignment;
107 getAlignment(): CommonBlockAlignment {
108 const self = this.getLatest();
109 return self.__alignment;
112 isInline(): boolean {
116 decorate(editor: LexicalEditor, config: EditorConfig): EditorDecoratorAdapter {
123 createDOM(_config: EditorConfig, _editor: LexicalEditor) {
124 const element = document.createElement('img');
125 element.setAttribute('src', this.__src);
128 element.setAttribute('width', String(this.__width));
131 element.setAttribute('height', String(this.__height));
134 element.setAttribute('alt', this.__alt);
137 if (this.__alignment) {
138 element.classList.add('align-' + this.__alignment);
141 return el('span', {class: 'editor-image-wrap'}, [
146 updateDOM(prevNode: ImageNode, dom: HTMLElement) {
147 const image = dom.querySelector('img');
148 if (!image) return false;
150 if (prevNode.__src !== this.__src) {
151 image.setAttribute('src', this.__src);
154 if (prevNode.__width !== this.__width) {
156 image.setAttribute('width', String(this.__width));
158 image.removeAttribute('width');
162 if (prevNode.__height !== this.__height) {
164 image.setAttribute('height', String(this.__height));
166 image.removeAttribute('height');
170 if (prevNode.__alt !== this.__alt) {
172 image.setAttribute('alt', String(this.__alt));
174 image.removeAttribute('alt');
178 if (prevNode.__alignment !== this.__alignment) {
179 if (prevNode.__alignment) {
180 image.classList.remove('align-' + prevNode.__alignment);
182 if (this.__alignment) {
183 image.classList.add('align-' + this.__alignment);
190 static importDOM(): DOMConversionMap|null {
192 img(node: HTMLElement): DOMConversion|null {
194 conversion: (element: HTMLElement): DOMConversionOutput|null => {
196 const src = element.getAttribute('src') || '';
197 const options: ImageNodeOptions = {
198 alt: element.getAttribute('alt') || '',
199 height: Number.parseInt(element.getAttribute('height') || '0'),
200 width: Number.parseInt(element.getAttribute('width') || '0'),
203 const node = new ImageNode(src, options);
204 node.setAlignment(extractAlignmentFromElement(element));
214 exportJSON(): SerializedImageNode {
220 height: this.__height,
222 alignment: this.__alignment,
226 static importJSON(serializedNode: SerializedImageNode): ImageNode {
227 const node = $createImageNode(serializedNode.src, {
228 alt: serializedNode.alt,
229 width: serializedNode.width,
230 height: serializedNode.height,
232 node.setAlignment(serializedNode.alignment);
237 export function $createImageNode(src: string, options: ImageNodeOptions = {}): ImageNode {
238 return new ImageNode(src, options);
241 export function $isImageNode(node: LexicalNode | null | undefined) {
242 return node instanceof ImageNode;