Skip to content

Commit

Permalink
Rich text: preserve comments (#62128)
Browse files Browse the repository at this point in the history
Co-authored-by: ellatrix <[email protected]>
Co-authored-by: lysyjan <[email protected]>
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: RolfKyburz <[email protected]>
Co-authored-by: strarsis <[email protected]>
Co-authored-by: danielbachhuber <[email protected]>
  • Loading branch information
7 people authored Nov 25, 2024
1 parent e27e5e4 commit b76d9f0
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 8 deletions.
19 changes: 15 additions & 4 deletions packages/block-editor/src/components/rich-text/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
&:focus {
// Removes outline added by the browser.
outline: none;

[data-rich-text-format-boundary] {
border-radius: $radius-small;
}
}
}

Expand All @@ -34,3 +30,18 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before
background: rgb(255, 255, 0);
}
}

[data-rich-text-comment],
[data-rich-text-format-boundary] {
border-radius: $radius-small;
}

[data-rich-text-comment] {
background-color: currentColor;

span {
filter: invert(100%);
color: currentColor;
padding: 0 2px;
}
}
28 changes: 28 additions & 0 deletions packages/rich-text/src/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
30 changes: 30 additions & 0 deletions packages/rich-text/src/test/__snapshots__/to-dom.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,21 @@ exports[`recordToDom should not error with overlapping formats (2) 1`] = `
</body>
`;

exports[`recordToDom should preserve comments 1`] = `
<body>
<span
contenteditable="false"
data-rich-text-comment="comment"
>
<span>
comment
</span>
</span>
</body>
`;

exports[`recordToDom should preserve emoji 1`] = `
<body>
🍒
Expand All @@ -289,6 +304,21 @@ exports[`recordToDom should preserve emoji in formatting 1`] = `
</body>
`;

exports[`recordToDom should preserve funky comments 1`] = `
<body>
<span
contenteditable="false"
data-rich-text-comment="/funky"
>
<span>
/funky
</span>
</span>
</body>
`;

exports[`recordToDom should preserve non breaking space 1`] = `
<body>
test  test
Expand Down
52 changes: 52 additions & 0 deletions packages/rich-text/src/test/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,58 @@ export const spec = [
text: '\ufffc',
},
},
{
description: 'should preserve comments',
html: '<!--comment-->',
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: '<//funky>',
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 = [
Expand Down
12 changes: 9 additions & 3 deletions packages/rich-text/src/to-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ] );
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions packages/rich-text/src/to-html-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 `</{comment-content}>` for Bits, where `comment-content`
// would be `/{bit-name}` or `__{translatable-string}` (TBD).
return `<!--${ attributes[ 'data-rich-text-comment' ] }-->`;
}

let attributeString = '';

for ( const key in attributes ) {
Expand Down
15 changes: 14 additions & 1 deletion packages/rich-text/src/to-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,20 @@ 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' ],
},
} );
append(
append( pointer, { type: 'span' } ),
attributes[ 'data-rich-text-comment' ].trim()
);
} else if ( ! isEditableTree && type === 'script' ) {
pointer = append(
getParent( pointer ),
fromFormat( {
Expand Down

0 comments on commit b76d9f0

Please sign in to comment.