UNPKG

@wordpress/blocks

Version:
87 lines (76 loc) 2.29 kB
/** * Internal dependencies */ import { getSibling } from './utils'; function isFormattingSpace( character ) { return ( character === ' ' || character === '\r' || character === '\n' || character === '\t' ); } /** * Removes spacing that formats HTML. * * @see https://www.w3.org/TR/css-text-3/#white-space-processing * * @param {Node} node The node to be processed. * @return {void} */ export default function htmlFormattingRemover( node ) { if ( node.nodeType !== node.TEXT_NODE ) { return; } // Ignore pre content. Note that this does not use Element#closest due to // a combination of (a) node may not be Element and (b) node.parentElement // does not have full support in all browsers (Internet Exporer). // // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility /** @type {Node?} */ let parent = node; while ( ( parent = parent.parentNode ) ) { if ( parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE' ) { return; } } // First, replace any sequence of HTML formatting space with a single space. let newData = node.data.replace( /[ \r\n\t]+/g, ' ' ); // Remove the leading space if the text element is at the start of a block, // is preceded by a line break element, or has a space in the previous // node. if ( newData[ 0 ] === ' ' ) { const previousSibling = getSibling( node, 'previous' ); if ( ! previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice( -1 ) === ' ' ) { newData = newData.slice( 1 ); } } // Remove the trailing space if the text element is at the end of a block, // is succeeded by a line break element, or has a space in the next text // node. if ( newData[ newData.length - 1 ] === ' ' ) { const nextSibling = getSibling( node, 'next' ); if ( ! nextSibling || nextSibling.nodeName === 'BR' || ( nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace( nextSibling.textContent[ 0 ] ) ) ) { newData = newData.slice( 0, -1 ); } } // If there's no data left, remove the node, so `previousSibling` stays // accurate. Otherwise, update the node data. if ( ! newData ) { node.parentNode.removeChild( node ); } else { node.data = newData; } }