From 81c223a51f11da5644c2c03a820722e655952f62 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 14 Jan 2022 12:01:45 +0100 Subject: [PATCH 01/12] Add initial version of the style engine --- docs/manifest.json | 6 + package-lock.json | 19 ++- package.json | 1 + packages/block-editor/package.json | 1 + packages/block-editor/src/hooks/style.js | 37 ++++-- packages/blocks/src/api/constants.js | 1 + .../lib/util.js | 6 +- packages/edit-site/package.json | 1 + .../global-styles/use-global-styles-output.js | 15 ++- packages/style-engine/.npmrc | 1 + packages/style-engine/CHANGELOG.md | 121 ++++++++++++++++++ packages/style-engine/README.md | 62 +++++++++ packages/style-engine/package.json | 37 ++++++ packages/style-engine/src/index.ts | 59 +++++++++ packages/style-engine/src/styles/index.ts | 6 + packages/style-engine/src/styles/padding.ts | 19 +++ packages/style-engine/src/styles/utils.ts | 44 +++++++ packages/style-engine/src/test/index.js | 32 +++++ packages/style-engine/src/types.ts | 32 +++++ packages/style-engine/tsconfig.json | 8 ++ tools/webpack/packages.js | 6 +- 21 files changed, 490 insertions(+), 24 deletions(-) create mode 100644 packages/style-engine/.npmrc create mode 100644 packages/style-engine/CHANGELOG.md create mode 100644 packages/style-engine/README.md create mode 100644 packages/style-engine/package.json create mode 100644 packages/style-engine/src/index.ts create mode 100644 packages/style-engine/src/styles/index.ts create mode 100644 packages/style-engine/src/styles/padding.ts create mode 100644 packages/style-engine/src/styles/utils.ts create mode 100644 packages/style-engine/src/test/index.js create mode 100644 packages/style-engine/src/types.ts create mode 100644 packages/style-engine/tsconfig.json diff --git a/docs/manifest.json b/docs/manifest.json index 3ab1908240867..c5deaa3b4b3f0 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1745,6 +1745,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 ca1c7e71efad5..ed513dbf7cfbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15744,6 +15744,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", @@ -16214,6 +16215,7 @@ "@wordpress/notices": "file:packages/notices", "@wordpress/plugins": "file:packages/plugins", "@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", @@ -16911,6 +16913,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, @@ -19241,16 +19250,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 ab2f863cc4530..6895168e5a3bc 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 c8d527323e527..ee27b0305da0a 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -53,6 +53,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 5882d5275937b..d15851f05b22c 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 674caea6af4c9..a237402e143f9 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 a22837af6a72e..87d67f8dbd68f 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 698f6234e0bae..23b01517c6f6b 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -50,6 +50,7 @@ "@wordpress/notices": "file:../notices", "@wordpress/plugins": "file:../plugins", "@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 b3ca7bd9ba016..a5af190334212 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 0000000000000..43c97e719a5a8 --- /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 0000000000000..330d83fcc8826 --- /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 0000000000000..1d410dd255379 --- /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. + + + +

Code is Poetry.

