lexical-remark
Version:
This package contains Markdown helpers and functionality for Lexical using remark-parse.
112 lines (111 loc) • 3.25 kB
JavaScript
/* eslint-disable @typescript-eslint/no-use-before-define */
import lexicalUtils from '@lexical/utils';
import lexical from 'lexical';
function convertAttachmentElement(domNode) {
return {
node: $createAttachmentNode(domNode.getAttribute('href') ?? '', domNode.getAttribute('download') ?? ''),
};
}
export class AttachmentNode extends lexical.ElementNode {
__filename;
__url;
constructor(url, filename, key) {
super(key);
this.__url = url;
this.__filename = filename;
}
static getType() {
return 'attachment';
}
static clone(node) {
return new AttachmentNode(node.__url, node.__filename, node.__key);
}
createDOM(config, editor) {
const dom = document.createElement('a');
dom.href = this.__url;
dom.download = this.__filename;
return dom;
}
updateDOM(prevNode, dom, config) {
const newText = this.getTextContent()
.replace(/^(?:📎)?\s*([^\s]|$)/, '$1')
.trim();
if (!newText.length) {
this.remove();
return false;
}
if (!this.getTextContent().startsWith('📎 ') || newText !== this.__filename) {
this.setFilename(newText);
this.getChildAtIndex(0)?.setTextContent(`📎 ${newText}`);
dom.download = newText;
}
if (prevNode.__url !== this.__url) {
dom.href = this.__url;
}
return false;
}
static importDOM() {
return {
a: (domNode) => {
if (!lexicalUtils.isHTMLAnchorElement(domNode)) {
return null;
}
if (!domNode.getAttribute('download')) {
return null;
}
return {
conversion: convertAttachmentElement,
priority: lexical.COMMAND_PRIORITY_HIGH,
};
},
};
}
static importJSON(serializedNode) {
return $createAttachmentNode(serializedNode.url, serializedNode.filename);
}
exportJSON() {
return {
...super.exportJSON(),
filename: this.getFilename(),
type: 'attachment',
url: this.getURL(),
version: 1,
};
}
insertNewAfter(selection, restoreSelection) {
const element = this.getParentOrThrow().insertNewAfter(selection, restoreSelection);
return element;
}
canInsertTextBefore() {
return false;
}
canInsertTextAfter() {
return false;
}
canBeEmpty() {
return false;
}
isInline() {
return true;
}
getFilename() {
return this.getLatest().__filename;
}
setFilename(filename) {
const writable = this.getWritable();
writable.__filename = filename;
}
getURL() {
return this.getLatest().__url;
}
setURL(url) {
const writable = this.getWritable();
writable.__url = url;
}
}
export function $createAttachmentNode(url, filename, key) {
return new AttachmentNode(url, filename, key);
}
export function $isAttachmentNode(node) {
return node instanceof AttachmentNode;
}