From 8ac960333719b30058a4cad20228b0c35356dd83 Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 31 Mar 2023 22:23:58 +0200 Subject: [PATCH 01/11] Use PostCSS + PostCSS plugins for style transformation. --- packages/block-editor/package.json | 3 + .../src/utils/transform-styles/index.js | 29 +--- .../transforms/url-rewrite.js | 139 ------------------ .../utils/transform-styles/transforms/wrap.js | 56 ------- .../test/__snapshots__/build.js.snap | 18 +++ 5 files changed, 29 insertions(+), 216 deletions(-) delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/url-rewrite.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/wrap.js diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 225d9c987638a..5cc8fe9358e89 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -73,6 +73,9 @@ "fast-deep-equal": "^3.1.3", "inherits": "^2.0.3", "memize": "^2.1.0", + "postcss": "^8.4.21", + "postcss-editor-styles": "^0.3.0", + "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", "rememo": "^4.0.2", diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index c43e816d401e9..7d8833db6ebe3 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -1,14 +1,9 @@ /** - * WordPress dependencies + * External dependencies */ -import { compose } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import traverse from './traverse'; -import urlRewrite from './transforms/url-rewrite'; -import wrap from './transforms/wrap'; +import postcss from 'postcss'; +import wrap from 'postcss-editor-styles'; +import rebaseUrl from 'postcss-urlrebase'; /** * Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. @@ -19,18 +14,10 @@ import wrap from './transforms/wrap'; */ const transformStyles = ( styles, wrapperClassName = '' ) => { return Object.values( styles ?? [] ).map( ( { css, baseURL } ) => { - const transforms = []; - if ( wrapperClassName ) { - transforms.push( wrap( wrapperClassName ) ); - } - if ( baseURL ) { - transforms.push( urlRewrite( baseURL ) ); - } - if ( transforms.length ) { - return traverse( css, compose( transforms ) ); - } - - return css; + return postcss( [ + wrap( { scopeTo: wrapperClassName } ), + rebaseUrl( { rootUrl: baseURL } ), + ] ).process( css, {} ); } ); }; diff --git a/packages/block-editor/src/utils/transform-styles/transforms/url-rewrite.js b/packages/block-editor/src/utils/transform-styles/transforms/url-rewrite.js deleted file mode 100644 index e3461cb1088d7..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/url-rewrite.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Return `true` if the given path is http/https. - * - * @param {string} filePath path - * - * @return {boolean} is remote path. - */ -function isRemotePath( filePath ) { - return /^(?:https?:)?\/\//.test( filePath ); -} - -/** - * Return `true` if the given filePath is an absolute url. - * - * @param {string} filePath path - * - * @return {boolean} is absolute path. - */ -function isAbsolutePath( filePath ) { - return /^\/(?!\/)/.test( filePath ); -} - -/** - * Whether or not the url should be inluded. - * - * @param {Object} meta url meta info - * - * @return {boolean} is valid. - */ -function isValidURL( meta ) { - // Ignore hashes or data uris. - if ( - meta.value.indexOf( 'data:' ) === 0 || - meta.value.indexOf( '#' ) === 0 - ) { - return false; - } - - if ( isAbsolutePath( meta.value ) ) { - return false; - } - - // Do not handle the http/https urls if `includeRemote` is false. - if ( isRemotePath( meta.value ) ) { - return false; - } - - return true; -} - -/** - * Get the absolute path of the url, relative to the basePath - * - * @param {string} str the url - * @param {string} baseURL base URL - * - * @return {string} the full path to the file - */ -function getResourcePath( str, baseURL ) { - return new URL( str, baseURL ).toString(); -} - -/** - * Process the single `url()` pattern - * - * @param {string} baseURL the base URL for relative URLs. - * - * @return {Promise} the Promise. - */ -function processURL( baseURL ) { - return ( meta ) => ( { - ...meta, - newUrl: - 'url(' + - meta.before + - meta.quote + - getResourcePath( meta.value, baseURL ) + - meta.quote + - meta.after + - ')', - } ); -} - -/** - * Get all `url()`s, and return the meta info - * - * @param {string} value decl.value. - * - * @return {Array} the urls. - */ -function getURLs( value ) { - const reg = /url\((\s*)(['"]?)(.+?)\2(\s*)\)/g; - let match; - const URLs = []; - - while ( ( match = reg.exec( value ) ) !== null ) { - const meta = { - source: match[ 0 ], - before: match[ 1 ], - quote: match[ 2 ], - value: match[ 3 ], - after: match[ 4 ], - }; - if ( isValidURL( meta ) ) { - URLs.push( meta ); - } - } - return URLs; -} - -/** - * Replace the raw value's `url()` segment to the new value - * - * @param {string} raw the raw value. - * @param {Array} URLs the URLs to replace. - * - * @return {string} the new value. - */ -function replaceURLs( raw, URLs ) { - URLs.forEach( ( item ) => { - raw = raw.replace( item.source, item.newUrl ); - } ); - - return raw; -} - -const rewrite = ( rootURL ) => ( node ) => { - if ( node.type === 'declaration' ) { - const updatedURLs = getURLs( node.value ).map( processURL( rootURL ) ); - return { - ...node, - value: replaceURLs( node.value, updatedURLs ), - }; - } - - return node; -}; - -export default rewrite; diff --git a/packages/block-editor/src/utils/transform-styles/transforms/wrap.js b/packages/block-editor/src/utils/transform-styles/transforms/wrap.js deleted file mode 100644 index 74b940f80352b..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/wrap.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @constant string IS_ROOT_TAG Regex to check if the selector is a root tag selector. - */ -const IS_ROOT_TAG = /^(body|html|:root).*$/; - -/** - * Creates a callback to modify selectors so they only apply within a certain - * namespace. - * - * @param {string} namespace Namespace to prefix selectors with. - * @param {string[]} ignore Selectors to not prefix. - * - * @return {(node: Object) => Object} Callback to wrap selectors. - */ -const wrap = - ( namespace, ignore = [] ) => - ( node ) => { - /** - * Updates selector if necessary. - * - * @param {string} selector Selector to modify. - * - * @return {string} Updated selector. - */ - const updateSelector = ( selector ) => { - if ( ignore.includes( selector.trim() ) ) { - return selector; - } - - // Skip the update when a selector already has a namespace + space (" "). - if ( selector.trim().startsWith( `${ namespace } ` ) ) { - return selector; - } - - // Anything other than a root tag is always prefixed. - { - if ( ! selector.match( IS_ROOT_TAG ) ) { - return namespace + ' ' + selector; - } - } - - // HTML and Body elements cannot be contained within our container so lets extract their styles. - return selector.replace( /^(body|html|:root)/, namespace ); - }; - - if ( node.type === 'rule' ) { - return { - ...node, - selectors: node.selectors.map( updateSelector ), - }; - } - - return node; - }; - -export default wrap; diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 254950316e496..ae82311b07b28 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -31,6 +31,11 @@ exports[`DependencyExtractionWebpackPlugin Webpack \`combine-assets\` should pro ] `; +exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: Asset file 'assets.php' should match snapshot 1`] = ` +" array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'bf200ecb3dcb6881a1f3'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => '0af6c51a8e6ac934b85a')); +" +`; + exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array('wp-blob'), 'version' => '47f8a22aa6c04c930f5f'); " @@ -49,6 +54,19 @@ exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should pro ] `; +exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: External modules should match snapshot 2`] = ` +[ + { + "externalType": "window", + "request": [ + "wp", + "blob", + ], + "userRequest": "@wordpress/blob", + }, +] +`; + exports[`DependencyExtractionWebpackPlugin Webpack \`function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = ` " array('lodash', 'wp-blob'), 'version' => '35d057cb1c8a30094445'); " From 5ffcc290d05d2347b59e6cfa119be85fc8d31bac Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Mon, 25 Sep 2023 23:00:15 -0300 Subject: [PATCH 02/11] Remove the now replaced CSS parsing code. --- packages/block-editor/package.json | 4 +- .../src/utils/transform-styles/ast/index.js | 5 - .../src/utils/transform-styles/ast/parse.js | 732 ------------------ .../ast/stringify/compiler.js | 50 -- .../ast/stringify/compress.js | 238 ------ .../ast/stringify/identity.js | 286 ------- .../transform-styles/ast/stringify/index.js | 32 - .../test/__snapshots__/traverse.js.snap | 7 - .../utils/transform-styles/test/traverse.js | 24 - .../test/__snapshots__/url-rewrite.js.snap | 25 - .../test/__snapshots__/wrap.js.snap | 64 -- .../transforms/test/url-rewrite.js | 39 - .../transform-styles/transforms/test/wrap.js | 95 --- .../src/utils/transform-styles/traverse.js | 32 - 14 files changed, 1 insertion(+), 1632 deletions(-) delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/index.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/parse.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/compiler.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/compress.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/identity.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/index.js delete mode 100644 packages/block-editor/src/utils/transform-styles/test/__snapshots__/traverse.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/test/traverse.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/url-rewrite.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/url-rewrite.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/wrap.js delete mode 100644 packages/block-editor/src/utils/transform-styles/traverse.js diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 5cc8fe9358e89..71c0ac5761039 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -71,7 +71,6 @@ "diff": "^4.0.2", "dom-scroll-into-view": "^1.2.1", "fast-deep-equal": "^3.1.3", - "inherits": "^2.0.3", "memize": "^2.1.0", "postcss": "^8.4.21", "postcss-editor-styles": "^0.3.0", @@ -79,8 +78,7 @@ "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", "rememo": "^4.0.2", - "remove-accents": "^0.5.0", - "traverse": "^0.6.6" + "remove-accents": "^0.5.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/block-editor/src/utils/transform-styles/ast/index.js b/packages/block-editor/src/utils/transform-styles/ast/index.js deleted file mode 100644 index b4dc1de499f47..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -export { default as parse } from './parse'; -export { default as stringify } from './stringify'; diff --git a/packages/block-editor/src/utils/transform-styles/ast/parse.js b/packages/block-editor/src/utils/transform-styles/ast/parse.js deleted file mode 100644 index 8f7d227d61442..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/parse.js +++ /dev/null @@ -1,732 +0,0 @@ -/* eslint-disable @wordpress/no-unused-vars-before-return */ - -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -// http://www.w3.org/TR/CSS21/grammar.htm -// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 -const commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; - -export default function ( css, options ) { - options = options || {}; - - /** - * Positional. - */ - - let lineno = 1; - let column = 1; - - /** - * Update lineno and column based on `str`. - */ - - function updatePosition( str ) { - const lines = str.match( /\n/g ); - if ( lines ) { - lineno += lines.length; - } - const i = str.lastIndexOf( '\n' ); - // eslint-disable-next-line no-bitwise - column = ~i ? str.length - i : column + str.length; - } - - /** - * Mark position and patch `node.position`. - */ - - function position() { - const start = { line: lineno, column }; - return function ( node ) { - node.position = new Position( start ); - whitespace(); - return node; - }; - } - - /** - * Store position information for a node - */ - - function Position( start ) { - this.start = start; - this.end = { line: lineno, column }; - this.source = options.source; - } - - /** - * Non-enumerable source string - */ - - Position.prototype.content = css; - - /** - * Error `msg`. - */ - - const errorsList = []; - - function error( msg ) { - const err = new Error( - options.source + ':' + lineno + ':' + column + ': ' + msg - ); - err.reason = msg; - err.filename = options.source; - err.line = lineno; - err.column = column; - err.source = css; - - if ( options.silent ) { - errorsList.push( err ); - } else { - throw err; - } - } - - /** - * Parse stylesheet. - */ - - function stylesheet() { - const rulesList = rules(); - - return { - type: 'stylesheet', - stylesheet: { - source: options.source, - rules: rulesList, - parsingErrors: errorsList, - }, - }; - } - - /** - * Opening brace. - */ - - function open() { - return match( /^{\s*/ ); - } - - /** - * Closing brace. - */ - - function close() { - return match( /^}/ ); - } - - /** - * Parse ruleset. - */ - - function rules() { - let node; - const accumulator = []; - whitespace(); - comments( accumulator ); - while ( - css.length && - css.charAt( 0 ) !== '}' && - ( node = atrule() || rule() ) - ) { - if ( node !== false ) { - accumulator.push( node ); - comments( accumulator ); - } - } - return accumulator; - } - - /** - * Match `re` and return captures. - */ - - function match( re ) { - const m = re.exec( css ); - if ( ! m ) { - return; - } - const str = m[ 0 ]; - updatePosition( str ); - css = css.slice( str.length ); - return m; - } - - /** - * Parse whitespace. - */ - - function whitespace() { - match( /^\s*/ ); - } - - /** - * Parse comments; - */ - - function comments( accumulator ) { - let c; - accumulator = accumulator || []; - // eslint-disable-next-line no-cond-assign - while ( ( c = comment() ) ) { - if ( c !== false ) { - accumulator.push( c ); - } - } - return accumulator; - } - - /** - * Parse comment. - */ - - function comment() { - const pos = position(); - if ( '/' !== css.charAt( 0 ) || '*' !== css.charAt( 1 ) ) { - return; - } - - let i = 2; - while ( - '' !== css.charAt( i ) && - ( '*' !== css.charAt( i ) || '/' !== css.charAt( i + 1 ) ) - ) { - ++i; - } - i += 2; - - if ( '' === css.charAt( i - 1 ) ) { - return error( 'End of comment missing' ); - } - - const str = css.slice( 2, i - 2 ); - column += 2; - updatePosition( str ); - css = css.slice( i ); - column += 2; - - return pos( { - type: 'comment', - comment: str, - } ); - } - - /** - * Parse selector. - */ - - function selector() { - const m = match( /^([^{]+)/ ); - if ( ! m ) { - return; - } - // FIXME: Remove all comments from selectors http://ostermiller.org/findcomment.html - return trim( m[ 0 ] ) - .replace( /\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '' ) - .replace( /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function ( matched ) { - return matched.replace( /,/g, '\u200C' ); - } ) - .split( /\s*(?![^(]*\)),\s*/ ) - .map( function ( s ) { - return s.replace( /\u200C/g, ',' ); - } ); - } - - /** - * Parse declaration. - */ - - function declaration() { - const pos = position(); - - // prop. - let prop = match( /^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/ ); - if ( ! prop ) { - return; - } - prop = trim( prop[ 0 ] ); - - // : - if ( ! match( /^:\s*/ ) ) { - return error( "property missing ':'" ); - } - - // val. - const val = match( - /^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/ - ); - - const ret = pos( { - type: 'declaration', - property: prop.replace( commentre, '' ), - value: val ? trim( val[ 0 ] ).replace( commentre, '' ) : '', - } ); - - // ; - match( /^[;\s]*/ ); - - return ret; - } - - /** - * Parse declarations. - */ - - function declarations() { - const decls = []; - - if ( ! open() ) { - return error( "missing '{'" ); - } - comments( decls ); - - // declarations. - let decl; - // eslint-disable-next-line no-cond-assign - while ( ( decl = declaration() ) ) { - if ( decl !== false ) { - decls.push( decl ); - comments( decls ); - } - } - - if ( ! close() ) { - return error( "missing '}'" ); - } - return decls; - } - - /** - * Parse keyframe. - */ - - function keyframe() { - let m; - const vals = []; - const pos = position(); - - // eslint-disable-next-line no-cond-assign - while ( ( m = match( /^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/ ) ) ) { - vals.push( m[ 1 ] ); - match( /^,\s*/ ); - } - - if ( ! vals.length ) { - return; - } - - return pos( { - type: 'keyframe', - values: vals, - declarations: declarations(), - } ); - } - - /** - * Parse keyframes. - */ - - function atkeyframes() { - const pos = position(); - let m = match( /^@([-\w]+)?keyframes\s*/ ); - - if ( ! m ) { - return; - } - const vendor = m[ 1 ]; - - // identifier - m = match( /^([-\w]+)\s*/ ); - if ( ! m ) { - return error( '@keyframes missing name' ); - } - const name = m[ 1 ]; - - if ( ! open() ) { - return error( "@keyframes missing '{'" ); - } - - let frame; - let frames = comments(); - // eslint-disable-next-line no-cond-assign - while ( ( frame = keyframe() ) ) { - frames.push( frame ); - frames = frames.concat( comments() ); - } - - if ( ! close() ) { - return error( "@keyframes missing '}'" ); - } - - return pos( { - type: 'keyframes', - name, - vendor, - keyframes: frames, - } ); - } - - /** - * Parse supports. - */ - - function atsupports() { - const pos = position(); - const m = match( /^@supports *([^{]+)/ ); - - if ( ! m ) { - return; - } - const supports = trim( m[ 1 ] ); - - if ( ! open() ) { - return error( "@supports missing '{'" ); - } - - const style = comments().concat( rules() ); - - if ( ! close() ) { - return error( "@supports missing '}'" ); - } - - return pos( { - type: 'supports', - supports, - rules: style, - } ); - } - - /** - * Parse host. - */ - - function athost() { - const pos = position(); - const m = match( /^@host\s*/ ); - - if ( ! m ) { - return; - } - - if ( ! open() ) { - return error( "@host missing '{'" ); - } - - const style = comments().concat( rules() ); - - if ( ! close() ) { - return error( "@host missing '}'" ); - } - - return pos( { - type: 'host', - rules: style, - } ); - } - - /** - * Parse media. - */ - - function atmedia() { - const pos = position(); - const m = match( /^@media *([^{]+)/ ); - - if ( ! m ) { - return; - } - const media = trim( m[ 1 ] ); - - if ( ! open() ) { - return error( "@media missing '{'" ); - } - - const style = comments().concat( rules() ); - - if ( ! close() ) { - return error( "@media missing '}'" ); - } - - return pos( { - type: 'media', - media, - rules: style, - } ); - } - - /** - * Parse container. - */ - - function atcontainer() { - const pos = position(); - const m = match( /^@container *([^{]+)/ ); - - if ( ! m ) { - return; - } - const container = trim( m[ 1 ] ); - - if ( ! open() ) { - return error( "@container missing '{'" ); - } - - const style = comments().concat( rules() ); - - if ( ! close() ) { - return error( "@container missing '}'" ); - } - - return pos( { - type: 'container', - container, - rules: style, - } ); - } - - /** - * Parse custom-media. - */ - - function atcustommedia() { - const pos = position(); - const m = match( /^@custom-media\s+(--[^\s]+)\s*([^{;]+);/ ); - if ( ! m ) { - return; - } - - return pos( { - type: 'custom-media', - name: trim( m[ 1 ] ), - media: trim( m[ 2 ] ), - } ); - } - - /** - * Parse paged media. - */ - - function atpage() { - const pos = position(); - const m = match( /^@page */ ); - if ( ! m ) { - return; - } - - const sel = selector() || []; - - if ( ! open() ) { - return error( "@page missing '{'" ); - } - let decls = comments(); - - // declarations. - let decl; - // eslint-disable-next-line no-cond-assign - while ( ( decl = declaration() ) ) { - decls.push( decl ); - decls = decls.concat( comments() ); - } - - if ( ! close() ) { - return error( "@page missing '}'" ); - } - - return pos( { - type: 'page', - selectors: sel, - declarations: decls, - } ); - } - - /** - * Parse document. - */ - - function atdocument() { - const pos = position(); - const m = match( /^@([-\w]+)?document *([^{]+)/ ); - if ( ! m ) { - return; - } - - const vendor = trim( m[ 1 ] ); - const doc = trim( m[ 2 ] ); - - if ( ! open() ) { - return error( "@document missing '{'" ); - } - - const style = comments().concat( rules() ); - - if ( ! close() ) { - return error( "@document missing '}'" ); - } - - return pos( { - type: 'document', - document: doc, - vendor, - rules: style, - } ); - } - - /** - * Parse font-face. - */ - - function atfontface() { - const pos = position(); - const m = match( /^@font-face\s*/ ); - if ( ! m ) { - return; - } - - if ( ! open() ) { - return error( "@font-face missing '{'" ); - } - let decls = comments(); - - // declarations. - let decl; - // eslint-disable-next-line no-cond-assign - while ( ( decl = declaration() ) ) { - decls.push( decl ); - decls = decls.concat( comments() ); - } - - if ( ! close() ) { - return error( "@font-face missing '}'" ); - } - - return pos( { - type: 'font-face', - declarations: decls, - } ); - } - - /** - * Parse import - */ - - const atimport = _compileAtrule( 'import' ); - - /** - * Parse charset - */ - - const atcharset = _compileAtrule( 'charset' ); - - /** - * Parse namespace - */ - - const atnamespace = _compileAtrule( 'namespace' ); - - /** - * Parse non-block at-rules - */ - - function _compileAtrule( name ) { - const re = new RegExp( '^@' + name + '\\s*([^;]+);' ); - return function () { - const pos = position(); - const m = match( re ); - if ( ! m ) { - return; - } - const ret = { type: name }; - ret[ name ] = m[ 1 ].trim(); - return pos( ret ); - }; - } - - /** - * Parse at rule. - */ - - function atrule() { - if ( css[ 0 ] !== '@' ) { - return; - } - - return ( - atkeyframes() || - atmedia() || - atcontainer() || - atcustommedia() || - atsupports() || - atimport() || - atcharset() || - atnamespace() || - atdocument() || - atpage() || - athost() || - atfontface() - ); - } - - /** - * Parse rule. - */ - - function rule() { - const pos = position(); - const sel = selector(); - - if ( ! sel ) { - return error( 'selector missing' ); - } - comments(); - - return pos( { - type: 'rule', - selectors: sel, - declarations: declarations(), - } ); - } - - return addParent( stylesheet() ); -} - -/** - * Trim `str`. - */ - -function trim( str ) { - return str ? str.replace( /^\s+|\s+$/g, '' ) : ''; -} - -/** - * Adds non-enumerable parent node reference to each node. - */ - -function addParent( obj, parent ) { - const isNode = obj && typeof obj.type === 'string'; - const childParent = isNode ? obj : parent; - - for ( const k in obj ) { - const value = obj[ k ]; - if ( Array.isArray( value ) ) { - value.forEach( function ( v ) { - addParent( v, childParent ); - } ); - } else if ( value && typeof value === 'object' ) { - addParent( value, childParent ); - } - } - - if ( isNode ) { - Object.defineProperty( obj, 'parent', { - configurable: true, - writable: true, - enumerable: false, - value: parent || null, - } ); - } - - return obj; -} - -/* eslint-enable @wordpress/no-unused-vars-before-return */ diff --git a/packages/block-editor/src/utils/transform-styles/ast/stringify/compiler.js b/packages/block-editor/src/utils/transform-styles/ast/stringify/compiler.js deleted file mode 100644 index d2500b730424f..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/stringify/compiler.js +++ /dev/null @@ -1,50 +0,0 @@ -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -/** - * Expose `Compiler`. - */ - -export default Compiler; - -/** - * Initialize a compiler. - */ - -function Compiler( opts ) { - this.options = opts || {}; -} - -/** - * Emit `str` - */ - -Compiler.prototype.emit = function ( str ) { - return str; -}; - -/** - * Visit `node`. - */ - -Compiler.prototype.visit = function ( node ) { - return this[ node.type ]( node ); -}; - -/** - * Map visit over array of `nodes`, optionally using a `delim` - */ - -Compiler.prototype.mapVisit = function ( nodes, delim ) { - let buf = ''; - delim = delim || ''; - - for ( let i = 0, length = nodes.length; i < length; i++ ) { - buf += this.visit( nodes[ i ] ); - if ( delim && i < length - 1 ) { - buf += this.emit( delim ); - } - } - - return buf; -}; diff --git a/packages/block-editor/src/utils/transform-styles/ast/stringify/compress.js b/packages/block-editor/src/utils/transform-styles/ast/stringify/compress.js deleted file mode 100644 index 6a2a3af3769be..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/stringify/compress.js +++ /dev/null @@ -1,238 +0,0 @@ -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -/** - * External dependencies - */ -import inherits from 'inherits'; - -/** - * Internal dependencies - */ -import Base from './compiler'; - -/** - * Expose compiler. - */ - -export default Compiler; - -/** - * Initialize a new `Compiler`. - */ - -function Compiler( options ) { - Base.call( this, options ); -} - -/** - * Inherit from `Base.prototype`. - */ - -inherits( Compiler, Base ); - -/** - * Compile `node`. - */ - -Compiler.prototype.compile = function ( node ) { - return node.stylesheet.rules.map( this.visit, this ).join( '' ); -}; - -/** - * Visit comment node. - */ - -Compiler.prototype.comment = function ( node ) { - return this.emit( '', node.position ); -}; - -/** - * Visit import node. - */ - -Compiler.prototype.import = function ( node ) { - return this.emit( '@import ' + node.import + ';', node.position ); -}; - -/** - * Visit media node. - */ - -Compiler.prototype.media = function ( node ) { - return ( - this.emit( '@media ' + node.media, node.position ) + - this.emit( '{' ) + - this.mapVisit( node.rules ) + - this.emit( '}' ) - ); -}; - -/** - * Visit container node. - */ - -Compiler.prototype.container = function ( node ) { - return ( - this.emit( '@container ' + node.container, node.position ) + - this.emit( '{' ) + - this.mapVisit( node.rules ) + - this.emit( '}' ) - ); -}; - -/** - * Visit document node. - */ - -Compiler.prototype.document = function ( node ) { - const doc = '@' + ( node.vendor || '' ) + 'document ' + node.document; - - return ( - this.emit( doc, node.position ) + - this.emit( '{' ) + - this.mapVisit( node.rules ) + - this.emit( '}' ) - ); -}; - -/** - * Visit charset node. - */ - -Compiler.prototype.charset = function ( node ) { - return this.emit( '@charset ' + node.charset + ';', node.position ); -}; - -/** - * Visit namespace node. - */ - -Compiler.prototype.namespace = function ( node ) { - return this.emit( '@namespace ' + node.namespace + ';', node.position ); -}; - -/** - * Visit supports node. - */ - -Compiler.prototype.supports = function ( node ) { - return ( - this.emit( '@supports ' + node.supports, node.position ) + - this.emit( '{' ) + - this.mapVisit( node.rules ) + - this.emit( '}' ) - ); -}; - -/** - * Visit keyframes node. - */ - -Compiler.prototype.keyframes = function ( node ) { - return ( - this.emit( - '@' + ( node.vendor || '' ) + 'keyframes ' + node.name, - node.position - ) + - this.emit( '{' ) + - this.mapVisit( node.keyframes ) + - this.emit( '}' ) - ); -}; - -/** - * Visit keyframe node. - */ - -Compiler.prototype.keyframe = function ( node ) { - const decls = node.declarations; - - return ( - this.emit( node.values.join( ',' ), node.position ) + - this.emit( '{' ) + - this.mapVisit( decls ) + - this.emit( '}' ) - ); -}; - -/** - * Visit page node. - */ - -Compiler.prototype.page = function ( node ) { - const sel = node.selectors.length ? node.selectors.join( ', ' ) : ''; - - return ( - this.emit( '@page ' + sel, node.position ) + - this.emit( '{' ) + - this.mapVisit( node.declarations ) + - this.emit( '}' ) - ); -}; - -/** - * Visit font-face node. - */ - -Compiler.prototype[ 'font-face' ] = function ( node ) { - return ( - this.emit( '@font-face', node.position ) + - this.emit( '{' ) + - this.mapVisit( node.declarations ) + - this.emit( '}' ) - ); -}; - -/** - * Visit host node. - */ - -Compiler.prototype.host = function ( node ) { - return ( - this.emit( '@host', node.position ) + - this.emit( '{' ) + - this.mapVisit( node.rules ) + - this.emit( '}' ) - ); -}; - -/** - * Visit custom-media node. - */ - -Compiler.prototype[ 'custom-media' ] = function ( node ) { - return this.emit( - '@custom-media ' + node.name + ' ' + node.media + ';', - node.position - ); -}; - -/** - * Visit rule node. - */ - -Compiler.prototype.rule = function ( node ) { - const decls = node.declarations; - if ( ! decls.length ) { - return ''; - } - - return ( - this.emit( node.selectors.join( ',' ), node.position ) + - this.emit( '{' ) + - this.mapVisit( decls ) + - this.emit( '}' ) - ); -}; - -/** - * Visit declaration node. - */ - -Compiler.prototype.declaration = function ( node ) { - return ( - this.emit( node.property + ':' + node.value, node.position ) + - this.emit( ';' ) - ); -}; diff --git a/packages/block-editor/src/utils/transform-styles/ast/stringify/identity.js b/packages/block-editor/src/utils/transform-styles/ast/stringify/identity.js deleted file mode 100644 index 760ca4044631e..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/stringify/identity.js +++ /dev/null @@ -1,286 +0,0 @@ -/* eslint-disable @wordpress/no-unused-vars-before-return */ - -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -/** - * External dependencies - */ -import inherits from 'inherits'; - -/** - * Internal dependencies - */ -import Base from './compiler'; - -/** - * Expose compiler. - */ - -export default Compiler; - -/** - * Initialize a new `Compiler`. - */ - -function Compiler( options ) { - options = options || {}; - Base.call( this, options ); - this.indentation = options.indent; -} - -/** - * Inherit from `Base.prototype`. - */ - -inherits( Compiler, Base ); - -/** - * Compile `node`. - */ - -Compiler.prototype.compile = function ( node ) { - return this.stylesheet( node ); -}; - -/** - * Visit stylesheet node. - */ - -Compiler.prototype.stylesheet = function ( node ) { - return this.mapVisit( node.stylesheet.rules, '\n\n' ); -}; - -/** - * Visit comment node. - */ - -Compiler.prototype.comment = function ( node ) { - return this.emit( - this.indent() + '/*' + node.comment + '*/', - node.position - ); -}; - -/** - * Visit import node. - */ - -Compiler.prototype.import = function ( node ) { - return this.emit( '@import ' + node.import + ';', node.position ); -}; - -/** - * Visit media node. - */ - -Compiler.prototype.media = function ( node ) { - return ( - this.emit( '@media ' + node.media, node.position ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.rules, '\n\n' ) + - this.emit( this.indent( -1 ) + '\n}' ) - ); -}; - -/** - * Visit container node. - */ - -Compiler.prototype.container = function ( node ) { - return ( - this.emit( '@container ' + node.container, node.position ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.rules, '\n\n' ) + - this.emit( this.indent( -1 ) + '\n}' ) - ); -}; - -/** - * Visit document node. - */ - -Compiler.prototype.document = function ( node ) { - const doc = '@' + ( node.vendor || '' ) + 'document ' + node.document; - - return ( - this.emit( doc, node.position ) + - this.emit( ' ' + ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.rules, '\n\n' ) + - this.emit( this.indent( -1 ) + '\n}' ) - ); -}; - -/** - * Visit charset node. - */ - -Compiler.prototype.charset = function ( node ) { - return this.emit( '@charset ' + node.charset + ';', node.position ); -}; - -/** - * Visit namespace node. - */ - -Compiler.prototype.namespace = function ( node ) { - return this.emit( '@namespace ' + node.namespace + ';', node.position ); -}; - -/** - * Visit supports node. - */ - -Compiler.prototype.supports = function ( node ) { - return ( - this.emit( '@supports ' + node.supports, node.position ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.rules, '\n\n' ) + - this.emit( this.indent( -1 ) + '\n}' ) - ); -}; - -/** - * Visit keyframes node. - */ - -Compiler.prototype.keyframes = function ( node ) { - return ( - this.emit( - '@' + ( node.vendor || '' ) + 'keyframes ' + node.name, - node.position - ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.keyframes, '\n' ) + - this.emit( this.indent( -1 ) + '}' ) - ); -}; - -/** - * Visit keyframe node. - */ - -Compiler.prototype.keyframe = function ( node ) { - const decls = node.declarations; - - return ( - this.emit( this.indent() ) + - this.emit( node.values.join( ', ' ), node.position ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( decls, '\n' ) + - this.emit( this.indent( -1 ) + '\n' + this.indent() + '}\n' ) - ); -}; - -/** - * Visit page node. - */ - -Compiler.prototype.page = function ( node ) { - const sel = node.selectors.length ? node.selectors.join( ', ' ) + ' ' : ''; - - return ( - this.emit( '@page ' + sel, node.position ) + - this.emit( '{\n' ) + - this.emit( this.indent( 1 ) ) + - this.mapVisit( node.declarations, '\n' ) + - this.emit( this.indent( -1 ) ) + - this.emit( '\n}' ) - ); -}; - -/** - * Visit font-face node. - */ - -Compiler.prototype[ 'font-face' ] = function ( node ) { - return ( - this.emit( '@font-face ', node.position ) + - this.emit( '{\n' ) + - this.emit( this.indent( 1 ) ) + - this.mapVisit( node.declarations, '\n' ) + - this.emit( this.indent( -1 ) ) + - this.emit( '\n}' ) - ); -}; - -/** - * Visit host node. - */ - -Compiler.prototype.host = function ( node ) { - return ( - this.emit( '@host', node.position ) + - this.emit( ' {\n' + this.indent( 1 ) ) + - this.mapVisit( node.rules, '\n\n' ) + - this.emit( this.indent( -1 ) + '\n}' ) - ); -}; - -/** - * Visit custom-media node. - */ - -Compiler.prototype[ 'custom-media' ] = function ( node ) { - return this.emit( - '@custom-media ' + node.name + ' ' + node.media + ';', - node.position - ); -}; - -/** - * Visit rule node. - */ - -Compiler.prototype.rule = function ( node ) { - const indent = this.indent(); - const decls = node.declarations; - if ( ! decls.length ) { - return ''; - } - - return ( - this.emit( - node.selectors - .map( function ( s ) { - return indent + s; - } ) - .join( ',\n' ), - node.position - ) + - this.emit( ' {\n' ) + - this.emit( this.indent( 1 ) ) + - this.mapVisit( decls, '\n' ) + - this.emit( this.indent( -1 ) ) + - this.emit( '\n' + this.indent() + '}' ) - ); -}; - -/** - * Visit declaration node. - */ - -Compiler.prototype.declaration = function ( node ) { - return ( - this.emit( this.indent() ) + - this.emit( node.property + ': ' + node.value, node.position ) + - this.emit( ';' ) - ); -}; - -/** - * Increase, decrease or return current indentation. - */ - -Compiler.prototype.indent = function ( level ) { - this.level = this.level || 1; - - if ( null !== level ) { - this.level += level; - return ''; - } - - return Array( this.level ).join( this.indentation || ' ' ); -}; - -/* eslint-enable @wordpress/no-unused-vars-before-return */ diff --git a/packages/block-editor/src/utils/transform-styles/ast/stringify/index.js b/packages/block-editor/src/utils/transform-styles/ast/stringify/index.js deleted file mode 100644 index 2f332cdb52bec..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/ast/stringify/index.js +++ /dev/null @@ -1,32 +0,0 @@ -// Adapted from https://github.com/reworkcss/css -// because we needed to remove source map support. - -/** - * Internal dependencies - */ -import Compressed from './compress'; -import Identity from './identity'; - -/** - * Stringfy the given AST `node`. - * - * Options: - * - * - `compress` space-optimized output - * - `sourcemap` return an object with `.code` and `.map` - * - * @param {Object} node - * @param {Object} [options] - * @return {string} - */ - -export default function ( node, options ) { - options = options || {}; - - const compiler = options.compress - ? new Compressed( options ) - : new Identity( options ); - - const code = compiler.compile( node ); - return code; -} diff --git a/packages/block-editor/src/utils/transform-styles/test/__snapshots__/traverse.js.snap b/packages/block-editor/src/utils/transform-styles/test/__snapshots__/traverse.js.snap deleted file mode 100644 index 1ff3cab7d6336..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/test/__snapshots__/traverse.js.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CSS traverse Should traverse the CSS 1`] = ` -"namespace h1 { -color: red; -}" -`; diff --git a/packages/block-editor/src/utils/transform-styles/test/traverse.js b/packages/block-editor/src/utils/transform-styles/test/traverse.js deleted file mode 100644 index bb1be2635fe53..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/test/traverse.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Internal dependencies - */ -import traverse from '../traverse'; - -describe( 'CSS traverse', () => { - it( 'Should traverse the CSS', () => { - const input = `h1 { color: red; }`; - const output = traverse( input, ( node ) => { - if ( node.type === 'rule' ) { - return { - ...node, - selectors: node.selectors.map( - ( selector ) => 'namespace ' + selector - ), - }; - } - - return node; - } ); - - expect( output ).toMatchSnapshot(); - } ); -} ); diff --git a/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/url-rewrite.js.snap b/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/url-rewrite.js.snap deleted file mode 100644 index 48aaf43221e7d..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/url-rewrite.js.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`URL rewrite should not replace absolute paths 1`] = ` -"h1 { -background: url(/images/test.png); -}" -`; - -exports[`URL rewrite should not replace remote paths 1`] = ` -"h1 { -background: url(http://wp.org/images/test.png); -}" -`; - -exports[`URL rewrite should replace complex relative paths 1`] = ` -"h1 { -background: url(http://wp-site.local/themes/gut/images/test.png); -}" -`; - -exports[`URL rewrite should replace relative paths 1`] = ` -"h1 { -background: url(http://wp-site.local/themes/gut/css/images/test.png); -}" -`; diff --git a/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap b/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap deleted file mode 100644 index b9815cdc700b3..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap +++ /dev/null @@ -1,64 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CSS selector wrap should ignore font-face selectors 1`] = ` -"@font-face { -font-family: myFirstFont; -src: url(sansation_light.woff); -}" -`; - -exports[`CSS selector wrap should ignore keyframes 1`] = ` -"@keyframes edit-post__fade-in-animation { -from { -opacity: 0; -} -}" -`; - -exports[`CSS selector wrap should ignore selectors 1`] = ` -".my-namespace h1, -body { -color: red; -}" -`; - -exports[`CSS selector wrap should not double wrap selectors 1`] = ` -".my-namespace h1, -.my-namespace .red { -color: red; -}" -`; - -exports[`CSS selector wrap should replace :root selectors 1`] = ` -".my-namespace { ---my-color: #ff0000; -}" -`; - -exports[`CSS selector wrap should replace root tags 1`] = ` -".my-namespace, -.my-namespace h1 { -color: red; -}" -`; - -exports[`CSS selector wrap should wrap multiple selectors 1`] = ` -".my-namespace h1, -.my-namespace h2 { -color: red; -}" -`; - -exports[`CSS selector wrap should wrap regular selectors 1`] = ` -".my-namespace h1 { -color: red; -}" -`; - -exports[`CSS selector wrap should wrap selectors inside container queries 1`] = ` -"@container (width > 400px) { -.my-namespace h1 { -color: red; -} -}" -`; diff --git a/packages/block-editor/src/utils/transform-styles/transforms/test/url-rewrite.js b/packages/block-editor/src/utils/transform-styles/transforms/test/url-rewrite.js deleted file mode 100644 index abbbf0754187e..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/test/url-rewrite.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Internal dependencies - */ -import traverse from '../../traverse'; -import rewrite from '../url-rewrite'; - -describe( 'URL rewrite', () => { - it( 'should replace relative paths', () => { - const callback = rewrite( 'http://wp-site.local/themes/gut/css/' ); - const input = `h1 { background: url(images/test.png); }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should replace complex relative paths', () => { - const callback = rewrite( 'http://wp-site.local/themes/gut/css/' ); - const input = `h1 { background: url(../images/test.png); }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should not replace absolute paths', () => { - const callback = rewrite( 'http://wp-site.local/themes/gut/css/' ); - const input = `h1 { background: url(/images/test.png); }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should not replace remote paths', () => { - const callback = rewrite( 'http://wp-site.local/themes/gut/css/' ); - const input = `h1 { background: url(http://wp.org/images/test.png); }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); -} ); diff --git a/packages/block-editor/src/utils/transform-styles/transforms/test/wrap.js b/packages/block-editor/src/utils/transform-styles/transforms/test/wrap.js deleted file mode 100644 index a1f4f141d21c9..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/transforms/test/wrap.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Internal dependencies - */ -import traverse from '../../traverse'; -import wrap from '../wrap'; - -describe( 'CSS selector wrap', () => { - it( 'should wrap regular selectors', () => { - const callback = wrap( '.my-namespace' ); - const input = `h1 { color: red; }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should wrap multiple selectors', () => { - const callback = wrap( '.my-namespace' ); - const input = `h1, h2 { color: red; }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should ignore selectors', () => { - const callback = wrap( '.my-namespace', [ 'body' ] ); - const input = `h1, body { color: red; }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should replace root tags', () => { - const callback = wrap( '.my-namespace' ); - const input = `body, h1 { color: red; }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should ignore keyframes', () => { - const callback = wrap( '.my-namespace' ); - const input = ` - @keyframes edit-post__fade-in-animation { - from { - opacity: 0; - } - }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should wrap selectors inside container queries', () => { - const callback = wrap( '.my-namespace' ); - const input = ` - @container (width > 400px) { - h1 { color: red; } - }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should ignore font-face selectors', () => { - const callback = wrap( '.my-namespace' ); - const input = ` - @font-face { - font-family: myFirstFont; - src: url(sansation_light.woff); - }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should replace :root selectors', () => { - const callback = wrap( '.my-namespace' ); - const input = ` - :root { - --my-color: #ff0000; - }`; - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); - - it( 'should not double wrap selectors', () => { - const callback = wrap( '.my-namespace' ); - const input = ` .my-namespace h1, .red { color: red; }`; - - const output = traverse( input, callback ); - - expect( output ).toMatchSnapshot(); - } ); -} ); diff --git a/packages/block-editor/src/utils/transform-styles/traverse.js b/packages/block-editor/src/utils/transform-styles/traverse.js deleted file mode 100644 index 28ad59b4ea799..0000000000000 --- a/packages/block-editor/src/utils/transform-styles/traverse.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * External dependencies - */ -import traverse from 'traverse'; - -/** - * Internal dependencies - */ -import { parse, stringify } from './ast'; - -function traverseCSS( css, callback ) { - try { - const parsed = parse( css ); - - const updated = traverse.map( parsed, function ( node ) { - if ( ! node ) { - return node; - } - const updatedNode = callback( node ); - return this.update( updatedNode ); - } ); - - return stringify( updated ); - } catch ( err ) { - // eslint-disable-next-line no-console - console.warn( 'Error while traversing the CSS: ' + err ); - - return null; - } -} - -export default traverseCSS; From 5659fa14cc96a3c01811f3989b2b10a7a4128a25 Mon Sep 17 00:00:00 2001 From: strarsis Date: Mon, 14 Aug 2023 21:05:30 +0200 Subject: [PATCH 03/11] Use synchronous PostCSS API. --- packages/block-editor/src/utils/transform-styles/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index 7d8833db6ebe3..de331f0f7392c 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -17,7 +17,7 @@ const transformStyles = ( styles, wrapperClassName = '' ) => { return postcss( [ wrap( { scopeTo: wrapperClassName } ), rebaseUrl( { rootUrl: baseURL } ), - ] ).process( css, {} ); + ] ).process( css, {} ).css; // use sync PostCSS API } ); }; From 9b37cd8cb90cb67adfe215d7bb3f1858b423ada7 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Mon, 25 Sep 2023 23:02:53 -0300 Subject: [PATCH 04/11] Update package-lock.json --- package-lock.json | 163 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 147 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index ed33a0a19a48e..83475fd6b625c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45914,6 +45914,38 @@ "postcss": "^8.2.15" } }, + "node_modules/postcss-editor-styles": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/postcss-editor-styles/-/postcss-editor-styles-0.3.0.tgz", + "integrity": "sha512-sKtPEWt+ScRCYbfu36AfaMK3LVUvetfOy2pObRv+8/VVTbObybGlDFMYx7hyK9KAJTfL3v0+i2pRl6pSWyqXZA==", + "dependencies": { + "postcss": "^7.0.18" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-editor-styles/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-editor-styles/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -46441,6 +46473,22 @@ "postcss": "^8.2.15" } }, + "node_modules/postcss-urlrebase": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.3.0.tgz", + "integrity": "sha512-LOFN43n1IewKriXiypMNNinXeptttSyGGRLPbBMdQzuTvvCEo5mz/gG06y/HqrkN7p3ayHQf2R2bTBv639FOaQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.3.0" + } + }, + "node_modules/postcss-urlrebase/node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, "node_modules/postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", @@ -52850,11 +52898,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, - "node_modules/traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -56066,13 +56109,14 @@ "diff": "^4.0.2", "dom-scroll-into-view": "^1.2.1", "fast-deep-equal": "^3.1.3", - "inherits": "^2.0.3", "memize": "^2.1.0", + "postcss": "^8.4.21", + "postcss-editor-styles": "^0.3.0", + "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", "rememo": "^4.0.2", - "remove-accents": "^0.5.0", - "traverse": "^0.6.6" + "remove-accents": "^0.5.0" }, "engines": { "node": ">=12" @@ -56082,6 +56126,41 @@ "react-dom": "^18.0.0" } }, + "packages/block-editor/node_modules/postcss": { + "version": "8.4.30", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz", + "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "packages/block-editor/node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, "packages/block-library": { "name": "@wordpress/block-library", "version": "8.21.0", @@ -69479,13 +69558,31 @@ "diff": "^4.0.2", "dom-scroll-into-view": "^1.2.1", "fast-deep-equal": "^3.1.3", - "inherits": "^2.0.3", "memize": "^2.1.0", + "postcss": "^8.4.21", + "postcss-editor-styles": "^0.3.0", + "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", "rememo": "^4.0.2", - "remove-accents": "^0.5.0", - "traverse": "^0.6.6" + "remove-accents": "^0.5.0" + }, + "dependencies": { + "postcss": { + "version": "8.4.30", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz", + "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==", + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + } } }, "@wordpress/block-library": { @@ -95357,6 +95454,30 @@ "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", "dev": true }, + "postcss-editor-styles": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/postcss-editor-styles/-/postcss-editor-styles-0.3.0.tgz", + "integrity": "sha512-sKtPEWt+ScRCYbfu36AfaMK3LVUvetfOy2pObRv+8/VVTbObybGlDFMYx7hyK9KAJTfL3v0+i2pRl6pSWyqXZA==", + "requires": { + "postcss": "^7.0.18" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } + } + }, "postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -95748,6 +95869,21 @@ "postcss-selector-parser": "^6.0.5" } }, + "postcss-urlrebase": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.3.0.tgz", + "integrity": "sha512-LOFN43n1IewKriXiypMNNinXeptttSyGGRLPbBMdQzuTvvCEo5mz/gG06y/HqrkN7p3ayHQf2R2bTBv639FOaQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + } + } + }, "postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", @@ -100640,11 +100776,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, "tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", From 5819d8d595bf7f794d26a14e10c1510d4eb99510 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Mon, 25 Sep 2023 23:23:24 -0300 Subject: [PATCH 05/11] Add basic wrapping test --- .../src/utils/test/transform-styles.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/block-editor/src/utils/test/transform-styles.js diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js new file mode 100644 index 0000000000000..ed1ff895df932 --- /dev/null +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -0,0 +1,19 @@ +/** + * Internal dependencies + */ +import transformStyles from '../transform-styles'; + +it( 'should wrap selectors inside container queries', () => { + const input = ` + @container (width > 400px) { + h1 { color: red; } + }`; + const output = transformStyles( { input: { css: input } }, 'my-namespace' ); + + expect( output ).toEqual( [ + ` + @container (width > 400px) { + .my-namespace h1 { color: red; } + }`, + ] ); +} ); From 76c50fe2fae9d25005fd4479e3a32f8a394899b1 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Mon, 25 Sep 2023 23:26:34 -0300 Subject: [PATCH 06/11] Use correct postcss-prefixwrap package --- package-lock.json | 73 ++++--------------- packages/block-editor/package.json | 2 +- .../src/utils/transform-styles/index.js | 15 ++-- 3 files changed, 26 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83475fd6b625c..7603e03b936bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45914,38 +45914,6 @@ "postcss": "^8.2.15" } }, - "node_modules/postcss-editor-styles": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-editor-styles/-/postcss-editor-styles-0.3.0.tgz", - "integrity": "sha512-sKtPEWt+ScRCYbfu36AfaMK3LVUvetfOy2pObRv+8/VVTbObybGlDFMYx7hyK9KAJTfL3v0+i2pRl6pSWyqXZA==", - "dependencies": { - "postcss": "^7.0.18" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/postcss-editor-styles/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "node_modules/postcss-editor-styles/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -46364,6 +46332,14 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postcss-prefixwrap": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.41.0.tgz", + "integrity": "sha512-gmwwAEE+ci3/ZKjUZppTETINlh1QwihY8gCstInuS7ohk353KYItU4d64hvnUvO2GUy29hBGPHz4Ce+qJRi90A==", + "peerDependencies": { + "postcss": "*" + } + }, "node_modules/postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", @@ -56111,7 +56087,7 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-editor-styles": "^0.3.0", + "postcss-prefixwrap": "^1.41.0", "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", @@ -69560,7 +69536,7 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-editor-styles": "^0.3.0", + "postcss-prefixwrap": "^1.41.0", "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", @@ -95454,30 +95430,6 @@ "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", "dev": true }, - "postcss-editor-styles": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-editor-styles/-/postcss-editor-styles-0.3.0.tgz", - "integrity": "sha512-sKtPEWt+ScRCYbfu36AfaMK3LVUvetfOy2pObRv+8/VVTbObybGlDFMYx7hyK9KAJTfL3v0+i2pRl6pSWyqXZA==", - "requires": { - "postcss": "^7.0.18" - }, - "dependencies": { - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - } - } - }, "postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -95793,6 +95745,11 @@ } } }, + "postcss-prefixwrap": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/postcss-prefixwrap/-/postcss-prefixwrap-1.41.0.tgz", + "integrity": "sha512-gmwwAEE+ci3/ZKjUZppTETINlh1QwihY8gCstInuS7ohk353KYItU4d64hvnUvO2GUy29hBGPHz4Ce+qJRi90A==" + }, "postcss-reduce-initial": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 71c0ac5761039..5abf843b85f51 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -73,7 +73,7 @@ "fast-deep-equal": "^3.1.3", "memize": "^2.1.0", "postcss": "^8.4.21", - "postcss-editor-styles": "^0.3.0", + "postcss-prefixwrap": "^1.41.0", "postcss-urlrebase": "^1.0.0", "react-autosize-textarea": "^7.1.0", "react-easy-crop": "^4.5.1", diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index de331f0f7392c..82a453b83305f 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -2,7 +2,7 @@ * External dependencies */ import postcss from 'postcss'; -import wrap from 'postcss-editor-styles'; +import wrap from 'postcss-prefixwrap'; import rebaseUrl from 'postcss-urlrebase'; /** @@ -14,10 +14,15 @@ import rebaseUrl from 'postcss-urlrebase'; */ const transformStyles = ( styles, wrapperClassName = '' ) => { return Object.values( styles ?? [] ).map( ( { css, baseURL } ) => { - return postcss( [ - wrap( { scopeTo: wrapperClassName } ), - rebaseUrl( { rootUrl: baseURL } ), - ] ).process( css, {} ).css; // use sync PostCSS API + return postcss( + [ + wrapperClassName && + wrap( `.${ wrapperClassName }`, { + prefixRootTags: true, + } ), + rebaseUrl( { rootUrl: baseURL } ), + ].filter( Boolean ) + ).process( css, {} ).css; // use sync PostCSS API } ); }; From bdb95261fe7141beb734a7d002922fac5e212618 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Mon, 25 Sep 2023 23:42:24 -0300 Subject: [PATCH 07/11] Update test snapshots --- .../test/__snapshots__/build.js.snap | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index ae82311b07b28..254950316e496 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -31,11 +31,6 @@ exports[`DependencyExtractionWebpackPlugin Webpack \`combine-assets\` should pro ] `; -exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: Asset file 'assets.php' should match snapshot 1`] = ` -" array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'bf200ecb3dcb6881a1f3'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => '0af6c51a8e6ac934b85a')); -" -`; - exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array('wp-blob'), 'version' => '47f8a22aa6c04c930f5f'); " @@ -54,19 +49,6 @@ exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should pro ] `; -exports[`DependencyExtractionWebpackPlugin Webpack \`dynamic-import\` should produce expected output: External modules should match snapshot 2`] = ` -[ - { - "externalType": "window", - "request": [ - "wp", - "blob", - ], - "userRequest": "@wordpress/blob", - }, -] -`; - exports[`DependencyExtractionWebpackPlugin Webpack \`function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = ` " array('lodash', 'wp-blob'), 'version' => '35d057cb1c8a30094445'); " From 1366beb36c4df1a33f39d4d14a561ad92f75039d Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Tue, 17 Oct 2023 20:31:01 -0300 Subject: [PATCH 08/11] Add more tests and fix type signature --- packages/block-editor/README.md | 14 +- .../__snapshots__/transform-styles.js.snap | 94 ++++++++ .../src/utils/test/transform-styles.js | 208 ++++++++++++++++-- .../src/utils/transform-styles/index.js | 24 +- packages/block-library/src/html/preview.js | 2 +- 5 files changed, 318 insertions(+), 24 deletions(-) create mode 100644 packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 02671d5dca0e3..9c7a72f089714 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -789,13 +789,23 @@ Applies a series of CSS rule transforms to wrap selectors inside a given class a _Parameters_ -- _styles_ `Object|Array`: CSS rules. -- _wrapperClassName_ `string`: Wrapper Class Name. +- _styles_ `EditorStyle[]`: CSS rules. +- _wrapperSelector_ `string`: Wrapper selector. _Returns_ - `Array`: converted rules. +_Type Definition_ + +- _EditorStyle_ `Object` + +_Properties_ + +- _css_ `string`: the CSS block(s), as a single string. +- _baseURL_ `?string`: the base URL to be used as the reference when rewritting urls. +- _ignoredSelectors_ `?string[]`: the selectors not to wrap. + ### Typewriter Ensures that the text selection keeps the same vertical distance from the viewport during keyboard events within this component. The vertical distance can vary. It is the last clicked or scrolled to position. diff --git a/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap b/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap new file mode 100644 index 0000000000000..665912c7f326c --- /dev/null +++ b/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`transformStyles URL rewrite should not replace absolute paths 1`] = ` +[ + "h1 { background: url(/images/test.png); }", +] +`; + +exports[`transformStyles URL rewrite should not replace remote paths 1`] = ` +[ + "h1 { background: url(http://wp.org/images/test.png); }", +] +`; + +exports[`transformStyles URL rewrite should replace complex relative paths 1`] = ` +[ + "h1 { background: url(http://wp-site.local/themes/gut/images/test.png); }", +] +`; + +exports[`transformStyles URL rewrite should rewrite relative paths 1`] = ` +[ + "h1 { background: url(http://wp-site.local/themes/gut/css/images/test.png); }", +] +`; + +exports[`transformStyles selector wrap should ignore font-face selectors 1`] = ` +[ + " + @font-face { + font-family: myFirstFont; + src: url(sansation_light.woff); + }", +] +`; + +exports[`transformStyles selector wrap should ignore keyframes 1`] = ` +[ + " + @keyframes edit-post__fade-in-animation { + from { + opacity: 0; + } + }", +] +`; + +exports[`transformStyles selector wrap should ignore selectors 1`] = ` +[ + ".my-namespace h1, body { color: red; }", +] +`; + +exports[`transformStyles selector wrap should not double wrap selectors 1`] = ` +[ + " .my-namespace h1, .my-namespace .red { color: red; }", +] +`; + +exports[`transformStyles selector wrap should replace :root selectors 1`] = ` +[ + " + .my-namespace { + --my-color: #ff0000; + }", +] +`; + +exports[`transformStyles selector wrap should replace root tags 1`] = ` +[ + ".my-namespace, .my-namespace h1 { color: red; }", +] +`; + +exports[`transformStyles selector wrap should wrap multiple selectors 1`] = ` +[ + ".my-namespace h1, .my-namespace h2 { color: red; }", +] +`; + +exports[`transformStyles selector wrap should wrap regular selectors 1`] = ` +[ + ".my-namespace h1 { color: red; }", +] +`; + +exports[`transformStyles selector wrap should wrap selectors inside container queries 1`] = ` +[ + " + @container (width > 400px) { + .my-namespace h1 { color: red; } + }", +] +`; diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index ed1ff895df932..37ecfc6b98c31 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -3,17 +3,199 @@ */ import transformStyles from '../transform-styles'; -it( 'should wrap selectors inside container queries', () => { - const input = ` - @container (width > 400px) { - h1 { color: red; } - }`; - const output = transformStyles( { input: { css: input } }, 'my-namespace' ); - - expect( output ).toEqual( [ - ` - @container (width > 400px) { - .my-namespace h1 { color: red; } - }`, - ] ); +describe( 'transformStyles', () => { + describe( 'selector wrap', () => { + it( 'should wrap regular selectors', () => { + const input = `h1 { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should wrap multiple selectors', () => { + const input = `h1, h2 { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should ignore selectors', () => { + const input = `h1, body { color: red; }`; + const output = transformStyles( + [ + { + css: input, + ignoredSelectors: [ 'body' ], + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should replace root tags', () => { + const input = `body, h1 { color: red; }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should ignore keyframes', () => { + const input = ` + @keyframes edit-post__fade-in-animation { + from { + opacity: 0; + } + }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should wrap selectors inside container queries', () => { + const input = ` + @container (width > 400px) { + h1 { color: red; } + }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should ignore font-face selectors', () => { + const input = ` + @font-face { + font-family: myFirstFont; + src: url(sansation_light.woff); + }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should replace :root selectors', () => { + const input = ` + :root { + --my-color: #ff0000; + }`; + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should not double wrap selectors', () => { + const input = ` .my-namespace h1, .red { color: red; }`; + + const output = transformStyles( + [ + { + css: input, + }, + ], + '.my-namespace' + ); + + expect( output ).toMatchSnapshot(); + } ); + } ); + + describe( 'URL rewrite', () => { + it( 'should rewrite relative paths', () => { + const input = `h1 { background: url(images/test.png); }`; + const output = transformStyles( [ + { + css: input, + baseURL: 'http://wp-site.local/themes/gut/css/', + }, + ] ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should replace complex relative paths', () => { + const input = `h1 { background: url(../images/test.png); }`; + const output = transformStyles( [ + { + css: input, + baseURL: 'http://wp-site.local/themes/gut/css/', + }, + ] ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should not replace absolute paths', () => { + const input = `h1 { background: url(/images/test.png); }`; + const output = transformStyles( [ + { + css: input, + baseURL: 'http://wp-site.local/themes/gut/css/', + }, + ] ); + + expect( output ).toMatchSnapshot(); + } ); + + it( 'should not replace remote paths', () => { + const input = `h1 { background: url(http://wp.org/images/test.png); }`; + const output = transformStyles( [ + { + css: input, + baseURL: 'http://wp-site.local/themes/gut/css/', + }, + ] ); + + expect( output ).toMatchSnapshot(); + } ); + } ); } ); diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index 82a453b83305f..8f5e1702307a4 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -8,19 +8,27 @@ import rebaseUrl from 'postcss-urlrebase'; /** * Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. * - * @param {Object|Array} styles CSS rules. - * @param {string} wrapperClassName Wrapper Class Name. + * @typedef {Object} EditorStyle + * @property {string} css the CSS block(s), as a single string. + * @property {?string} baseURL the base URL to be used as the reference when rewritting urls. + * @property {?string[]} ignoredSelectors the selectors not to wrap. + * + * @param {EditorStyle[]} styles CSS rules. + * @param {string} wrapperSelector Wrapper selector. * @return {Array} converted rules. */ -const transformStyles = ( styles, wrapperClassName = '' ) => { - return Object.values( styles ?? [] ).map( ( { css, baseURL } ) => { +const transformStyles = ( styles, wrapperSelector = '' ) => { + return styles.map( ( { css, ignoredSelectors = [], baseURL } ) => { return postcss( [ - wrapperClassName && - wrap( `.${ wrapperClassName }`, { - prefixRootTags: true, + wrapperSelector && + wrap( wrapperSelector, { + ignoredSelectors: [ + ...ignoredSelectors, + wrapperSelector, + ], } ), - rebaseUrl( { rootUrl: baseURL } ), + baseURL && rebaseUrl( { rootUrl: baseURL } ), ].filter( Boolean ) ).process( css, {} ).css; // use sync PostCSS API } ); diff --git a/packages/block-library/src/html/preview.js b/packages/block-library/src/html/preview.js index 4d3fe5f41915a..47396c62165e8 100644 --- a/packages/block-library/src/html/preview.js +++ b/packages/block-library/src/html/preview.js @@ -23,7 +23,7 @@ const DEFAULT_STYLES = ` export default function HTMLEditPreview( { content, isSelected } ) { const settingStyles = useSelect( ( select ) => { - return select( blockEditorStore ).getSettings()?.styles; + return select( blockEditorStore ).getSettings()?.styles ?? []; }, [] ); const styles = useMemo( From 3446d420639bd79a94355abc8513c15dd1dc1020 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Tue, 17 Oct 2023 20:46:25 -0300 Subject: [PATCH 09/11] Ensure that data URLs do not break the CSS transformer --- .../test/__snapshots__/transform-styles.js.snap | 9 +++++++++ .../src/utils/test/transform-styles.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap b/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap index 665912c7f326c..28c4202f414a9 100644 --- a/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap +++ b/packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap @@ -92,3 +92,12 @@ exports[`transformStyles selector wrap should wrap selectors inside container qu }", ] `; + +exports[`transformStyles should not break with data urls 1`] = ` +[ + ".wp-block-group { + background-image: url("data:image/svg+xml,%3Csvg%3E.b%7Bclip-path:url(test);%7D%3C/svg%3E"); + color: red !important; + }", +] +`; diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index 37ecfc6b98c31..f162a0b2f6048 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -149,6 +149,22 @@ describe( 'transformStyles', () => { } ); } ); + it( 'should not break with data urls', () => { + const input = `.wp-block-group { + background-image: url("data:image/svg+xml,%3Csvg%3E.b%7Bclip-path:url(test);%7D%3C/svg%3E"); + color: red !important; + }`; + + const output = transformStyles( [ + { + css: input, + baseURL: 'http://wp-site.local/themes/gut/css/', + }, + ] ); + + expect( output ).toMatchSnapshot(); + } ); + describe( 'URL rewrite', () => { it( 'should rewrite relative paths', () => { const input = `h1 { background: url(images/test.png); }`; From 80dfffcbe165645d10f9a28aa63bd0d97191ff8f Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Thu, 19 Oct 2023 13:27:38 -0300 Subject: [PATCH 10/11] Do not optional chain something that is not optional --- packages/block-library/src/html/preview.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/html/preview.js b/packages/block-library/src/html/preview.js index 47396c62165e8..159c85115d817 100644 --- a/packages/block-library/src/html/preview.js +++ b/packages/block-library/src/html/preview.js @@ -22,9 +22,9 @@ const DEFAULT_STYLES = ` `; export default function HTMLEditPreview( { content, isSelected } ) { - const settingStyles = useSelect( ( select ) => { - return select( blockEditorStore ).getSettings()?.styles ?? []; - }, [] ); + const settingStyles = useSelect( + ( select ) => select( blockEditorStore ).getSettings().styles + ); const styles = useMemo( () => [ DEFAULT_STYLES, ...transformStyles( settingStyles ) ], From 05c3606a907442ab869868ca716da20dc47cf4f5 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini Date: Thu, 19 Oct 2023 13:28:04 -0300 Subject: [PATCH 11/11] Filter out non-CSS styles before passing the array to transformStyles --- packages/block-library/src/html/preview.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/html/preview.js b/packages/block-library/src/html/preview.js index 159c85115d817..d515c0119aa8d 100644 --- a/packages/block-library/src/html/preview.js +++ b/packages/block-library/src/html/preview.js @@ -27,7 +27,12 @@ export default function HTMLEditPreview( { content, isSelected } ) { ); const styles = useMemo( - () => [ DEFAULT_STYLES, ...transformStyles( settingStyles ) ], + () => [ + DEFAULT_STYLES, + ...transformStyles( + settingStyles.filter( ( style ) => style.css ) + ), + ], [ settingStyles ] );