1// JavaScript 2import { 3 DecoratorNode, 4 createCommand, 5} from 'lexical'; 6 7// Command to insert an image 8export const INSERT_IMAGE_COMMAND = createCommand('INSERT_IMAGE_COMMAND'); 9 10const CLASS_FLOAT_LEFT = 'float-left'; 11const CLASS_FLOAT_RIGHT = 'float-right'; 12 13const isFloating = (elm) => { 14 elm.classList.contains(CLASS_FLOAT_LEFT) || elm.classList.contains(CLASS_FLOAT_RIGHT); 15} 16 17export class ImageNode extends DecoratorNode { 18 // data needed for the image 19 __src; 20 __alt; 21 __width; 22 __height; 23 __className; 24 25 static getType() { 26 return 'image'; 27 } 28 29 static clone(node) { 30 const newNode = new ImageNode(node.__src, node.__alt, node.__width, node.__height, node.__key); 31 newNode.__className = node.__className; 32 // noinspection JSValidateTypes 33 return newNode; 34 } 35 36 constructor(src, alt = '', width = null, height = null, key) { 37 super(key); 38 this.__src = src; 39 this.__alt = alt; 40 this.__width = width; 41 this.__height = height; 42 this.__className = ''; 43 } 44 45 createDOM() { 46 // Not used for DecoratorNode rendering when decorate() returns React 47 const img = document.createElement('img'); 48 img.src = this.__src; 49 if (this.__alt) img.alt = this.__alt; 50 if (this.__width) img.width = this.__width; 51 if (this.__height) img.height = this.__height; 52 img.className = this.__className || ''; 53 // noinspection JSValidateTypes 54 return img; 55 } 56 57 decorate() { 58 const img = document.createElement('img'); 59 img.src = this.__src; 60 img.alt = this.__alt || ''; 61 if (this.__width) img.width = this.__width; 62 if (this.__height) img.height = this.__height; 63 img.className = this.__className || ''; 64 return img; 65 } 66 67 updateDOM(prevNode, dom, config) { 68 // Keep class in sync if it changed 69 if (!prevNode.__className && isFloating(dom) 70 || !dom.classList.contains(prevNode.__className) 71 ) { 72 dom.classList = this.__className || ''; 73 return true; 74 } 75 if (dom.src !== this.__src) { 76 dom.src = this.__src; 77 return true; 78 } 79 return false; 80 } 81 82 static importDOM() { 83 return { 84 'img': () => ({ 85 conversion: $convertImageElement, 86 priority: 1 87 }) 88 }; 89 } 90 91 // Serialization (for persistence / copy paste) 92 exportJSON() { 93 return { 94 type: 'image', 95 version: 1, 96 src: this.__src, 97 alt: this.__alt, 98 width: this.__width, 99 height: this.__height, 100 className: this.__className, 101 }; 102 } 103 104 static importJSON(serializedNode) { 105 const {src, alt, width, height, className} = serializedNode; 106 const node = new ImageNode(src, alt, width, height); 107 node.__className = className; 108 // noinspection JSValidateTypes 109 return node; 110 } 111 112 // Convenience getters/setters if needed 113 114 // noinspection JSUnusedGlobalSymbols 115 getSrc() { 116 return this.__src; 117 } 118 // noinspection JSUnusedGlobalSymbols 119 setSrc(src) { 120 this.__src = src; 121 this.markDirty(); 122 } 123 // noinspection JSUnusedGlobalSymbols 124 getAlt() { 125 return this.__alt; 126 } 127 // noinspection JSUnusedGlobalSymbols 128 setAlt(alt) { 129 this.__alt = alt; 130 this.markDirty(); 131 } 132 133 // Required: indicate if the node is inline or block. Images are usually inline or block depending on your needs. 134 isInline() { 135 return false; // false -> treat as block element (paragraph-level) 136 } 137 138 setFloat(value) { 139 if (!value || value === 'none') { 140 this.__className = ''; 141 } else if (['left', 'right'].indexOf(value) !== -1) { 142 this.__className = `float-${value}`; 143 } 144 this.markDirty(); 145 } 146 147 getClass() { 148 return this.__className; 149 } 150} 151 152function $convertImageElement(element) { 153 const node = $createImageNode(element.src, element.alt, element.width, element.height); 154 node.__className = element.className || ''; 155 return {node}; 156} 157 158// Create helper 159export function $createImageNode(src, alt = '', width = null, height = null) { 160 return new ImageNode(src, alt, width, height); 161} 162 163export function $isImageNode(node) { 164 return node instanceof ImageNode; 165}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.