Skip to content

Commit

Permalink
Restore stripping white space when parsing HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Nov 10, 2023
1 parent e11bc4c commit 0c26493
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 2 deletions.
6 changes: 6 additions & 0 deletions packages/block-editor/src/components/rich-text/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ _Optional._ Whether to show the input is selected or not in order to show the fo

_Optional._ A list of autocompleters to use instead of the default.

### `preserveWhiteSpace: Boolean`

_Optional._ Whether or not to preserve white space characters in the `value`.
Normally tab, newline and space characters are collapsed to a single space or
trimmed.

## RichText.Content

`RichText.Content` should be used in the `save` function of your block to correctly save rich text content.
Expand Down
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function RichTextWrapper(
__unstableOnSplitAtEnd: onSplitAtEnd,
__unstableOnSplitAtDoubleLineEnd: onSplitAtDoubleLineEnd,
identifier,
preserveWhiteSpace,
__unstablePastePlainText: pastePlainText,
__unstableEmbedURLOnPaste,
__unstableDisableFormats: disableFormats,
Expand Down Expand Up @@ -261,6 +262,7 @@ export function RichTextWrapper(
placeholder,
__unstableIsSelected: isSelected,
__unstableDisableFormats: disableFormats,
preserveWhiteSpace,
__unstableDependencies: [ ...dependencies, tagName ],
__unstableAfterParse: addEditorOnlyFormats,
__unstableBeforeSerialize: removeEditorOnlyFormats,
Expand Down
3 changes: 2 additions & 1 deletion packages/block-library/src/code/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"content": {
"type": "string",
"source": "html",
"selector": "code"
"selector": "code",
"__unstablePreserveWhiteSpace": true
}
},
"supports": {
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/code/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function CodeEdit( {
onMerge={ mergeBlocks }
placeholder={ __( 'Write code…' ) }
aria-label={ __( 'Code' ) }
preserveWhiteSpace
__unstablePastePlainText
__unstableOnSplitAtDoubleLineEnd={ () =>
insertBlocksAfter( createBlock( getDefaultBlockName() ) )
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/preformatted/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"source": "html",
"selector": "pre",
"default": "",
"__unstablePreserveWhiteSpace": true,
"__experimentalRole": "content"
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/preformatted/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function PreformattedEdit( {
<RichText
tagName="pre"
identifier="content"
preserveWhiteSpace
value={ content }
onChange={ ( nextContent ) => {
setAttributes( {
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/verse/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"source": "html",
"selector": "pre",
"default": "",
"__unstablePreserveWhiteSpace": true,
"__experimentalRole": "content"
},
"textAlign": {
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/verse/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function VerseEdit( {
<RichText
tagName="pre"
identifier="content"
preserveWhiteSpace
value={ content }
onChange={ ( nextContent ) => {
setAttributes( {
Expand Down
1 change: 1 addition & 0 deletions packages/rich-text/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ _Parameters_
- _$1.text_ `[string]`: Text to create value from.
- _$1.html_ `[string]`: HTML to create value from.
- _$1.range_ `[Range]`: Range to create value from.
- _$1.preserveWhiteSpace_ `[boolean]`: Whether or not to collapse white space characters.
- _$1.\_\_unstableIsEditableTree_ `[boolean]`:

_Returns_
Expand Down
3 changes: 2 additions & 1 deletion packages/rich-text/src/component/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function useRichText( {
selectionEnd,
placeholder,
onSelectionChange,
preserveWhiteSpace,
onChange,
__unstableDisableFormats: disableFormats,
__unstableIsSelected: isSelected,
Expand Down Expand Up @@ -69,7 +70,7 @@ export function useRichText( {

function setRecordFromProps() {
_value.current = value;
record.current = create( { html: value } );
record.current = create( { html: value, preserveWhiteSpace } );
if ( disableFormats ) {
record.current.formats = Array( value.length );
record.current.replacements = Array( value.length );
Expand Down
22 changes: 22 additions & 0 deletions packages/rich-text/src/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ function toFormat( { tagName, attributes } ) {
* @param {string} [$1.text] Text to create value from.
* @param {string} [$1.html] HTML to create value from.
* @param {Range} [$1.range] Range to create value from.
* @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse
* white space characters.
* @param {boolean} [$1.__unstableIsEditableTree]
*
* @return {RichTextValue} A rich text value.
Expand All @@ -145,6 +147,7 @@ export function create( {
html,
range,
__unstableIsEditableTree: isEditableTree,
preserveWhiteSpace,
} = {} ) {
if ( typeof text === 'string' && text.length > 0 ) {
return {
Expand All @@ -155,6 +158,7 @@ export function create( {
}

if ( typeof html === 'string' && html.length > 0 ) {
html = preserveWhiteSpace ? html : collapseWhiteSpace( html );
// It does not matter which document this is, we're just using it to
// parse.
element = createElement( document, html );
Expand Down Expand Up @@ -264,6 +268,24 @@ function filterRange( node, range, filter ) {
return { startContainer, startOffset, endContainer, endOffset };
}

/**
* Collapse any whitespace used for HTML formatting to one space character,
* because it will also be displayed as such by the browser.
*
* We need to strip it from the content because we use white-space: pre-wrap for
* displaying editable rich text. Without using white-space: pre-wrap, the
* browser will litter the content with non breaking spaces, among other issues.
* See packages/rich-text/src/component/use-default-style.js.
*
* @see
* https://developer.mozilla.org/en-US/docs/Web/CSS/white-space-collapse#collapsing_of_white_space
*
* @param {string} string
*/
function collapseWhiteSpace( string ) {
return string.replace( /[ \n\r\t]+/g, ' ' ).replace( /^ | $/g, '' );
}

/**
* Removes reserved characters used by rich-text (zero width non breaking spaces added by `toTree` and object replacement characters).
*
Expand Down

0 comments on commit 0c26493

Please sign in to comment.