From 258cfbe1b77a0b5089f127284b928c3c1e53e52a Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 30 May 2024 09:39:27 +0300 Subject: [PATCH 1/7] Rich text: preserve comment nodes --- .../src/components/rich-text/content.scss | 26 +++++++++++++---- packages/rich-text/src/create.js | 28 +++++++++++++++++++ packages/rich-text/src/to-dom.js | 12 ++++++-- packages/rich-text/src/to-html-string.js | 9 ++++++ packages/rich-text/src/to-tree.js | 11 +++++++- 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index 6f118479fc6b0..f144aaf75cb5e 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -13,10 +13,6 @@ &:focus { // Removes outline added by the browser. outline: none; - - [data-rich-text-format-boundary] { - border-radius: $radius-small; - } } } @@ -32,11 +28,29 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before opacity: 0.8; } +[data-rich-text-comment], +[data-rich-text-script], +[data-rich-text-format-boundary] { + border-radius: 2px; +} + +[data-rich-text-comment], [data-rich-text-script] { display: inline; + background-color: currentColor; &::before { - content: ""; - background: rgb(255, 255, 0); + filter: invert(100%); + color: currentColor; } } + +[data-rich-text-script]::before { + content: ""; +} + +// Only fill in the comment content if the comment is not replaced (in the +// future they might be by Bits). +[data-rich-text-comment]:empty::before { + content: "[" attr(data-rich-text-comment) "]"; +} diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index 898bdfa73b330..d683836d9e2fa 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -469,6 +469,34 @@ function createFromElement( { element, range, isEditableTree } ) { continue; } + if ( + node.nodeType === node.COMMENT_NODE || + ( node.nodeType === node.ELEMENT_NODE && + node.tagName === 'SPAN' && + node.hasAttribute( 'data-rich-text-comment' ) ) + ) { + const value = { + formats: [ , ], + replacements: [ + { + type: '#comment', + attributes: { + 'data-rich-text-comment': + node.nodeType === node.COMMENT_NODE + ? node.nodeValue + : node.getAttribute( + 'data-rich-text-comment' + ), + }, + }, + ], + text: OBJECT_REPLACEMENT_CHARACTER, + }; + accumulateSelection( accumulator, node, range, value ); + mergePair( accumulator, value ); + continue; + } + if ( node.nodeType !== node.ELEMENT_NODE ) { continue; } diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index e7288e4ba1633..ac8308c7274b5 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -68,10 +68,16 @@ function append( element, child ) { const { type, attributes } = child; if ( type ) { - child = element.ownerDocument.createElement( type ); + if ( type === '#comment' ) { + child = element.ownerDocument.createComment( + attributes[ 'data-rich-text-comment' ] + ); + } else { + child = element.ownerDocument.createElement( type ); - for ( const key in attributes ) { - child.setAttribute( key, attributes[ key ] ); + for ( const key in attributes ) { + child.setAttribute( key, attributes[ key ] ); + } } } diff --git a/packages/rich-text/src/to-html-string.js b/packages/rich-text/src/to-html-string.js index f770dfdefc128..a4c12b4c47f00 100644 --- a/packages/rich-text/src/to-html-string.js +++ b/packages/rich-text/src/to-html-string.js @@ -88,6 +88,15 @@ function remove( object ) { } function createElementHTML( { type, attributes, object, children } ) { + if ( type === '#comment' ) { + // We can't restore the original comment delimiters, because once parsed + // into DOM nodes, we don't have the information. But in the future we + // could allow comment handlers to specify custom delimiters, for + // example `` for Bits, where `comment-content` + // would be `/{bit-name}` or `__{translatable-string}` (TBD). + return ``; + } + let attributeString = ''; for ( const key in attributes ) { diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 46671c951bc09..2c69bf0860eda 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -229,7 +229,16 @@ export function toTree( { const { type, attributes, innerHTML } = replacement; const formatType = getFormatType( type ); - if ( ! isEditableTree && type === 'script' ) { + if ( isEditableTree && type === '#comment' ) { + pointer = append( getParent( pointer ), { + type: 'span', + attributes: { + contenteditable: 'false', + 'data-rich-text-comment': + attributes[ 'data-rich-text-comment' ], + }, + } ); + } else if ( ! isEditableTree && type === 'script' ) { pointer = append( getParent( pointer ), fromFormat( { From 6397bdc869ad2303987637817f71f4c1c0c5f743 Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 30 May 2024 10:14:02 +0300 Subject: [PATCH 2/7] Improve interaction --- .../src/components/rich-text/content.scss | 26 ++++++++----------- packages/rich-text/src/to-tree.js | 4 +++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index f144aaf75cb5e..a9fa288d03a57 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -28,29 +28,25 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before opacity: 0.8; } +[data-rich-text-script] { + display: inline; + + &::before { + content: ""; + background: rgb(255, 255, 0); + } +} + [data-rich-text-comment], -[data-rich-text-script], [data-rich-text-format-boundary] { border-radius: 2px; } -[data-rich-text-comment], -[data-rich-text-script] { - display: inline; +[data-rich-text-comment] { background-color: currentColor; - &::before { + span { filter: invert(100%); color: currentColor; } } - -[data-rich-text-script]::before { - content: ""; -} - -// Only fill in the comment content if the comment is not replaced (in the -// future they might be by Bits). -[data-rich-text-comment]:empty::before { - content: "[" attr(data-rich-text-comment) "]"; -} diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 2c69bf0860eda..38a1df44b39a1 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -238,6 +238,10 @@ export function toTree( { attributes[ 'data-rich-text-comment' ], }, } ); + append( + append( pointer, { type: 'span' } ), + attributes[ 'data-rich-text-comment' ] + ); } else if ( ! isEditableTree && type === 'script' ) { pointer = append( getParent( pointer ), From 232e617895e339020139558125acd24105c0156c Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 30 May 2024 10:15:58 +0300 Subject: [PATCH 3/7] Restore brackets --- packages/rich-text/src/to-tree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 38a1df44b39a1..4a1d5a9fc9882 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -240,7 +240,7 @@ export function toTree( { } ); append( append( pointer, { type: 'span' } ), - attributes[ 'data-rich-text-comment' ] + '[' + attributes[ 'data-rich-text-comment' ] + ']' ); } else if ( ! isEditableTree && type === 'script' ) { pointer = append( From 98f32902f1f09c8694f941df49c2749b220ae197 Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 30 May 2024 14:25:29 +0300 Subject: [PATCH 4/7] Add unit tests --- .../src/test/__snapshots__/to-dom.js.snap | 30 +++++++++++ packages/rich-text/src/test/helpers/index.js | 52 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap index 0daf48aa9a1c3..ebaf6c30373d3 100644 --- a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap +++ b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap @@ -272,6 +272,21 @@ exports[`recordToDom should not error with overlapping formats (2) 1`] = ` `; +exports[`recordToDom should preserve comments 1`] = ` + + + + + [comment] + + + + +`; + exports[`recordToDom should preserve emoji 1`] = ` 🍒 @@ -289,6 +304,21 @@ exports[`recordToDom should preserve emoji in formatting 1`] = ` `; +exports[`recordToDom should preserve funky comments 1`] = ` + + + + + [/funky] + + + + +`; + exports[`recordToDom should preserve non breaking space 1`] = ` test  test diff --git a/packages/rich-text/src/test/helpers/index.js b/packages/rich-text/src/test/helpers/index.js index f246ab956db3a..7658ede7e3773 100644 --- a/packages/rich-text/src/test/helpers/index.js +++ b/packages/rich-text/src/test/helpers/index.js @@ -551,6 +551,58 @@ export const spec = [ text: '\ufffc', }, }, + { + description: 'should preserve comments', + html: '', + createRange: ( element ) => ( { + startOffset: 0, + startContainer: element, + endOffset: 1, + endContainer: element, + } ), + startPath: [ 0, 0 ], + endPath: [ 2, 0 ], + record: { + start: 0, + end: 1, + formats: [ , ], + replacements: [ + { + attributes: { + 'data-rich-text-comment': 'comment', + }, + type: '#comment', + }, + ], + text: '\ufffc', + }, + }, + { + description: 'should preserve funky comments', + html: '', + createRange: ( element ) => ( { + startOffset: 0, + startContainer: element, + endOffset: 1, + endContainer: element, + } ), + startPath: [ 0, 0 ], + endPath: [ 2, 0 ], + record: { + start: 0, + end: 1, + formats: [ , ], + replacements: [ + { + attributes: { + 'data-rich-text-comment': '/funky', + }, + type: '#comment', + }, + ], + text: '\ufffc', + }, + }, ]; export const specWithRegistration = [ From 4ac1c514a76094a7054af6cd4c8a498f4e4e6d4a Mon Sep 17 00:00:00 2001 From: Ella Date: Mon, 18 Nov 2024 16:46:26 +0100 Subject: [PATCH 5/7] Remove brackets --- packages/block-editor/src/components/rich-text/content.scss | 1 + packages/rich-text/src/to-tree.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index a9fa288d03a57..b69527f6607e9 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -48,5 +48,6 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before span { filter: invert(100%); color: currentColor; + padding: 0 2px; } } diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 4a1d5a9fc9882..0e3caad4f70c8 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -240,7 +240,7 @@ export function toTree( { } ); append( append( pointer, { type: 'span' } ), - '[' + attributes[ 'data-rich-text-comment' ] + ']' + attributes[ 'data-rich-text-comment' ].trim() ); } else if ( ! isEditableTree && type === 'script' ) { pointer = append( From 423d89203530d41f622a4454f0ec7e30cce25021 Mon Sep 17 00:00:00 2001 From: Ella Date: Mon, 18 Nov 2024 16:53:57 +0100 Subject: [PATCH 6/7] Adjust unit tests --- packages/rich-text/src/test/__snapshots__/to-dom.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap index ebaf6c30373d3..0e2ac57bea370 100644 --- a/packages/rich-text/src/test/__snapshots__/to-dom.js.snap +++ b/packages/rich-text/src/test/__snapshots__/to-dom.js.snap @@ -280,7 +280,7 @@ exports[`recordToDom should preserve comments 1`] = ` data-rich-text-comment="comment" > - [comment] + comment @@ -312,7 +312,7 @@ exports[`recordToDom should preserve funky comments 1`] = ` data-rich-text-comment="/funky" > - [/funky] + /funky From e92bbf551eeb1b6d615af2252956afbc96f6c909 Mon Sep 17 00:00:00 2001 From: Ella Date: Mon, 25 Nov 2024 09:09:58 +0100 Subject: [PATCH 7/7] Restore -small --- packages/block-editor/src/components/rich-text/content.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/rich-text/content.scss b/packages/block-editor/src/components/rich-text/content.scss index b69527f6607e9..401f1cde26acc 100644 --- a/packages/block-editor/src/components/rich-text/content.scss +++ b/packages/block-editor/src/components/rich-text/content.scss @@ -39,7 +39,7 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before [data-rich-text-comment], [data-rich-text-format-boundary] { - border-radius: 2px; + border-radius: $radius-small; } [data-rich-text-comment] {