From 2c283bcc08ce608f076ac1769daa76f1424b0115 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 29 May 2024 00:14:58 -0400 Subject: [PATCH] fix(richtext-lexical): user-defined html converters not taking precedence, and shared default html converters doubling in size after every field initialization --- .../features/converters/html/field/index.ts | 32 +++++++++++++++++-- .../src/field/features/link/feature.server.ts | 3 +- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/richtext-lexical/src/field/features/converters/html/field/index.ts b/packages/richtext-lexical/src/field/features/converters/html/field/index.ts index 4b2369909..dfef833d6 100644 --- a/packages/richtext-lexical/src/field/features/converters/html/field/index.ts +++ b/packages/richtext-lexical/src/field/features/converters/html/field/index.ts @@ -28,12 +28,12 @@ export const consolidateHTMLConverters = ({ editorConfig, }: { editorConfig: SanitizedServerEditorConfig -}) => { +}): HTMLConverter[] => { const htmlConverterFeature = editorConfig.resolvedFeatureMap.get('htmlConverter') const htmlConverterFeatureProps: HTMLConverterFeatureProps = htmlConverterFeature?.serverFeatureProps - const defaultConvertersWithConvertersFromFeatures = defaultHTMLConverters + const defaultConvertersWithConvertersFromFeatures = [...defaultHTMLConverters] for (const converter of editorConfig.features.converters.html) { defaultConvertersWithConvertersFromFeatures.push(converter) @@ -48,7 +48,33 @@ export const consolidateHTMLConverters = ({ : (htmlConverterFeatureProps?.converters as HTMLConverter[]) || defaultConvertersWithConvertersFromFeatures - return finalConverters + // filter converters by nodeTypes. The last converter in the list wins. If there are multiple converters for the same nodeType, the last one will be used and the node types will be removed from + // previous converters. If previous converters do not have any nodeTypes left, they will be removed from the list. + // This guarantees that user-added converters which are added after the default ones will always have precedence + const foundNodeTypes: string[] = [] + const filteredConverters: HTMLConverter[] = [] + for (const converter of finalConverters.reverse()) { + if (!converter.nodeTypes?.length) { + continue + } + const newConverter: HTMLConverter = { + converter: converter.converter, + nodeTypes: [...converter.nodeTypes], + } + newConverter.nodeTypes = newConverter.nodeTypes.filter((nodeType) => { + if (foundNodeTypes.includes(nodeType)) { + return false + } + foundNodeTypes.push(nodeType) + return true + }) + + if (newConverter.nodeTypes.length) { + filteredConverters.push(newConverter) + } + } + + return filteredConverters } export const lexicalHTML: ( diff --git a/packages/richtext-lexical/src/field/features/link/feature.server.ts b/packages/richtext-lexical/src/field/features/link/feature.server.ts index a5c86ee26..615f21f13 100644 --- a/packages/richtext-lexical/src/field/features/link/feature.server.ts +++ b/packages/richtext-lexical/src/field/features/link/feature.server.ts @@ -169,13 +169,14 @@ export const LinkFeature: FeatureProviderProviderServer${childrenText}` + return `${childrenText}` }, nodeTypes: [LinkNode.getType()], },