6 LexicalEditor, LexicalNode,
10 import type {EditorConfig} from "lexical/LexicalEditor";
11 import {el} from "../helpers";
13 export interface ImageNodeOptions {
19 export type SerializedImageNode = Spread<{
24 }, SerializedLexicalNode>
26 export class ImageNode extends DecoratorNode<HTMLElement> {
33 static getType(): string {
37 static clone(node: ImageNode): ImageNode {
38 return new ImageNode(node.__src, {
41 height: node.__height,
45 constructor(src: string, options: ImageNodeOptions, key?: string) {
49 this.__alt = options.alt;
52 this.__width = options.width;
55 this.__height = options.height;
59 setAltText(altText: string): void {
60 const self = this.getWritable();
64 getAltText(): string {
65 const self = this.getLatest();
69 setHeight(height: number): void {
70 const self = this.getWritable();
71 self.__height = height;
75 const self = this.getLatest();
79 setWidth(width: number): void {
80 const self = this.getWritable();
85 const self = this.getLatest();
93 decorate(editor: LexicalEditor, config: EditorConfig): HTMLElement {
94 console.log('decorate!');
96 class: 'editor-image-decorator',
97 }, ['decoration!!!']);
100 createDOM(_config: EditorConfig, _editor: LexicalEditor) {
101 const element = document.createElement('img');
102 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: unknown, dom: HTMLElement) {
120 // Returning false tells Lexical that this node does not need its
121 // DOM element replacing with a new copy from createDOM.
125 static importDOM(): DOMConversionMap|null {
127 img(node: HTMLElement): DOMConversion|null {
129 conversion: (element: HTMLElement): DOMConversionOutput|null => {
131 const src = element.getAttribute('src') || '';
132 const options: ImageNodeOptions = {
133 alt: element.getAttribute('alt') || '',
134 height: Number.parseInt(element.getAttribute('height') || '0'),
135 width: Number.parseInt(element.getAttribute('width') || '0'),
139 node: new ImageNode(src, options),
148 exportJSON(): SerializedImageNode {
154 height: this.__height,
159 static importJSON(serializedNode: SerializedImageNode): ImageNode {
160 return $createImageNode(serializedNode.src, {
161 alt: serializedNode.alt,
162 width: serializedNode.width,
163 height: serializedNode.height,
168 export function $createImageNode(src: string, options: ImageNodeOptions = {}): ImageNode {
169 return new ImageNode(src, options);
172 export function $isImageNode(node: LexicalNode | null | undefined) {
173 return node instanceof ImageNode;