@wordpress/style-engine 0.5.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/index.js +13 -2
  3. package/build/index.js.map +1 -1
  4. package/build/styles/color/background.js +21 -0
  5. package/build/styles/color/background.js.map +1 -0
  6. package/build/styles/color/gradient.js +21 -0
  7. package/build/styles/color/gradient.js.map +1 -0
  8. package/build/styles/color/index.js +21 -0
  9. package/build/styles/color/index.js.map +1 -0
  10. package/build/styles/color/text.js +21 -0
  11. package/build/styles/color/text.js.map +1 -0
  12. package/build/styles/constants.js +13 -0
  13. package/build/styles/constants.js.map +1 -0
  14. package/build/styles/index.js +5 -3
  15. package/build/styles/index.js.map +1 -1
  16. package/build/styles/spacing/index.js +19 -0
  17. package/build/styles/spacing/index.js.map +1 -0
  18. package/build/styles/{margin.js → spacing/margin.js} +1 -1
  19. package/build/styles/spacing/margin.js.map +1 -0
  20. package/build/styles/{padding.js → spacing/padding.js} +1 -1
  21. package/build/styles/spacing/padding.js.map +1 -0
  22. package/build/styles/typography/index.js +57 -0
  23. package/build/styles/typography/index.js.map +1 -0
  24. package/build/styles/utils.js +54 -2
  25. package/build/styles/utils.js.map +1 -1
  26. package/build-module/index.js +13 -2
  27. package/build-module/index.js.map +1 -1
  28. package/build-module/styles/color/background.js +12 -0
  29. package/build-module/styles/color/background.js.map +1 -0
  30. package/build-module/styles/color/gradient.js +12 -0
  31. package/build-module/styles/color/gradient.js.map +1 -0
  32. package/build-module/styles/color/index.js +8 -0
  33. package/build-module/styles/color/index.js.map +1 -0
  34. package/build-module/styles/color/text.js +12 -0
  35. package/build-module/styles/color/text.js.map +1 -0
  36. package/build-module/styles/constants.js +4 -0
  37. package/build-module/styles/constants.js.map +1 -0
  38. package/build-module/styles/index.js +4 -3
  39. package/build-module/styles/index.js.map +1 -1
  40. package/build-module/styles/spacing/index.js +7 -0
  41. package/build-module/styles/spacing/index.js.map +1 -0
  42. package/build-module/styles/{margin.js → spacing/margin.js} +1 -1
  43. package/build-module/styles/spacing/margin.js.map +1 -0
  44. package/build-module/styles/{padding.js → spacing/padding.js} +1 -1
  45. package/build-module/styles/spacing/padding.js.map +1 -0
  46. package/build-module/styles/typography/index.js +48 -0
  47. package/build-module/styles/typography/index.js.map +1 -0
  48. package/build-module/styles/utils.js +49 -2
  49. package/build-module/styles/utils.js.map +1 -1
  50. package/build-types/index.d.ts.map +1 -1
  51. package/build-types/styles/color/background.d.ts +14 -0
  52. package/build-types/styles/color/background.d.ts.map +1 -0
  53. package/build-types/styles/color/gradient.d.ts +14 -0
  54. package/build-types/styles/color/gradient.d.ts.map +1 -0
  55. package/build-types/styles/color/index.d.ts +10 -0
  56. package/build-types/styles/color/index.d.ts.map +1 -0
  57. package/build-types/styles/color/text.d.ts +14 -0
  58. package/build-types/styles/color/text.d.ts.map +1 -0
  59. package/build-types/styles/constants.d.ts +4 -0
  60. package/build-types/styles/constants.d.ts.map +1 -0
  61. package/build-types/styles/index.d.ts +5 -1
  62. package/build-types/styles/index.d.ts.map +1 -1
  63. package/build-types/styles/spacing/index.d.ts +6 -0
  64. package/build-types/styles/spacing/index.d.ts.map +1 -0
  65. package/build-types/styles/{margin.d.ts → spacing/margin.d.ts} +2 -2
  66. package/build-types/styles/spacing/margin.d.ts.map +1 -0
  67. package/build-types/styles/{padding.d.ts → spacing/padding.d.ts} +2 -2
  68. package/build-types/styles/spacing/padding.d.ts.map +1 -0
  69. package/build-types/styles/typography/index.d.ts +14 -0
  70. package/build-types/styles/typography/index.d.ts.map +1 -0
  71. package/build-types/styles/utils.d.ts +33 -0
  72. package/build-types/styles/utils.d.ts.map +1 -1
  73. package/build-types/types.d.ts +14 -1
  74. package/build-types/types.d.ts.map +1 -1
  75. package/class-wp-style-engine.php +189 -61
  76. package/package.json +2 -2
  77. package/phpunit/class-wp-style-engine-test.php +86 -67
  78. package/src/index.ts +13 -1
  79. package/src/styles/color/background.ts +19 -0
  80. package/src/styles/color/gradient.ts +19 -0
  81. package/src/styles/color/index.ts +8 -0
  82. package/src/styles/color/text.ts +14 -0
  83. package/src/styles/constants.ts +3 -0
  84. package/src/styles/index.ts +4 -3
  85. package/src/styles/spacing/index.ts +7 -0
  86. package/src/styles/{margin.ts → spacing/margin.ts} +2 -2
  87. package/src/styles/{padding.ts → spacing/padding.ts} +2 -2
  88. package/src/styles/typography/index.ts +99 -0
  89. package/src/styles/utils.ts +67 -2
  90. package/src/test/index.js +101 -2
  91. package/src/types.ts +14 -1
  92. package/tsconfig.tsbuildinfo +1 -1
  93. package/build/styles/margin.js.map +0 -1
  94. package/build/styles/padding.js.map +0 -1
  95. package/build-module/styles/margin.js.map +0 -1
  96. package/build-module/styles/padding.js.map +0 -1
  97. package/build-types/styles/margin.d.ts.map +0 -1
  98. package/build-types/styles/padding.d.ts.map +0 -1