diff --git a/packages/style-engine/package.json b/packages/style-engine/package.json new file mode 100644 index 0000000000000..74512443ba912 --- /dev/null +++ b/packages/style-engine/package.json @@ -0,0 +1,37 @@ +{ + "name": "@wordpress/style-engine", + "version": "0.1.0", + "description": "WordPress Style engine.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "gutenberg", + "styles", + "global styles" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/style-engine/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/style-engine" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "engines": { + "node": ">=12" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "types": "build-types", + "sideEffects": false, + "dependencies": { + "@babel/runtime": "^7.16.0", + "lodash": "^4.17.21" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts new file mode 100644 index 0000000000000..2fad43edb7034 --- /dev/null +++ b/packages/style-engine/src/index.ts @@ -0,0 +1,59 @@ +/** + * External dependencies + */ +import { groupBy } from 'lodash'; + +/** + * Internal dependencies + */ +import type { Style, GeneratedCSSRule, StyleDefinition } from './types'; +import { styleDefinitions } from './styles'; + +/** + * Generates a stylesheet for a given style object and selector. + * + * @param style Style object. + * @param selector CSS selector. + * + * @return generated stylesheet. + */ +export function generate( style: Style, selector: string ): string { + const rules = getCSSRules( style, selector ); + const groupedRules = groupBy( rules, 'selector' ); + const selectorRules = Object.keys( groupedRules ).reduce( + ( acc: string[], subSelector: string ) => { + acc.push( + `${ subSelector } { ${ groupedRules[ subSelector ] + .map( + ( rule: GeneratedCSSRule ) => + `${ rule.key }: ${ rule.value };` + ) + .join( ' ' ) } }` + ); + return acc; + }, + [] + ); + + return selectorRules.join( '\n' ); +} + +/** + * Returns a JSON representation of the generated CSS rules. + * + * @param style Style object. + * @param selector CSS selector. + * + * @return generated styles. + */ +export function getCSSRules( + style: Style, + selector: string +): GeneratedCSSRule[] { + let rules: GeneratedCSSRule[] = []; + styleDefinitions.forEach( ( definition: StyleDefinition ) => { + rules = [ ...rules, ...definition.generate( style, selector ) ]; + } ); + + return rules; +} diff --git a/packages/style-engine/src/styles/index.ts b/packages/style-engine/src/styles/index.ts new file mode 100644 index 0000000000000..2f09e42817693 --- /dev/null +++ b/packages/style-engine/src/styles/index.ts @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import padding from './padding'; + +export const styleDefinitions = [ padding ]; diff --git a/packages/style-engine/src/styles/padding.ts b/packages/style-engine/src/styles/padding.ts new file mode 100644 index 0000000000000..8c8485edb479e --- /dev/null +++ b/packages/style-engine/src/styles/padding.ts @@ -0,0 +1,19 @@ +/** + * Internal dependencies + */ +import type { Style } from '../types'; +import { generateBoxRules } from './utils'; + +const padding = { + name: 'padding', + generate: ( style: Style, selector: string ) => { + return generateBoxRules( + style, + selector, + [ 'spacing', 'padding' ], + 'padding' + ); + }, +}; + +export default padding; diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts new file mode 100644 index 0000000000000..76efe97391a25 --- /dev/null +++ b/packages/style-engine/src/styles/utils.ts @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; + +/** + * Internal dependencies + */ +import type { GeneratedCSSRule, Style, Box } from '../types'; + +export function generateBoxRules( + style: Style, + selector: string, + path: string[], + ruleKey: string +): GeneratedCSSRule[] { + const boxStyle: Box | string | undefined = get( style, path ); + if ( ! boxStyle ) { + return []; + } + + const rules: GeneratedCSSRule[] = []; + if ( typeof boxStyle === 'string' ) { + rules.push( { selector, key: ruleKey, value: boxStyle } ); + } else { + const sideRules = [ 'top', 'bottom', 'left', 'right' ].reduce( + ( acc: GeneratedCSSRule[], side: string ) => { + const value: string | undefined = get( boxStyle, [ side ] ); + if ( value ) { + acc.push( { + selector, + key: `${ ruleKey }-${ side }`, + value, + } ); + } + return acc; + }, + [] + ); + rules.push( ...sideRules ); + } + + return rules; +} diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js new file mode 100644 index 0000000000000..8eaf997c26324 --- /dev/null +++ b/packages/style-engine/src/test/index.js @@ -0,0 +1,32 @@ +/** + * Internal dependencies + */ +import { generate } from '../index'; + +describe( 'generate', () => { + it( 'should generate empty style', () => { + expect( generate( {}, '.some-selector' ) ).toEqual( '' ); + } ); + + it( 'should generate padding styles', () => { + expect( + generate( + { + spacing: { padding: '10px' }, + }, + '.some-selector' + ) + ).toEqual( '.some-selector { padding: 10px; }' ); + + expect( + generate( + { + spacing: { padding: { top: '10px', bottom: '5px' } }, + }, + '.some-selector' + ) + ).toEqual( + '.some-selector { padding-top: 10px; padding-bottom: 5px; }' + ); + } ); +} ); diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts new file mode 100644 index 0000000000000..96dc5b41d036e --- /dev/null +++ b/packages/style-engine/src/types.ts @@ -0,0 +1,32 @@ +export type Box = { + top?: string; + bottom?: string; + left?: string; + right?: string; +}; + +export interface Style { + spacing?: { + padding?: string | Box; + margin?: string | Box; + lineHeight?: string; + fontSize?: string; + fontFamily?: string; + fontWeight?: string; + fontStyle?: string; + textDecoration?: string; + textTransform?: string; + letterSpacing?: string; + }; +} + +export type GeneratedCSSRule = { + selector: string; + value: string; + key: string; +}; + +export interface StyleDefinition { + name: string; + generate: ( style: Style, selector: string ) => GeneratedCSSRule[]; +} diff --git a/packages/style-engine/tsconfig.json b/packages/style-engine/tsconfig.json new file mode 100644 index 0000000000000..3c2c31f506f13 --- /dev/null +++ b/packages/style-engine/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 48902ee90406a..5aa5bcc74bb9d 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -19,7 +19,11 @@ const { dependencies } = require( '../../package' ); const { baseConfig, plugins, stylesTransform } = require( './shared' ); const WORDPRESS_NAMESPACE = '@wordpress/'; -const BUNDLED_PACKAGES = [ '@wordpress/icons', '@wordpress/interface' ]; +const BUNDLED_PACKAGES = [ + '@wordpress/icons', + '@wordpress/interface', + '@wordpress/style-engine', +]; const gutenbergPackages = Object.keys( dependencies ) .filter( From 60d6a28182a3bb5fccfadbd6e6277c7f56886811 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 24 Jan 2022 15:31:50 +1100 Subject: [PATCH 02/12] Update Style type to move typography attributes to their own object --- packages/style-engine/src/types.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 96dc5b41d036e..4eedae9f52c7b 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -7,16 +7,18 @@ export type Box = { export interface Style { spacing?: { - padding?: string | Box; margin?: string | Box; - lineHeight?: string; + padding?: string | Box; + }; + typography?: { fontSize?: string; fontFamily?: string; fontWeight?: string; fontStyle?: string; + letterSpacing?: string; + lineHeight?: string; textDecoration?: string; textTransform?: string; - letterSpacing?: string; }; } From a6d97b1da5b23374050534aaa397e2daa41f8340 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 24 Jan 2022 15:41:25 +1100 Subject: [PATCH 03/12] Update useEngine check --- packages/block-editor/src/hooks/style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index d15851f05b22c..3055555ec724e 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -86,7 +86,7 @@ export function getInlineStyles( styles = {} ) { // option and backwards compatibility for border radius support. const styleValue = get( styles, path ); - if ( ! styleValue.useEngine ) { + if ( ! STYLE_PROPERTY[ propKey ].useEngine ) { if ( !! subPaths && ! isString( styleValue ) ) { Object.entries( subPaths ).forEach( ( entry ) => { const [ name, subPath ] = entry; From a1746d218815a963db2d8bdbeee11b1af13f2c73 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 24 Jan 2022 15:51:34 +1100 Subject: [PATCH 04/12] Clear out changelog --- packages/style-engine/CHANGELOG.md | 116 +---------------------------- 1 file changed, 1 insertion(+), 115 deletions(-) diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index 330d83fcc8826..6367d4fc4b6ce 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,120 +2,6 @@ ## 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. +- Added initial version of the style engine ([#37978](https://github.com/WordPress/gutenberg/pull/37978)). From 9b2e35f861b4825935ac021bb169a5379977bb75 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 24 Jan 2022 17:28:31 +1100 Subject: [PATCH 05/12] Attempt to fix issue with package-lock.json and the check-local-changes step --- package-lock.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/package-lock.json b/package-lock.json index ed513dbf7cfbe..b7f3f03dcfbce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19250,6 +19250,16 @@ "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", From bc33ed20eac859b6e6fba9d1297dd79b9b169bb8 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 25 Jan 2022 16:40:45 +1100 Subject: [PATCH 06/12] Switch getCSSRules to use camelCase and generate to switch to kebabCase --- packages/style-engine/src/index.ts | 4 +- packages/style-engine/src/styles/utils.ts | 4 +- packages/style-engine/src/test/index.js | 45 ++++++++++++++++++++++- packages/style-engine/src/types.ts | 4 ++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts index 2fad43edb7034..dfc189bcb936c 100644 --- a/packages/style-engine/src/index.ts +++ b/packages/style-engine/src/index.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import { groupBy } from 'lodash'; +import { groupBy, kebabCase } from 'lodash'; /** * Internal dependencies @@ -26,7 +26,7 @@ export function generate( style: Style, selector: string ): string { `${ subSelector } { ${ groupedRules[ subSelector ] .map( ( rule: GeneratedCSSRule ) => - `${ rule.key }: ${ rule.value };` + `${ kebabCase( rule.key ) }: ${ rule.value };` ) .join( ' ' ) } }` ); diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index 76efe97391a25..a91c71c04b6f5 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import { get } from 'lodash'; +import { get, upperFirst } from 'lodash'; /** * Internal dependencies @@ -29,7 +29,7 @@ export function generateBoxRules( if ( value ) { acc.push( { selector, - key: `${ ruleKey }-${ side }`, + key: `${ ruleKey }${ upperFirst( side ) }`, value, } ); } diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js index 8eaf997c26324..50e03a234d0c2 100644 --- a/packages/style-engine/src/test/index.js +++ b/packages/style-engine/src/test/index.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { generate } from '../index'; +import { getCSSRules, generate } from '../index'; describe( 'generate', () => { it( 'should generate empty style', () => { @@ -30,3 +30,46 @@ describe( 'generate', () => { ); } ); } ); + +describe( 'getCSSRules', () => { + it( 'should return an empty rules array', () => { + expect( getCSSRules( {}, '.some-selector' ) ).toEqual( [] ); + } ); + + it( 'should return a rules array with CSS keys formatted in camelCase', () => { + expect( + getCSSRules( + { + spacing: { padding: '10px' }, + }, + '.some-selector' + ) + ).toEqual( [ + { + selector: '.some-selector', + key: 'padding', + value: '10px', + }, + ] ); + + expect( + getCSSRules( + { + spacing: { padding: { top: '10px', bottom: '5px' } }, + }, + '.some-selector' + ) + ).toEqual( [ + { + selector: '.some-selector', + key: 'paddingTop', + value: '10px', + }, + { + selector: '.some-selector', + key: 'paddingBottom', + value: '5px', + }, + ] ); + } ); +} ); diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 4eedae9f52c7b..80ec18a9d3cc0 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -25,6 +25,10 @@ export interface Style { export type GeneratedCSSRule = { selector: string; value: string; + /** + * The CSS key in JS style attribute format, compatible with React. + * E.g. `paddingTop` instead of `padding-top`. + */ key: string; }; From 55e18f689c95e6d4f1fe9c5406f0f987a2148a4e Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 25 Jan 2022 17:22:19 +1100 Subject: [PATCH 07/12] Skip useEngine styles in globalstyles reduce call, update output to use kebabCase --- .../components/global-styles/use-global-styles-output.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 a5af190334212..b756d3f90a102 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 @@ -149,9 +149,9 @@ function flattenTree( input = {}, prefix, token ) { function getStylesDeclarations( blockStyles = {} ) { const output = reduce( STYLE_PROPERTY, - ( declarations, { value, properties }, key ) => { + ( declarations, { value, properties, useEngine }, key ) => { const pathToValue = value; - if ( first( pathToValue ) === 'elements' ) { + if ( first( pathToValue ) === 'elements' || useEngine ) { return declarations; } @@ -197,7 +197,10 @@ function getStylesDeclarations( blockStyles = {} ) { if ( rule.selector !== 'self' ) { throw "This style can't be added as inline style"; } - return ( output[ rule.key ] = compileStyleValue( rule.value ) ); + const cssProperty = rule.key.startsWith( '--' ) + ? rule.key + : kebabCase( rule.key ); + output.push( `${ cssProperty }: ${ compileStyleValue( rule.value ) }` ); } ); return output; From 551884d41097d0f462e5e31abb814e2271134dbc Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 25 Jan 2022 17:35:19 +1100 Subject: [PATCH 08/12] Change order of box sides to match TRBL order of shorthand syntax and fix unit test --- packages/style-engine/src/styles/utils.ts | 2 +- packages/style-engine/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index a91c71c04b6f5..7f58a27cc147d 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -23,7 +23,7 @@ export function generateBoxRules( if ( typeof boxStyle === 'string' ) { rules.push( { selector, key: ruleKey, value: boxStyle } ); } else { - const sideRules = [ 'top', 'bottom', 'left', 'right' ].reduce( + const sideRules = [ 'top', 'right', 'bottom', 'left' ].reduce( ( acc: GeneratedCSSRule[], side: string ) => { const value: string | undefined = get( boxStyle, [ side ] ); if ( value ) { diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 80ec18a9d3cc0..e33ace6c9c80d 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -1,8 +1,8 @@ export type Box = { top?: string; + right?: string; bottom?: string; left?: string; - right?: string; }; export interface Style { From 0cffd1ea09cdd3d300e683254ed8829ab2af798f Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 31 Jan 2022 14:28:03 +1100 Subject: [PATCH 09/12] Add StyleOptions type and update function signature to include options object instead of selector string --- packages/block-editor/src/hooks/style.js | 2 +- .../global-styles/use-global-styles-output.js | 2 +- packages/style-engine/README.md | 4 ++-- packages/style-engine/src/index.ts | 23 +++++++++++-------- packages/style-engine/src/styles/padding.ts | 6 ++--- packages/style-engine/src/styles/utils.ts | 12 ++++++---- packages/style-engine/src/test/index.js | 16 +++++++++---- packages/style-engine/src/types.ts | 9 +++++++- 8 files changed, 49 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 3055555ec724e..8f2973957486e 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -107,7 +107,7 @@ export function getInlineStyles( styles = {} ) { // 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' ); + const extraRules = getCSSRules( styles, { selector: 'self' } ); extraRules.forEach( ( rule ) => { if ( rule.selector !== 'self' ) { throw "This style can't be added as inline style"; 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 b756d3f90a102..72ed5a5afe32e 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 @@ -192,7 +192,7 @@ 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' ); + const extraRules = getCSSRules( blockStyles, { selector: 'self' } ); extraRules.forEach( ( rule ) => { if ( rule.selector !== 'self' ) { throw "This style can't be added as inline style"; diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md index 1d410dd255379..612097cc49735 100644 --- a/packages/style-engine/README.md +++ b/packages/style-engine/README.md @@ -38,7 +38,7 @@ Generates a stylesheet for a given style object and selector. _Parameters_ - _style_ `Style`: Style object. -- _selector_ `string`: CSS selector. +- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated. _Returns_ @@ -51,7 +51,7 @@ Returns a JSON representation of the generated CSS rules. _Parameters_ - _style_ `Style`: Style object. -- _selector_ `string`: CSS selector. +- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated. _Returns_ diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts index dfc189bcb936c..532a1db985b34 100644 --- a/packages/style-engine/src/index.ts +++ b/packages/style-engine/src/index.ts @@ -6,19 +6,24 @@ import { groupBy, kebabCase } from 'lodash'; /** * Internal dependencies */ -import type { Style, GeneratedCSSRule, StyleDefinition } from './types'; +import type { + Style, + StyleOptions, + GeneratedCSSRule, + StyleDefinition, +} from './types'; import { styleDefinitions } from './styles'; /** * Generates a stylesheet for a given style object and selector. * - * @param style Style object. - * @param selector CSS selector. + * @param style Style object. + * @param options Options object with settings to adjust how the styles are generated. * * @return generated stylesheet. */ -export function generate( style: Style, selector: string ): string { - const rules = getCSSRules( style, selector ); +export function generate( style: Style, options: StyleOptions ): string { + const rules = getCSSRules( style, options ); const groupedRules = groupBy( rules, 'selector' ); const selectorRules = Object.keys( groupedRules ).reduce( ( acc: string[], subSelector: string ) => { @@ -41,18 +46,18 @@ export function generate( style: Style, selector: string ): string { /** * Returns a JSON representation of the generated CSS rules. * - * @param style Style object. - * @param selector CSS selector. + * @param style Style object. + * @param options Options object with settings to adjust how the styles are generated. * * @return generated styles. */ export function getCSSRules( style: Style, - selector: string + options: StyleOptions ): GeneratedCSSRule[] { let rules: GeneratedCSSRule[] = []; styleDefinitions.forEach( ( definition: StyleDefinition ) => { - rules = [ ...rules, ...definition.generate( style, selector ) ]; + rules = [ ...rules, ...definition.generate( style, options ) ]; } ); return rules; diff --git a/packages/style-engine/src/styles/padding.ts b/packages/style-engine/src/styles/padding.ts index 8c8485edb479e..94b268de35604 100644 --- a/packages/style-engine/src/styles/padding.ts +++ b/packages/style-engine/src/styles/padding.ts @@ -1,15 +1,15 @@ /** * Internal dependencies */ -import type { Style } from '../types'; +import type { Style, StyleOptions } from '../types'; import { generateBoxRules } from './utils'; const padding = { name: 'padding', - generate: ( style: Style, selector: string ) => { + generate: ( style: Style, options: StyleOptions ) => { return generateBoxRules( style, - selector, + options, [ 'spacing', 'padding' ], 'padding' ); diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index 7f58a27cc147d..5455901e49d1a 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -6,11 +6,11 @@ import { get, upperFirst } from 'lodash'; /** * Internal dependencies */ -import type { GeneratedCSSRule, Style, Box } from '../types'; +import type { GeneratedCSSRule, Style, Box, StyleOptions } from '../types'; export function generateBoxRules( style: Style, - selector: string, + options: StyleOptions, path: string[], ruleKey: string ): GeneratedCSSRule[] { @@ -21,14 +21,18 @@ export function generateBoxRules( const rules: GeneratedCSSRule[] = []; if ( typeof boxStyle === 'string' ) { - rules.push( { selector, key: ruleKey, value: boxStyle } ); + rules.push( { + selector: options.selector, + key: ruleKey, + value: boxStyle, + } ); } else { const sideRules = [ 'top', 'right', 'bottom', 'left' ].reduce( ( acc: GeneratedCSSRule[], side: string ) => { const value: string | undefined = get( boxStyle, [ side ] ); if ( value ) { acc.push( { - selector, + selector: options.selector, key: `${ ruleKey }${ upperFirst( side ) }`, value, } ); diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js index 50e03a234d0c2..14c0deb49b806 100644 --- a/packages/style-engine/src/test/index.js +++ b/packages/style-engine/src/test/index.js @@ -14,7 +14,9 @@ describe( 'generate', () => { { spacing: { padding: '10px' }, }, - '.some-selector' + { + selector: '.some-selector', + } ) ).toEqual( '.some-selector { padding: 10px; }' ); @@ -23,7 +25,9 @@ describe( 'generate', () => { { spacing: { padding: { top: '10px', bottom: '5px' } }, }, - '.some-selector' + { + selector: '.some-selector', + } ) ).toEqual( '.some-selector { padding-top: 10px; padding-bottom: 5px; }' @@ -42,7 +46,9 @@ describe( 'getCSSRules', () => { { spacing: { padding: '10px' }, }, - '.some-selector' + { + selector: '.some-selector', + } ) ).toEqual( [ { @@ -57,7 +63,9 @@ describe( 'getCSSRules', () => { { spacing: { padding: { top: '10px', bottom: '5px' } }, }, - '.some-selector' + { + selector: '.some-selector', + } ) ).toEqual( [ { diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index e33ace6c9c80d..f906942aa0847 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -22,6 +22,13 @@ export interface Style { }; } +export type StyleOptions = { + /** + * CSS selector for the generated style. + */ + selector: string; +}; + export type GeneratedCSSRule = { selector: string; value: string; @@ -34,5 +41,5 @@ export type GeneratedCSSRule = { export interface StyleDefinition { name: string; - generate: ( style: Style, selector: string ) => GeneratedCSSRule[]; + generate: ( style: Style, options: StyleOptions ) => GeneratedCSSRule[]; } From a59de6c029cec327afc5a3135ac0d975151faf5d Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 2 Feb 2022 16:40:08 +1100 Subject: [PATCH 10/12] Remove unnecessary return statement --- packages/block-editor/src/hooks/style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 8f2973957486e..c6f0ee91a2f2b 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -112,7 +112,7 @@ export function getInlineStyles( styles = {} ) { if ( rule.selector !== 'self' ) { throw "This style can't be added as inline style"; } - return ( output[ rule.key ] = rule.value ); + output[ rule.key ] = rule.value; } ); return output; From 91109e1a9c4231014f3a1368c39b5c61bcf9fffa Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 14 Feb 2022 12:22:13 +1100 Subject: [PATCH 11/12] Switch rules reassignment to rules.push --- packages/style-engine/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts index 532a1db985b34..8117e27892140 100644 --- a/packages/style-engine/src/index.ts +++ b/packages/style-engine/src/index.ts @@ -55,9 +55,9 @@ export function getCSSRules( style: Style, options: StyleOptions ): GeneratedCSSRule[] { - let rules: GeneratedCSSRule[] = []; + const rules: GeneratedCSSRule[] = []; styleDefinitions.forEach( ( definition: StyleDefinition ) => { - rules = [ ...rules, ...definition.generate( style, options ) ]; + rules.push( ...definition.generate( style, options ) ); } ); return rules; From f0cbeffdc5c0854fa48152e368f1fcfe92871156 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 14 Feb 2022 12:37:06 +1100 Subject: [PATCH 12/12] Update style object types to use CSSProperties --- packages/style-engine/src/types.ts | 33 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index f906942aa0847..4046324171360 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -1,24 +1,29 @@ +/** + * External dependencies + */ +import type { CSSProperties } from 'react'; + export type Box = { - top?: string; - right?: string; - bottom?: string; - left?: string; + top?: CSSProperties[ 'top' ]; + right?: CSSProperties[ 'right' ]; + bottom?: CSSProperties[ 'bottom' ]; + left?: CSSProperties[ 'left' ]; }; export interface Style { spacing?: { - margin?: string | Box; - padding?: string | Box; + margin?: CSSProperties[ 'margin' ] | Box; + padding?: CSSProperties[ 'padding' ] | Box; }; typography?: { - fontSize?: string; - fontFamily?: string; - fontWeight?: string; - fontStyle?: string; - letterSpacing?: string; - lineHeight?: string; - textDecoration?: string; - textTransform?: string; + fontSize?: CSSProperties[ 'fontSize' ]; + fontFamily?: CSSProperties[ 'fontFamily' ]; + fontWeight?: CSSProperties[ 'fontWeight' ]; + fontStyle?: CSSProperties[ 'fontStyle' ]; + letterSpacing?: CSSProperties[ 'letterSpacing' ]; + lineHeight?: CSSProperties[ 'lineHeight' ]; + textDecoration?: CSSProperties[ 'textDecoration' ]; + textTransform?: CSSProperties[ 'textTransform' ]; }; }