diff --git a/docs/manifest.json b/docs/manifest.json
index 027ae8e86e1429..52fbe608db945f 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -1757,6 +1757,12 @@
"markdown_source": "../packages/shortcode/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/style-engine",
+ "slug": "packages-style-engine",
+ "markdown_source": "../packages/style-engine/README.md",
+ "parent": "packages"
+ },
{
"title": "@wordpress/stylelint-config",
"slug": "packages-stylelint-config",
diff --git a/package-lock.json b/package-lock.json
index 39b1b228d5aba0..c0f224198751f0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15784,6 +15784,7 @@
"@wordpress/notices": "file:packages/notices",
"@wordpress/rich-text": "file:packages/rich-text",
"@wordpress/shortcode": "file:packages/shortcode",
+ "@wordpress/style-engine": "file:packages/style-engine",
"@wordpress/token-list": "file:packages/token-list",
"@wordpress/url": "file:packages/url",
"@wordpress/warning": "file:packages/warning",
@@ -16269,6 +16270,7 @@
"@wordpress/plugins": "file:packages/plugins",
"@wordpress/primitives": "file:packages/primitives",
"@wordpress/reusable-blocks": "file:packages/reusable-blocks",
+ "@wordpress/style-engine": "file:packages/style-engine",
"@wordpress/url": "file:packages/url",
"@wordpress/viewport": "file:packages/viewport",
"classnames": "^2.3.1",
@@ -16982,6 +16984,13 @@
"memize": "^1.1.0"
}
},
+ "@wordpress/style-engine": {
+ "version": "file:packages/style-engine",
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "lodash": "^4.17.21"
+ }
+ },
"@wordpress/stylelint-config": {
"version": "file:packages/stylelint-config",
"dev": true,
@@ -19313,16 +19322,6 @@
"yauzl": "^2.7.0"
},
"dependencies": {
- "are-we-there-yet": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
- "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
- "dev": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- }
- },
"gauge": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.1.tgz",
diff --git a/package.json b/package.json
index 336abb58389e59..3ae95708706044 100755
--- a/package.json
+++ b/package.json
@@ -76,6 +76,7 @@
"@wordpress/rich-text": "file:packages/rich-text",
"@wordpress/server-side-render": "file:packages/server-side-render",
"@wordpress/shortcode": "file:packages/shortcode",
+ "@wordpress/style-engine": "file:packages/style-engine",
"@wordpress/token-list": "file:packages/token-list",
"@wordpress/url": "file:packages/url",
"@wordpress/viewport": "file:packages/viewport",
diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json
index 1609b7eca695e9..4ceaab8c2fdf56 100644
--- a/packages/block-editor/package.json
+++ b/packages/block-editor/package.json
@@ -54,6 +54,7 @@
"@wordpress/notices": "file:../notices",
"@wordpress/rich-text": "file:../rich-text",
"@wordpress/shortcode": "file:../shortcode",
+ "@wordpress/style-engine": "file:../style-engine",
"@wordpress/token-list": "file:../token-list",
"@wordpress/url": "file:../url",
"@wordpress/warning": "file:../warning",
diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js
index 5882d5275937be..d15851f05b22cd 100644
--- a/packages/block-editor/src/hooks/style.js
+++ b/packages/block-editor/src/hooks/style.js
@@ -27,6 +27,7 @@ import {
__EXPERIMENTAL_ELEMENTS as ELEMENTS,
} from '@wordpress/blocks';
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
+import { getCSSRules } from '@wordpress/style-engine';
/**
* Internal dependencies
@@ -85,21 +86,35 @@ export function getInlineStyles( styles = {} ) {
// option and backwards compatibility for border radius support.
const styleValue = get( styles, path );
- if ( !! subPaths && ! isString( styleValue ) ) {
- Object.entries( subPaths ).forEach( ( entry ) => {
- const [ name, subPath ] = entry;
- const value = get( styleValue, [ subPath ] );
-
- if ( value ) {
- output[ name ] = compileStyleValue( value );
- }
- } );
- } else if ( ! ignoredStyles.includes( path.join( '.' ) ) ) {
- output[ propKey ] = compileStyleValue( get( styles, path ) );
+ if ( ! styleValue.useEngine ) {
+ if ( !! subPaths && ! isString( styleValue ) ) {
+ Object.entries( subPaths ).forEach( ( entry ) => {
+ const [ name, subPath ] = entry;
+ const value = get( styleValue, [ subPath ] );
+
+ if ( value ) {
+ output[ name ] = compileStyleValue( value );
+ }
+ } );
+ } else if ( ! ignoredStyles.includes( path.join( '.' ) ) ) {
+ output[ propKey ] = compileStyleValue(
+ get( styles, path )
+ );
+ }
}
}
} );
+ // The goal is to move everything to server side generated engine styles
+ // This is temporary as we absorb more and more styles into the engine.
+ const extraRules = getCSSRules( styles, 'self' );
+ extraRules.forEach( ( rule ) => {
+ if ( rule.selector !== 'self' ) {
+ throw "This style can't be added as inline style";
+ }
+ return ( output[ rule.key ] = rule.value );
+ } );
+
return output;
}
diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js
index 674caea6af4c99..a237402e143f9d 100644
--- a/packages/blocks/src/api/constants.js
+++ b/packages/blocks/src/api/constants.js
@@ -99,6 +99,7 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
paddingBottom: 'bottom',
paddingLeft: 'left',
},
+ useEngine: true,
},
textDecoration: {
value: [ 'typography', 'textDecoration' ],
diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js
index a22837af6a72e9..87d67f8dbd68fd 100644
--- a/packages/dependency-extraction-webpack-plugin/lib/util.js
+++ b/packages/dependency-extraction-webpack-plugin/lib/util.js
@@ -1,5 +1,9 @@
const WORDPRESS_NAMESPACE = '@wordpress/';
-const BUNDLED_PACKAGES = [ '@wordpress/icons', '@wordpress/interface' ];
+const BUNDLED_PACKAGES = [
+ '@wordpress/icons',
+ '@wordpress/interface',
+ '@wordpress/style-engine',
+];
/**
* Default request to global transformation
diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json
index 325f86ff5a1011..0c8e2d00a20fb2 100644
--- a/packages/edit-site/package.json
+++ b/packages/edit-site/package.json
@@ -51,6 +51,7 @@
"@wordpress/plugins": "file:../plugins",
"@wordpress/primitives": "file:../primitives",
"@wordpress/reusable-blocks": "file:../reusable-blocks",
+ "@wordpress/style-engine": "file:../style-engine",
"@wordpress/url": "file:../url",
"@wordpress/viewport": "file:../viewport",
"classnames": "^2.3.1",
diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
index b3ca7bd9ba0167..a5af190334212b 100644
--- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js
+++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
@@ -23,6 +23,7 @@ import {
getBlockTypes,
} from '@wordpress/blocks';
import { useEffect, useState, useContext } from '@wordpress/element';
+import { getCSSRules } from '@wordpress/style-engine';
/**
* Internal dependencies
@@ -146,7 +147,7 @@ function flattenTree( input = {}, prefix, token ) {
* @return {Array} An array of style declarations.
*/
function getStylesDeclarations( blockStyles = {} ) {
- return reduce(
+ const output = reduce(
STYLE_PROPERTY,
( declarations, { value, properties }, key ) => {
const pathToValue = value;
@@ -188,6 +189,18 @@ function getStylesDeclarations( blockStyles = {} ) {
},
[]
);
+
+ // The goal is to move everything to server side generated engine styles
+ // This is temporary as we absorb more and more styles into the engine.
+ const extraRules = getCSSRules( blockStyles, 'self' );
+ extraRules.forEach( ( rule ) => {
+ if ( rule.selector !== 'self' ) {
+ throw "This style can't be added as inline style";
+ }
+ return ( output[ rule.key ] = compileStyleValue( rule.value ) );
+ } );
+
+ return output;
}
export const getNodesWithStyles = ( tree, blockSelectors ) => {
diff --git a/packages/style-engine/.npmrc b/packages/style-engine/.npmrc
new file mode 100644
index 00000000000000..43c97e719a5a82
--- /dev/null
+++ b/packages/style-engine/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md
new file mode 100644
index 00000000000000..330d83fcc88269
--- /dev/null
+++ b/packages/style-engine/CHANGELOG.md
@@ -0,0 +1,121 @@
+
+
+## Unreleased
+
+## 3.3.0 (2021-11-07)
+
+### New Feature
+
+- Added new `normalizePath` function ([#35992](https://github.com/WordPress/gutenberg/pull/35992)).
+
+## 3.2.3 (2021-10-12)
+
+### Bug Fix
+
+- Removed unused `react-native-url-polyfill` dependency ([#34687](https://github.com/WordPress/gutenberg/pull/34687)).
+
+## 3.2.0 (2021-07-21)
+
+## 3.1.0 (2021-05-20)
+
+## 3.0.0 (2021-05-14)
+
+### Breaking Changes
+
+- Drop support for Internet Explorer 11 ([#31110](https://github.com/WordPress/gutenberg/pull/31110)). Learn more at https://make.wordpress.org/core/2021/04/22/ie-11-support-phase-out-plan/.
+- Increase the minimum Node.js version to v12 matching Long Term Support releases ([#31270](https://github.com/WordPress/gutenberg/pull/31270)). Learn more at https://nodejs.org/en/about/releases/.
+
+## 2.22.0 (2021-03-17)
+
+## 2.21.0 (2021-01-05)
+
+### New Feature
+
+- Add optional argument `maxLength` for truncating URL in `filterURLForDisplay`
+
+## 2.16.0 (2020-06-15)
+
+### New Feature
+
+- Added `getPathAndQueryString`.
+
+## 2.14.0 (2020-04-30)
+
+### Bug fix
+
+- `addQueryArgs` arguments are optional ([#21926](https://github.com/WordPress/gutenberg/pull/21926))
+
+## 2.13.0 (2020-04-15)
+
+### New feature
+
+- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942))
+
+# 2.12.0 (2020-04-01)
+
+### Bug Fixes
+
+- `getQueryString` now correctly considers hash fragments when considering whether to return a query string. Previously, `getQueryString( 'https://example.com/#?foo' )` would wrongly return `'foo'` as its result. A hash fragment is always the last segment of a URL, and the querystring must always precede it ([see reference specification](https://url.spec.whatwg.org/#absolute-url-with-fragment-string)).
+
+## 2.11.0 (2020-02-10)
+
+### Bug Fixes
+
+- `isURL` now correctly returns `true` for many other forms of a valid URL, as it now conforms to the [URL Living Standard](https://url.spec.whatwg.org/) definition of a [valid URL string](https://url.spec.whatwg.org/#valid-url-string).
+
+## 2.3.3 (2019-01-03)
+
+### Bug Fixes
+
+- `addQueryArgs` will return only the querystring fragment if the passed `url` is undefined. Previously, an uncaught error would be thrown.
+- `addQueryArgs` will not append (or remove) a `?` if there are no query arguments to be added. Previously, `?` would be wrongly appended even if there was no querystring generated.
+
+## 2.3.2 (2018-12-12)
+
+## 2.3.1 (2018-11-20)
+
+### Bug fixes
+
+- The `isValidProtocol` function now correctly considers the protocol of the URL as only incoporating characters up to and including the colon (':').
+- `getFragment` is now greedier and matches fragments from the first occurence of the '#' symbol instead of the last.
+
+## 2.3.0 (2018-11-12)
+
+### New Features
+
+- Added `getProtocol`.
+- Added `isValidProtocol`.
+- Added `getAuthority`
+- Added `isValidAuthority`.
+- Added `getPath`.
+- Added `isValidPath`.
+- Added `getQueryString`.
+- Added `isValidQueryString`.
+- Added `getFragment`.
+- Added `isValidFragment`.
+
+## 2.2.0 (2018-10-29)
+
+### New Features
+
+- Added `getQueryArg`.
+- Added `hasQueryArg`.
+- Added `removeQueryArgs`.
+
+## 2.1.0 (2018-10-16)
+
+### New Feature
+
+- Added `safeDecodeURI`.
+
+## 2.0.1 (2018-09-30)
+
+### Bug Fix
+
+- Fix typo in the `qs` dependency definition in the `package.json`
+
+## 2.0.0 (2018-09-05)
+
+### Breaking Change
+
+- Change how required built-ins are polyfilled with Babel 7 ([#9171](https://github.com/WordPress/gutenberg/pull/9171)). If you're using an environment that has limited or no support for ES2015+ such as lower versions of IE then using [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](https://babeljs.io/docs/en/next/babel-polyfill) will add support for these methods.
diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md
new file mode 100644
index 00000000000000..1d410dd2553799
--- /dev/null
+++ b/packages/style-engine/README.md
@@ -0,0 +1,62 @@
+# Style Engine
+
+The Style Engine powering global styles and block customizations.
+
+## Installation
+
+Install the module
+
+```bash
+npm install @wordpress/style-engine --save
+```
+
+_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
+
+## Important
+
+This Package is considered experimental at the moment. The idea is to have a package used to generate styles based on a style object that is consistent between: backend, frontend, block style object and theme.json.
+
+Currently it's not a package that generates a wp.styleEngine global because it's not ready yet, it's still a bundled package but ultimately, we want it to be so, once the roadmap is finished:
+
+**TODO List:**
+
+- Add style definitions for all the currently supported styles in blocks and theme.json.
+- the CSS variable shortcuts for values (for presets...)
+- Support generating styles in the frontend.
+- Support generating styles in the backend (block supports and theme.json stylesheet).
+- Refactor all block styles to use the style engine server side.
+- Refactor all blocks to consistently use the "style" attribute for all customizations (get rid of the preset specific attributes).
+
+## Usage
+
+
+
+### generate
+
+Generates a stylesheet for a given style object and selector.
+
+_Parameters_
+
+- _style_ `Style`: Style object.
+- _selector_ `string`: CSS selector.
+
+_Returns_
+
+- `string`: generated stylesheet.
+
+### getCSSRules
+
+Returns a JSON representation of the generated CSS rules.
+
+_Parameters_
+
+- _style_ `Style`: Style object.
+- _selector_ `string`: CSS selector.
+
+_Returns_
+
+- `GeneratedCSSRule[]`: generated styles.
+
+
+
+