diff --git a/blocks/api/raw-handling/comment-remover.js b/blocks/api/raw-handling/comment-remover.js index 4cf85852bda42..93b580b5f44ea 100644 --- a/blocks/api/raw-handling/comment-remover.js +++ b/blocks/api/raw-handling/comment-remover.js @@ -8,50 +8,5 @@ export default function( node ) { return; } - if ( node.nodeValue.indexOf( 'more' ) === 0 ) { - // Grab any custom text in the comment - const customText = node.nodeValue.slice( 4 ).trim(); - - // When a comment is found, we need to look for any - // sibling, but it may not be a direct sibling - // (whitespace typically lies in between) - let sibling = node; - let noTeaser = false; - while ( ( sibling = sibling.nextSibling ) ) { - if ( - sibling.nodeType === COMMENT_NODE && - sibling.nodeValue === 'noteaser' - ) { - noTeaser = true; - sibling.parentNode.removeChild( sibling ); - break; - } - } - - // Conjure up a custom More element - const more = createMore( customText, noTeaser ); - - // Find the first ancestor to which the More element can be appended; - // appending to the closer P parents fails - let parent = node.parentNode; - while ( parent.nodeName.toLowerCase() === 'p' && parent.parentNode ) { - parent = parent.parentNode; - } - parent.appendChild( more ); - } - node.parentNode.removeChild( node ); } - -function createMore( customText, noTeaser ) { - const node = document.createElement( 'wp-block' ); - node.dataset.block = 'core/more'; - if ( customText ) { - node.dataset.customText = customText; - } - if ( noTeaser ) { - // "Boolean" data attribute - node.dataset.noTeaser = ''; - } - return node; -} diff --git a/blocks/api/raw-handling/index.js b/blocks/api/raw-handling/index.js index 9b6665e1eaaf1..da07a567f6abd 100644 --- a/blocks/api/raw-handling/index.js +++ b/blocks/api/raw-handling/index.js @@ -12,6 +12,7 @@ import { getBlockTypes, getUnknownTypeHandlerName } from '../registration'; import { getBlockAttributes, parseWithGrammar } from '../parser'; import normaliseBlocks from './normalise-blocks'; import stripAttributes from './strip-attributes'; +import specialCommentConverter from './special-comment-converter'; import commentRemover from './comment-remover'; import createUnwrapper from './create-unwrapper'; import isInlineContent from './is-inline-content'; @@ -96,6 +97,7 @@ export default function rawHandler( { HTML, plainText = '', mode = 'AUTO', tagNa // Add semantic formatting before attributes are stripped. formattingTransformer, stripAttributes, + specialCommentConverter, commentRemover, createUnwrapper( ( node ) => ! isInline( node, tagName ) ), ] ); @@ -124,6 +126,7 @@ export default function rawHandler( { HTML, plainText = '', mode = 'AUTO', tagNa // Add semantic formatting before attributes are stripped. formattingTransformer, stripAttributes, + specialCommentConverter, commentRemover, ! canUserUseUnfilteredHTML && createUnwrapper( ( element ) => element.nodeName === 'IFRAME' ), embeddedContentReducer, diff --git a/blocks/api/raw-handling/special-comment-converter.js b/blocks/api/raw-handling/special-comment-converter.js new file mode 100644 index 0000000000000..f3ea7828926de --- /dev/null +++ b/blocks/api/raw-handling/special-comment-converter.js @@ -0,0 +1,74 @@ +/** + * Browser dependencies + */ +const { COMMENT_NODE } = window.Node; + +/** + * Looks for `` comments, as well as the `` + * variant and its `` companion, and replaces them with a custom + * element representing a future block. + * + * The custom element is a way to bypass the rest of the `raw-handling` + * transforms, which would eliminate other kinds of node with which to carry + * ``'s data: nodes with `data` attributes, empty paragraphs, etc. + * + * The custom element is then expected to be recognized by any registered + * block's `raw` transform. + * + * @param {Node} node The node to be processed. + * @return {void} + */ +export default function( node ) { + if ( + node.nodeType !== COMMENT_NODE || + node.nodeValue.indexOf( 'more' ) !== 0 + ) { + // We don't specificially look for `noteaser`, meaning that if one is + // found on its own (and not adjacent to `more`), it will be lost. + return; + } + + // Grab any custom text in the comment + const customText = node.nodeValue.slice( 4 ).trim(); + + // When a `` comment is found, we need to look for any + // `` sibling, but it may not be a direct sibling + // (whitespace typically lies in between) + let sibling = node; + let noTeaser = false; + while ( ( sibling = sibling.nextSibling ) ) { + if ( + sibling.nodeType === COMMENT_NODE && + sibling.nodeValue === 'noteaser' + ) { + noTeaser = true; + sibling.parentNode.removeChild( sibling ); + break; + } + } + + // Conjure up a custom More element + const more = createMore( customText, noTeaser ); + + // Find the first ancestor to which the More element can be appended; + // appending to the closer P parents fails + let parent = node.parentNode; + while ( parent.nodeName.toLowerCase() === 'p' && parent.parentNode ) { + parent = parent.parentNode; + } + parent.appendChild( more ); + node.parentNode.removeChild( node ); +} + +function createMore( customText, noTeaser ) { + const node = document.createElement( 'wp-block' ); + node.dataset.block = 'core/more'; + if ( customText ) { + node.dataset.customText = customText; + } + if ( noTeaser ) { + // "Boolean" data attribute + node.dataset.noTeaser = ''; + } + return node; +}