86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
|
/* eslint-disable ghost/filenames/match-exported-class */
|
||
|
import {QuoteNode} from '@lexical/rich-text';
|
||
|
import {$createLineBreakNode, $isParagraphNode} from 'lexical';
|
||
|
|
||
|
// Since the QuoteNode is foundational to Lexical rich-text, only using a
|
||
|
// custom QuoteNode is undesirable as it means every package would need to
|
||
|
// be updated to work with the custom node. Instead we can use Lexical's node
|
||
|
// override/replacement mechanism to extend the default with our custom parsing
|
||
|
// logic.
|
||
|
//
|
||
|
// https://lexical.dev/docs/concepts/serialization#handling-extended-html-styling
|
||
|
|
||
|
export const extendedQuoteNodeReplacement = {replace: QuoteNode, with: () => new ExtendedQuoteNode()};
|
||
|
|
||
|
export class ExtendedQuoteNode extends QuoteNode {
|
||
|
constructor(key) {
|
||
|
super(key);
|
||
|
}
|
||
|
|
||
|
static getType() {
|
||
|
return 'extended-quote';
|
||
|
}
|
||
|
|
||
|
static clone(node) {
|
||
|
return new ExtendedQuoteNode(node.__key);
|
||
|
}
|
||
|
|
||
|
static importDOM() {
|
||
|
const importers = QuoteNode.importDOM();
|
||
|
return {
|
||
|
...importers,
|
||
|
blockquote: convertBlockquoteElement
|
||
|
};
|
||
|
}
|
||
|
|
||
|
static importJSON(serializedNode) {
|
||
|
return QuoteNode.importJSON(serializedNode);
|
||
|
}
|
||
|
|
||
|
exportJSON() {
|
||
|
const json = super.exportJSON();
|
||
|
json.type = 'extended-quote';
|
||
|
return json;
|
||
|
}
|
||
|
|
||
|
/* c8 ignore start */
|
||
|
extractWithChild() {
|
||
|
return true;
|
||
|
}
|
||
|
/* c8 ignore end */
|
||
|
}
|
||
|
|
||
|
function convertBlockquoteElement() {
|
||
|
return {
|
||
|
conversion: () => {
|
||
|
const node = new ExtendedQuoteNode();
|
||
|
return {
|
||
|
node,
|
||
|
after: (childNodes) => {
|
||
|
// Blockquotes can have nested paragraphs. In our original mobiledoc
|
||
|
// editor we parsed all of the nested paragraphs into a single blockquote
|
||
|
// separating each paragraph with two line breaks. We replicate that
|
||
|
// here so we don't have a breaking change in conversion behaviour.
|
||
|
const newChildNodes = [];
|
||
|
|
||
|
childNodes.forEach((child) => {
|
||
|
if ($isParagraphNode(child)) {
|
||
|
if (newChildNodes.length > 0) {
|
||
|
newChildNodes.push($createLineBreakNode());
|
||
|
newChildNodes.push($createLineBreakNode());
|
||
|
}
|
||
|
|
||
|
newChildNodes.push(...child.getChildren());
|
||
|
} else {
|
||
|
newChildNodes.push(child);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return newChildNodes;
|
||
|
}
|
||
|
};
|
||
|
},
|
||
|
priority: 1
|
||
|
};
|
||
|
}
|