@@ -16,6 +16,11 @@ if ( class_exists( 'WP_Style_Engine' ) ) {
16
16
  *
17
17
  * Consolidates rendering block styles to reduce duplication and streamline
18
18
  * CSS styles generation.
19
+ *
20
+ * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
21
+ * This is a low-level API that may need to do breaking changes. Please, use gutenberg_style_engine_get_styles instead.
22
+ *
23
+ * @access private
19
24
  */
20
25
  class WP_Style_Engine {
21
26
  /**
@@ -29,23 +34,87 @@ class WP_Style_Engine {
29
34
  * Style definitions that contain the instructions to
30
35
  * parse/output valid Gutenberg styles from a block's attributes.
31
36
  * For every style definition, the follow properties are valid:
32
- *
37
+ * - classnames => an array of classnames to be returned for block styles. The key is a classname or pattern.
38
+ * A value of `true` means the classname should be applied always. Otherwise a valid CSS property
39
+ * to match the incoming value, e.g., "color" to match var:preset|color|somePresetName.
33
40
  * - property_key => the key that represents a valid CSS property, e.g., "margin" or "border".
34
41
  * - path => a path that accesses the corresponding style value in the block style object.
35
- * - value_func => a function to generate an array of valid CSS rules for a particular style object.
36
- * For example, `'padding' => 'array( 'top' => '1em' )` will return `array( 'padding-top' => '1em' )`
37
42
  */
38
43
  const BLOCK_STYLE_DEFINITIONS_METADATA = array(
39
- 'spacing' => array(
44
+ 'color' => array(
45
+ 'text' => array(
46
+ 'property_key' => 'color',
47
+ 'path' => array( 'color', 'text' ),
48
+ 'classnames' => array(
49
+ 'has-text-color' => true,
50
+ 'has-%s-color' => 'color',
51
+ ),
52
+ ),
53
+ 'background' => array(
54
+ 'property_key' => 'background-color',
55
+ 'path' => array( 'color', 'background' ),
56
+ 'classnames' => array(
57
+ 'has-background' => true,
58
+ 'has-%s-background-color' => 'color',
59
+ ),
60
+ ),
61
+ 'gradient' => array(
62
+ 'property_key' => 'background',
63
+ 'path' => array( 'color', 'gradient' ),
64
+ 'classnames' => array(
65
+ 'has-background' => true,
66
+ 'has-%s-gradient-background' => 'gradient',
67
+ ),
68
+ ),
69
+ ),
70
+ 'spacing' => array(
40
71
  'padding' => array(
41
72
  'property_key' => 'padding',
42
73
  'path' => array( 'spacing', 'padding' ),
43
- 'value_func' => 'static::get_css_box_rules',
44
74
  ),
45
75
  'margin' => array(
46
76
  'property_key' => 'margin',
47
77
  'path' => array( 'spacing', 'margin' ),
48
- 'value_func' => 'static::get_css_box_rules',
78
+ ),
79
+ ),
80
+ 'typography' => array(
81
+ 'fontSize' => array(
82
+ 'property_key' => 'font-size',
83
+ 'path' => array( 'typography', 'fontSize' ),
84
+ 'classnames' => array(
85
+ 'has-%s-font-size' => 'font-size',
86
+ ),
87
+ ),
88
+ 'fontFamily' => array(
89
+ 'property_key' => 'font-family',
90
+ 'path' => array( 'typography', 'fontFamily' ),
91
+ 'classnames' => array(
92
+ 'has-%s-font-family' => 'font-family',
93
+ ),
94
+ ),
95
+ 'fontStyle' => array(
96
+ 'property_key' => 'font-style',
97
+ 'path' => array( 'typography', 'fontStyle' ),
98
+ ),
99
+ 'fontWeight' => array(
100
+ 'property_key' => 'font-weight',
101
+ 'path' => array( 'typography', 'fontWeight' ),
102
+ ),
103
+ 'lineHeight' => array(
104
+ 'property_key' => 'line-height',
105
+ 'path' => array( 'typography', 'lineHeight' ),
106
+ ),
107
+ 'textDecoration' => array(
108
+ 'property_key' => 'text-decoration',
109
+ 'path' => array( 'typography', 'textDecoration' ),
110
+ ),
111
+ 'textTransform' => array(
112
+ 'property_key' => 'text-transform',
113
+ 'path' => array( 'typography', 'textTransform' ),
114
+ ),
115
+ 'letterSpacing' => array(
116
+ 'property_key' => 'letter-spacing',
117
+ 'path' => array( 'typography', 'letterSpacing' ),
49
118
  ),
50
119
  ),
51
120
  );
@@ -66,26 +135,68 @@ class WP_Style_Engine {
66
135
  }
67
136
 
68
137
  /**
69
- * Returns a CSS ruleset based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA.
138
+ * Extracts the slug in kebab case from a preset string, e.g., "heavenly-blue" from 'var:preset|color|heavenlyBlue'.
139
+ *
140
+ * @param string $style_value A single css preset value.
141
+ * @param string $property_key The CSS property that is the second element of the preset string. Used for matching.
142
+ *
143
+ * @return string|null The slug, or null if not found.
144
+ */
145
+ protected static function get_slug_from_preset_value( $style_value, $property_key ) {
146
+ if ( is_string( $style_value ) && strpos( $style_value, "var:preset|{$property_key}|" ) !== false ) {
147
+ $index_to_splice = strrpos( $style_value, '|' ) + 1;
148
+ return _wp_to_kebab_case( substr( $style_value, $index_to_splice ) );
149
+ }
150
+ return null;
151
+ }
152
+
153
+ /**
154
+ * Returns classnames, and generates classname(s) from a CSS preset property pattern, e.g., 'var:preset|color|heavenly-blue'.
70
155
  *
71
- * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property.
72
- * @param array<string> $path An array of strings representing a path to the style value.
156
+ * @param array $style_value A single raw style value or css preset property from the generate() $block_styles array.
157
+ * @param array<string> $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA.
73
158
  *
74
- * @return array A CSS ruleset compatible with generate().
159
+ * @return array An array of CSS classnames.
75
160
  */
76
- protected function get_block_style_css_rules( $style_value, $path ) {
77
- $style_definition = _wp_array_get( static::BLOCK_STYLE_DEFINITIONS_METADATA, $path, null );
78
-
79
- if ( ! empty( $style_definition ) ) {
80
- if (
81
- isset( $style_definition['value_func'] ) &&
82
- is_callable( $style_definition['value_func'] )
83
- ) {
84
- return call_user_func( $style_definition['value_func'], $style_value, $style_definition['property_key'] );
161
+ protected static function get_classnames( $style_value, $style_definition ) {
162
+ $classnames = array();
163
+ if ( ! empty( $style_definition['classnames'] ) ) {
164
+ foreach ( $style_definition['classnames'] as $classname => $property_key ) {
165
+ if ( true === $property_key ) {
166
+ $classnames[] = $classname;
167
+ }
168
+
169
+ $slug = static::get_slug_from_preset_value( $style_value, $property_key );
170
+
171
+ if ( $slug ) {
172
+ // Right now we expect a classname pattern to be stored in BLOCK_STYLE_DEFINITIONS_METADATA.
173
+ // One day, if there are no stored schemata, we could allow custom patterns or
174
+ // generate classnames based on other properties
175
+ // such as a path or a value or a prefix passed in options.
176
+ $classnames[] = sprintf( $classname, $slug );
177
+ }
85
178
  }
86
179
  }
87
180
 
88
- return array();
181
+ return $classnames;
182
+ }
183
+
184
+ /**
185
+ * Returns CSS rules based on valid block style values.
186
+ *
187
+ * @param array $style_value A single raw style value from the generate() $block_styles array.
188
+ * @param array<string> $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA.
189
+ *
190
+ * @return array An array of CSS rules.
191
+ */
192
+ protected static function get_css( $style_value, $style_definition ) {
193
+ // Low-specificity check to see if the value is a CSS preset.
194
+ if ( is_string( $style_value ) && strpos( $style_value, 'var:' ) !== false ) {
195
+ return array();
196
+ }
197
+
198
+ // If required in the future, style definitions could define a callable `value_func` to generate custom CSS rules.
199
+ return static::get_css_rules( $style_value, $style_definition['property_key'] );
89
200
  }
90
201
 
91
202
  /**
@@ -93,72 +204,78 @@ class WP_Style_Engine {
93
204
  * Styles are bundled based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA.
94
205
  *
95
206
  * @param array $block_styles An array of styles from a block's attributes.
96
- * @param array $options = array(
97
- * 'inline' => (boolean) Whether to return inline CSS rules destined to be inserted in an HTML `style` attribute.
98
- * 'path' => (array) Specify a block style to generate, otherwise it'll try all in BLOCK_STYLE_DEFINITIONS_METADATA.
99
- * );.
100
207
  *
101
- * @return string A CSS ruleset formatted to be placed in an HTML `style` attribute.
208
+ * @return array|null array(
209
+ * 'styles' => (string) A CSS ruleset formatted to be placed in an HTML `style` attribute or tag.
210
+ * 'classnames' => (string) Classnames separated by a space.
211
+ * );
102
212
  */
103
- public function generate( $block_styles, $options = array() ) {
104
- $output = '';
105
-
106
- if ( empty( $block_styles ) ) {
107
- return $output;
213
+ public function generate( $block_styles ) {
214
+ if ( empty( $block_styles ) || ! is_array( $block_styles ) ) {
215
+ return null;
108
216
  }
109
217
 
110
- $rules = array();
218
+ $css_rules = array();
219
+ $classnames = array();
220
+ $styles_output = array();
111
221
 
112
- // If a path to a specific block style is defined, only return rules for that style.
113
- if ( isset( $options['path'] ) && is_array( $options['path'] ) ) {
114
- $style_value = _wp_array_get( $block_styles, $options['path'], null );
115
- if ( empty( $style_value ) ) {
116
- return $output;
117
- }
118
- $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $options['path'] ) );
119
- } else {
120
- // Otherwise build them all.
121
- foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) {
122
- foreach ( $definition_group as $style_definition ) {
123
- $style_value = _wp_array_get( $block_styles, $style_definition['path'], null );
124
- if ( empty( $style_value ) ) {
125
- continue;
126
- }
127
- $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $style_definition['path'] ) );
222
+ // Collect CSS and classnames.
223
+ foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) {
224
+ foreach ( $definition_group as $style_definition ) {
225
+ $style_value = _wp_array_get( $block_styles, $style_definition['path'], null );
226
+
227
+ if ( empty( $style_value ) ) {
228
+ continue;
128
229
  }
230
+
231
+ $classnames = array_merge( $classnames, static::get_classnames( $style_value, $style_definition ) );
232
+ $css_rules = array_merge( $css_rules, static::get_css( $style_value, $style_definition ) );
129
233
  }
130
234
  }
131
235
 
132
- if ( ! empty( $rules ) ) {
236
+ // Build CSS rules output.
237
+ $css_output = '';
238
+ if ( ! empty( $css_rules ) ) {
133
239
  // Generate inline style rules.
134
- if ( isset( $options['inline'] ) && true === $options['inline'] ) {
135
- foreach ( $rules as $rule => $value ) {
136
- $filtered_css = esc_html( safecss_filter_attr( "{$rule}:{$value}" ) );
137
- if ( ! empty( $filtered_css ) ) {
138
- $output .= $filtered_css . ';';
139
- }
240
+ // In the future there might be a flag in the option to output
241
+ // inline CSS rules (for HTML style attributes) vs selectors + rules for style tags.
242
+ foreach ( $css_rules as $rule => $value ) {
243
+ $filtered_css = esc_html( safecss_filter_attr( "{$rule}: {$value}" ) );
244
+ if ( ! empty( $filtered_css ) ) {
245
+ $css_output .= $filtered_css . '; ';
140
246
  }
141
247
  }
142
248
  }
143
249
 
144
- return $output;
250
+ if ( ! empty( $css_output ) ) {
251
+ $styles_output['css'] = trim( $css_output );
252
+ }
253
+
254
+ if ( ! empty( $classnames ) ) {
255
+ $styles_output['classnames'] = implode( ' ', array_unique( $classnames ) );
256
+ }
257
+
258
+ return $styles_output;
145
259
  }
146
260
 
147
261
  /**
148
- * Returns a CSS ruleset for box model styles such as margins, padding, and borders.
262
+ * Default style value parser that returns a CSS ruleset.
263
+ * If the input contains an array, it will be treated like a box model
264
+ * for styles such as margins and padding
149
265
  *
150
266
  * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property.
151
267
  * @param string $style_property The CSS property for which we're creating a rule.
152
268
  *
153
269
  * @return array The class name for the added style.
154
270
  */
155
- public static function get_css_box_rules( $style_value, $style_property ) {
271
+ protected static function get_css_rules( $style_value, $style_property ) {
156
272
  $rules = array();
157
273
 
158
274
  if ( ! $style_value ) {
159
275
  return $rules;
160
276
  }
161
277
 
278
+ // We assume box model-like properties.
162
279
  if ( is_array( $style_value ) ) {
163
280
  foreach ( $style_value as $key => $value ) {
164
281
  $rules[ "$style_property-$key" ] = $value;
@@ -166,17 +283,28 @@ class WP_Style_Engine {
166
283
  } else {
167
284
  $rules[ $style_property ] = $style_value;
168
285
  }
286
+
169
287
  return $rules;
170
288
  }
171
289
  }
172
290
 
173
291
  /**
174
- * This function returns the Style Engine instance.
292
+ * Global public interface method to WP_Style_Engine->generate.
293
+ *
294
+ * Returns an CSS ruleset.
295
+ * Styles are bundled based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA.
296
+ *
297
+ * @param array $block_styles An array of styles from a block's attributes.
175
298
  *
176
- * @return WP_Style_Engine
299
+ * @return array|null array(
300
+ * 'styles' => (string) A CSS ruleset formatted to be placed in an HTML `style` attribute or tag.
301
+ * 'classnames' => (string) Classnames separated by a space.
302
+ * );
177
303
  */
178
- function wp_get_style_engine() {
304
+ function wp_style_engine_generate( $block_styles ) {
179
305
  if ( class_exists( 'WP_Style_Engine' ) ) {
180
- return WP_Style_Engine::get_instance();
306
+ $style_engine = WP_Style_Engine::get_instance();
307
+ return $style_engine->generate( $block_styles );
181
308
  }
309
+ return null;
182
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/style-engine",
3
- "version": "0.5.1",
3
+ "version": "0.8.0",
4
4
  "description": "WordPress Style engine.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -34,5 +34,5 @@
34
34
  "publishConfig": {
35
35
  "access": "public"
36
36
  },
37
- "gitHead": "446565ecaa40370173c18926535e975ec5652b71"
37
+ "gitHead": "198fa129cf1af8dc615918987ea6795cd40ab7df"
38
38
  }
@@ -13,16 +13,12 @@ require __DIR__ . '/../class-wp-style-engine.php';
13
13
  */
14
14
  class WP_Style_Engine_Test extends WP_UnitTestCase {
15
15
  /**
16
- * Tests various manifestations of the $block_styles argument.
16
+ * Tests generating styles and classnames based on various manifestations of the $block_styles argument.
17
17
  *
18
- * @dataProvider data_block_styles_fixtures
18
+ * @dataProvider data_generate_styles_fixtures
19
19
  */
20
- function test_generate_css( $block_styles, $options, $expected_output ) {
21
- $style_engine = WP_Style_Engine::get_instance();
22
- $generated_styles = $style_engine->generate(
23
- $block_styles,
24
- $options
25
- );
20
+ function test_generate_styles( $block_styles, $expected_output ) {
21
+ $generated_styles = wp_style_engine_generate( $block_styles );
26
22
  $this->assertSame( $expected_output, $generated_styles );
27
23
  }
28
24
 
@@ -31,42 +27,30 @@ class WP_Style_Engine_Test extends WP_UnitTestCase {
31
27
  *
32
28
  * @return array
33
29
  */
34
- public function data_block_styles_fixtures() {
30
+ public function data_generate_styles_fixtures() {
35
31
  return array(
36
32
  'default_return_value' => array(
37
33
  'block_styles' => array(),
38
- 'options' => null,
39
- 'expected_output' => '',
34
+ 'expected_output' => null,
40
35
  ),
41
36
 
42
37
  'inline_invalid_block_styles_empty' => array(
43
- 'block_styles' => array(),
44
- 'options' => array(
45
- 'path' => array( 'spacing', 'padding' ),
46
- 'inline' => true,
47
- ),
48
- 'expected_output' => '',
38
+ 'block_styles' => 'hello world!',
39
+ 'expected_output' => null,
49
40
  ),
50
41
 
51
42
  'inline_invalid_block_styles_unknown_style' => array(
52
43
  'block_styles' => array(
53
44
  'pageBreakAfter' => 'verso',
54
45
  ),
55
- 'options' => array(
56
- 'inline' => true,
57
- ),
58
- 'expected_output' => '',
46
+ 'expected_output' => array(),
59
47
  ),
60
48
 
61
49
  'inline_invalid_block_styles_unknown_definition' => array(
62
50
  'block_styles' => array(
63
51
  'pageBreakAfter' => 'verso',
64
52
  ),
65
- 'options' => array(
66
- 'path' => array( 'pageBreakAfter', 'verso' ),
67
- 'inline' => true,
68
- ),
69
- 'expected_output' => '',
53
+ 'expected_output' => array(),
70
54
  ),
71
55
 
72
56
  'inline_invalid_block_styles_unknown_property' => array(
@@ -75,39 +59,25 @@ class WP_Style_Engine_Test extends WP_UnitTestCase {
75
59
  'gap' => '1000vw',
76
60
  ),
77
61
  ),
78
- 'options' => array(
79
- 'path' => array( 'spacing', 'padding' ),
80
- 'inline' => true,
81
- ),
82
- 'expected_output' => '',
62
+ 'expected_output' => array(),
83
63
  ),
84
64
 
85
- 'inline_invalid_multiple_style_unknown_property' => array(
65
+ 'valid_inline_css_and_classnames' => array(
86
66
  'block_styles' => array(
87
- 'spacing' => array(
88
- 'gavin' => '1000vw',
67
+ 'color' => array(
68
+ 'text' => 'var:preset|color|texas-flood',
89
69
  ),
90
- ),
91
- 'options' => array(
92
- 'inline' => true,
93
- ),
94
- 'expected_output' => '',
95
- ),
96
-
97
- 'inline_valid_single_style_string' => array(
98
- 'block_styles' => array(
99
70
  'spacing' => array(
100
71
  'margin' => '111px',
101
72
  ),
102
73
  ),
103
- 'options' => array(
104
- 'path' => array( 'spacing', 'margin' ),
105
- 'inline' => true,
74
+ 'expected_output' => array(
75
+ 'css' => 'margin: 111px;',
76
+ 'classnames' => 'has-text-color has-texas-flood-color',
106
77
  ),
107
- 'expected_output' => 'margin:111px;',
108
78
  ),
109
79
 
110
- 'inline_valid_single_style' => array(
80
+ 'inline_valid_box_model_style' => array(
111
81
  'block_styles' => array(
112
82
  'spacing' => array(
113
83
  'padding' => array(
@@ -124,34 +94,83 @@ class WP_Style_Engine_Test extends WP_UnitTestCase {
124
94
  ),
125
95
  ),
126
96
  ),
127
- 'options' => array(
128
- 'path' => array( 'spacing', 'padding' ),
129
- 'inline' => true,
97
+ 'expected_output' => array(
98
+ 'css' => 'padding-top: 42px; padding-left: 2%; padding-bottom: 44px; padding-right: 5rem; margin-top: 12rem; margin-left: 2vh; margin-bottom: 2px; margin-right: 10em;',
130
99
  ),
131
- 'expected_output' => 'padding-top:42px;padding-left:2%;padding-bottom:44px;padding-right:5rem;',
132
100
  ),
133
101
 
134
- 'inline_valid_multiple_style' => array(
102
+ 'inline_valid_typography_style' => array(
103
+ 'block_styles' => array(
104
+ 'typography' => array(
105
+ 'fontSize' => 'clamp(2em, 2vw, 4em)',
106
+ 'fontFamily' => 'Roboto,Oxygen-Sans,Ubuntu,sans-serif',
107
+ 'fontStyle' => 'italic',
108
+ 'fontWeight' => '800',
109
+ 'lineHeight' => '1.3',
110
+ 'textDecoration' => 'underline',
111
+ 'textTransform' => 'uppercase',
112
+ 'letterSpacing' => '2',
113
+ ),
114
+ ),
115
+ 'expected_output' => array(
116
+ 'css' => 'font-family: Roboto,Oxygen-Sans,Ubuntu,sans-serif; font-style: italic; font-weight: 800; line-height: 1.3; text-decoration: underline; text-transform: uppercase; letter-spacing: 2;',
117
+ ),
118
+ ),
119
+ 'valid_classnames_deduped' => array(
120
+ 'block_styles' => array(
121
+ 'color' => array(
122
+ 'text' => 'var:preset|color|copper-socks',
123
+ 'background' => 'var:preset|color|splendid-carrot',
124
+ 'gradient' => 'var:preset|gradient|like-wow-dude',
125
+ ),
126
+ 'typography' => array(
127
+ 'fontSize' => 'var:preset|font-size|fantastic',
128
+ 'fontFamily' => 'var:preset|font-family|totally-awesome',
129
+ ),
130
+ ),
131
+ 'expected_output' => array(
132
+ 'classnames' => 'has-text-color has-copper-socks-color has-background has-splendid-carrot-background-color has-like-wow-dude-gradient-background has-fantastic-font-size has-totally-awesome-font-family',
133
+ ),
134
+ ),
135
+ 'valid_classnames_with_null_style_values' => array(
135
136
  'block_styles' => array(
137
+ 'color' => array(
138
+ 'text' => '#fff',
139
+ 'background' => null,
140
+ ),
141
+ ),
142
+ 'expected_output' => array(
143
+ 'css' => 'color: #fff;',
144
+ 'classnames' => 'has-text-color',
145
+ ),
146
+ ),
147
+ 'invalid_classnames_preset_value' => array(
148
+ 'block_styles' => array(
149
+ 'color' => array(
150
+ 'text' => 'var:cheese|color|fantastic',
151
+ 'background' => 'var:preset|fromage|fantastic',
152
+ ),
136
153
  'spacing' => array(
137
- 'padding' => array(
138
- 'top' => '42px',
139
- 'left' => '2%',
140
- 'bottom' => '44px',
141
- 'right' => '5rem',
154
+ 'margin' => 'var:cheese|spacing|margin',
155
+ 'padding' => 'var:preset|spacing|padding',
156
+ ),
157
+ ),
158
+ 'expected_output' => array(
159
+ 'classnames' => 'has-text-color has-background',
160
+ ),
161
+ ),
162
+ 'invalid_classnames_options' => array(
163
+ 'block_styles' => array(
164
+ 'typography' => array(
165
+ 'fontSize' => array(
166
+ 'tomodachi' => 'friends',
142
167
  ),
143
- 'margin' => array(
144
- 'top' => '12rem',
145
- 'left' => '2vh',
146
- 'bottom' => '2px',
147
- 'right' => '10em',
168
+ 'fontFamily' => array(
169
+ 'oishii' => 'tasty',
148
170
  ),
149
171
  ),
150
172
  ),
151
- 'options' => array(
152
- 'inline' => true,
153
- ),
154
- 'expected_output' => 'padding-top:42px;padding-left:2%;padding-bottom:44px;padding-right:5rem;margin-top:12rem;margin-left:2vh;margin-bottom:2px;margin-right:10em;',
173
+ 'expected_output' => array(),
155
174
  ),
156
175
  );
157
176
  }
package/src/index.ts CHANGED
@@ -24,6 +24,16 @@ import { styleDefinitions } from './styles';
24
24
  */
25
25
  export function generate( style: Style, options: StyleOptions ): string {
26
26
  const rules = getCSSRules( style, options );
27
+
28
+ // If no selector is provided, treat generated rules as inline styles to be returned as a single string.
29
+ if ( ! options?.selector ) {
30
+ const inlineRules: string[] = [];
31
+ rules.forEach( ( rule ) => {
32
+ inlineRules.push( `${ kebabCase( rule.key ) }: ${ rule.value };` );
33
+ } );
34
+ return inlineRules.join( ' ' );
35
+ }
36
+
27
37
  const groupedRules = groupBy( rules, 'selector' );
28
38
  const selectorRules = Object.keys( groupedRules ).reduce(
29
39
  ( acc: string[], subSelector: string ) => {
@@ -57,7 +67,9 @@ export function getCSSRules(
57
67
  ): GeneratedCSSRule[] {
58
68
  const rules: GeneratedCSSRule[] = [];
59
69
  styleDefinitions.forEach( ( definition: StyleDefinition ) => {
60
- rules.push( ...definition.generate( style, options ) );
70
+ if ( typeof definition.generate === 'function' ) {
71
+ rules.push( ...definition.generate( style, options ) );
72
+ }
61
73
  } );
62
74
 
63
75
  return rules;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Style, StyleOptions } from '../../types';
5
+ import { generateRule } from '../utils';
6
+
7
+ const background = {
8
+ name: 'background',
9
+ generate: ( style: Style, options: StyleOptions ) => {
10
+ return generateRule(
11
+ style,
12
+ options,
13
+ [ 'color', 'background' ],
14
+ 'backgroundColor'
15
+ );
16
+ },
17
+ };
18
+
19
+ export default background;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Style, StyleOptions } from '../../types';
5
+ import { generateRule } from '../utils';
6
+
7
+ const gradient = {
8
+ name: 'gradient',
9
+ generate: ( style: Style, options: StyleOptions ) => {
10
+ return generateRule(
11
+ style,
12
+ options,
13
+ [ 'color', 'gradient' ],
14
+ 'background'
15
+ );
16
+ },
17
+ };
18
+
19
+ export default gradient;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import background from './background';
5
+ import gradient from './gradient';
6
+ import text from './text';
7
+
8
+ export default [ text, gradient, background ];
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Style, StyleOptions } from '../../types';
5
+ import { generateRule } from '../utils';
6
+
7
+ const text = {
8
+ name: 'text',
9
+ generate: ( style: Style, options: StyleOptions ) => {
10
+ return generateRule( style, options, [ 'color', 'text' ], 'color' );
11
+ },
12
+ };
13
+
14
+ export default text;