From ec27c3652e60b9095fa8ae8dc9758e5447145d47 Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Tue, 13 Aug 2024 10:28:28 +0200 Subject: [PATCH] Fix TextNode highlight formatting importDom Pull request #3583 by @moy2010 added a new textformat (which is helpful), but if we use HTML to serialize it gets lost because importDOM is not parsing the mark. - Added the missing mark entry - Added a highlight formatting menu entry to playground for manual testing (including icon, and CSS theme) - added the missing entry in devtools to show format: highlight - added a test to check for mark on html past --- .../src/generateContent.ts | 3 ++ .../html/TextFormatHTMLCopyAndPaste.spec.mjs | 35 +++++++++++++++++++ .../src/images/icons/highlighter.svg | 1 + packages/lexical-playground/src/index.css | 4 +++ .../src/plugins/ToolbarPlugin/index.tsx | 12 +++++++ .../src/themes/PlaygroundEditorTheme.css | 7 ++++ .../src/themes/PlaygroundEditorTheme.ts | 1 + packages/lexical/src/nodes/LexicalTextNode.ts | 5 +++ 8 files changed, 68 insertions(+) create mode 100644 packages/lexical-playground/src/images/icons/highlighter.svg diff --git a/packages/lexical-devtools-core/src/generateContent.ts b/packages/lexical-devtools-core/src/generateContent.ts index b08eb2ec777..5e431558d26 100644 --- a/packages/lexical-devtools-core/src/generateContent.ts +++ b/packages/lexical-devtools-core/src/generateContent.ts @@ -67,6 +67,8 @@ const FORMAT_PREDICATES = [ node.hasFormat('superscript') && 'Superscript', (node: TextNode | RangeSelection) => node.hasFormat('underline') && 'Underline', + (node: TextNode | RangeSelection) => + node.hasFormat('highlight') && 'Highlight', ]; const FORMAT_PREDICATES_PARAGRAPH = [ @@ -78,6 +80,7 @@ const FORMAT_PREDICATES_PARAGRAPH = [ (node: ParagraphNode) => node.hasTextFormat('subscript') && 'Subscript', (node: ParagraphNode) => node.hasTextFormat('superscript') && 'Superscript', (node: ParagraphNode) => node.hasTextFormat('underline') && 'Underline', + (node: ParagraphNode) => node.hasTextFormat('highlight') && 'Highlight', ]; const DETAIL_PREDICATES = [ diff --git a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjs b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjs index 4a6363168f6..c957e2ed59e 100644 --- a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjs @@ -70,4 +70,39 @@ test.describe('HTML CopyAndPaste', () => { `, ); }); + + test('Copy + paste html with highlight formatting', async ({ + page, + isPlainText, + }) => { + test.skip(isPlainText); + await focusEditor(page); + const clipboardData = { + 'text/html': `

BoldHighlightBold&Highlight

`, + }; + await pasteFromClipboard(page, clipboardData); + await assertHTML( + page, + html` +

+ + Bold + + + Highlight + + + + Bold&Highlight + + +

+ `, + ); + }); }); diff --git a/packages/lexical-playground/src/images/icons/highlighter.svg b/packages/lexical-playground/src/images/icons/highlighter.svg new file mode 100644 index 00000000000..01d88ddeac6 --- /dev/null +++ b/packages/lexical-playground/src/images/icons/highlighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/lexical-playground/src/index.css b/packages/lexical-playground/src/index.css index a6c9d65c267..1728fe26053 100644 --- a/packages/lexical-playground/src/index.css +++ b/packages/lexical-playground/src/index.css @@ -406,6 +406,10 @@ i.superscript { background-image: url(images/icons/type-superscript.svg); } +i.highlight { + background-image: url(images/icons/highlighter.svg); +} + i.link { background-image: url(images/icons/link.svg); } diff --git a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx index b32d841c7ec..4478e606958 100644 --- a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx @@ -539,6 +539,7 @@ export default function ToolbarPlugin({ const [isStrikethrough, setIsStrikethrough] = useState(false); const [isSubscript, setIsSubscript] = useState(false); const [isSuperscript, setIsSuperscript] = useState(false); + const [isHighlight, setIsHighlight] = useState(false); const [isCode, setIsCode] = useState(false); const [canUndo, setCanUndo] = useState(false); const [canRedo, setCanRedo] = useState(false); @@ -585,6 +586,7 @@ export default function ToolbarPlugin({ setIsStrikethrough(selection.hasFormat('strikethrough')); setIsSubscript(selection.hasFormat('subscript')); setIsSuperscript(selection.hasFormat('superscript')); + setIsHighlight(selection.hasFormat('highlight')); setIsCode(selection.hasFormat('code')); setIsRTL($isParentElementRTL(selection)); @@ -1052,6 +1054,16 @@ export default function ToolbarPlugin({ Superscript + { + activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'highlight'); + }} + className={'item ' + dropDownActiveClass(isHighlight)} + title="Highlight" + aria-label="Format text with a highlight"> + + Highlight + ({ + conversion: convertTextFormatElement, + priority: 0, + }), s: () => ({ conversion: convertTextFormatElement, priority: 0, @@ -1284,6 +1288,7 @@ const nodeNameToTextFormat: Record = { code: 'code', em: 'italic', i: 'italic', + mark: 'highlight', s: 'strikethrough', strong: 'bold', sub: 'subscript',