UNPKG

@wordpress/blocks

Version:
8 lines (7 loc) 9.19 kB
{ "version": 3, "sources": ["../../../src/api/raw-handling/utils.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { isPhrasingContent, getPhrasingContentSchema } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport { hasBlockSupport } from '..';\nimport { getRawTransforms } from './get-raw-transforms';\n\nexport function getBlockContentSchemaFromTransforms( transforms, context ) {\n\tconst phrasingContentSchema = getPhrasingContentSchema( context );\n\tconst schemaArgs = { phrasingContentSchema, isPaste: context === 'paste' };\n\tconst schemas = transforms.map( ( { isMatch, blockName, schema } ) => {\n\t\tconst hasAnchorSupport = hasBlockSupport( blockName, 'anchor' );\n\n\t\tschema = typeof schema === 'function' ? schema( schemaArgs ) : schema;\n\n\t\t// If the block does not has anchor support and the transform does not\n\t\t// provides an isMatch we can return the schema right away.\n\t\tif ( ! hasAnchorSupport && ! isMatch ) {\n\t\t\treturn schema;\n\t\t}\n\n\t\tif ( ! schema ) {\n\t\t\treturn {};\n\t\t}\n\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries( schema ).map( ( [ key, value ] ) => {\n\t\t\t\tlet attributes = value.attributes || [];\n\t\t\t\t// If the block supports the \"anchor\" functionality, it needs to keep its ID attribute.\n\t\t\t\tif ( hasAnchorSupport ) {\n\t\t\t\t\tattributes = [ ...attributes, 'id' ];\n\t\t\t\t}\n\t\t\t\treturn [\n\t\t\t\t\tkey,\n\t\t\t\t\t{\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\tattributes,\n\t\t\t\t\t\tisMatch: isMatch ? isMatch : undefined,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t} )\n\t\t);\n\t} );\n\n\tfunction mergeTagNameSchemaProperties( objValue, srcValue, key ) {\n\t\tswitch ( key ) {\n\t\t\tcase 'children': {\n\t\t\t\tif ( objValue === '*' || srcValue === '*' ) {\n\t\t\t\t\treturn '*';\n\t\t\t\t}\n\n\t\t\t\treturn { ...objValue, ...srcValue };\n\t\t\t}\n\t\t\tcase 'attributes':\n\t\t\tcase 'require': {\n\t\t\t\treturn [ ...( objValue || [] ), ...( srcValue || [] ) ];\n\t\t\t}\n\t\t\tcase 'isMatch': {\n\t\t\t\t// If one of the values being merge is undefined (matches everything),\n\t\t\t\t// the result of the merge will be undefined.\n\t\t\t\tif ( ! objValue || ! srcValue ) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\t// When merging two isMatch functions, the result is a new function\n\t\t\t\t// that returns if one of the source functions returns true.\n\t\t\t\treturn ( ...args ) => {\n\t\t\t\t\treturn objValue( ...args ) || srcValue( ...args );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// A tagName schema is an object with children, attributes, require, and\n\t// isMatch properties.\n\tfunction mergeTagNameSchemas( a, b ) {\n\t\tfor ( const key in b ) {\n\t\t\ta[ key ] = a[ key ]\n\t\t\t\t? mergeTagNameSchemaProperties( a[ key ], b[ key ], key )\n\t\t\t\t: { ...b[ key ] };\n\t\t}\n\t\treturn a;\n\t}\n\n\t// A schema is an object with tagName schemas by tag name.\n\tfunction mergeSchemas( a, b ) {\n\t\tfor ( const key in b ) {\n\t\t\ta[ key ] = a[ key ]\n\t\t\t\t? mergeTagNameSchemas( a[ key ], b[ key ] )\n\t\t\t\t: { ...b[ key ] };\n\t\t}\n\t\treturn a;\n\t}\n\n\treturn schemas.reduce( mergeSchemas, {} );\n}\n\n/**\n * Gets the block content schema, which is extracted and merged from all\n * registered blocks with raw transforms.\n *\n * @param {string} context Set to \"paste\" when in paste context, where the\n * schema is more strict.\n *\n * @return {Object} A complete block content schema.\n */\nexport function getBlockContentSchema( context ) {\n\treturn getBlockContentSchemaFromTransforms( getRawTransforms(), context );\n}\n\n/**\n * Checks whether HTML can be considered plain text. That is, it does not contain\n * any elements that are not line breaks, or it only contains a single non-semantic\n * wrapper element (span) with no semantic child elements.\n *\n * @param {string} HTML The HTML to check.\n *\n * @return {boolean} Whether the HTML can be considered plain text.\n */\nexport function isPlain( HTML ) {\n\tif ( ! /<(?!br[ />])/i.test( HTML ) ) {\n\t\treturn true;\n\t}\n\n\tconst doc = document.implementation.createHTMLDocument( '' );\n\tdoc.body.innerHTML = HTML;\n\n\tif ( doc.body.children.length !== 1 ) {\n\t\treturn false;\n\t}\n\n\tconst wrapper = doc.body.children.item( 0 );\n\n\tconst descendants = wrapper.getElementsByTagName( '*' );\n\tfor ( let i = 0; i < descendants.length; i++ ) {\n\t\tif ( descendants.item( i ).tagName !== 'BR' ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif ( wrapper.tagName !== 'SPAN' ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Given node filters, deeply filters and mutates a NodeList.\n *\n * @param {NodeList} nodeList The nodeList to filter.\n * @param {Array} filters An array of functions that can mutate with the provided node.\n * @param {Document} doc The document of the nodeList.\n * @param {Object} schema The schema to use.\n */\nexport function deepFilterNodeList( nodeList, filters, doc, schema ) {\n\tArray.from( nodeList ).forEach( ( node ) => {\n\t\tdeepFilterNodeList( node.childNodes, filters, doc, schema );\n\n\t\tfilters.forEach( ( item ) => {\n\t\t\t// Make sure the node is still attached to the document.\n\t\t\tif ( ! doc.contains( node ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titem( node, doc, schema );\n\t\t} );\n\t} );\n}\n\n/**\n * Given node filters, deeply filters HTML tags.\n * Filters from the deepest nodes to the top.\n *\n * @param {string} HTML The HTML to filter.\n * @param {Array} filters An array of functions that can mutate with the provided node.\n * @param {Object} schema The schema to use.\n *\n * @return {string} The filtered HTML.\n */\nexport function deepFilterHTML( HTML, filters = [], schema ) {\n\tconst doc = document.implementation.createHTMLDocument( '' );\n\n\tdoc.body.innerHTML = HTML;\n\n\tdeepFilterNodeList( doc.body.childNodes, filters, doc, schema );\n\n\treturn doc.body.innerHTML;\n}\n\n/**\n * Gets a sibling within text-level context.\n *\n * @param {Element} node The subject node.\n * @param {string} which \"next\" or \"previous\".\n */\nexport function getSibling( node, which ) {\n\tconst sibling = node[ `${ which }Sibling` ];\n\n\tif ( sibling && isPhrasingContent( sibling ) ) {\n\t\treturn sibling;\n\t}\n\n\tconst { parentNode } = node;\n\n\tif ( ! parentNode || ! isPhrasingContent( parentNode ) ) {\n\t\treturn;\n\t}\n\n\treturn getSibling( parentNode, which );\n}\n"], "mappings": "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", "names": [] }