PluginProbe
Gutenberg / 23.0.1
Gutenberg v23.0.1
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / block-supports / custom-css.php

custom-css.php in Gutenberg 23.0.1, at lib/block-supports/custom-css.php

146 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Custom CSS block support.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Render the custom CSS stylesheet and add class name to block as required.
10 *
11 * @since 7.0.0
12 *
13 * @param array $parsed_block The parsed block.
14 * @return array The same parsed block with custom CSS class name added if appropriate.
15 */
16 function gutenberg_render_custom_css_support_styles( $parsed_block ) {
17 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
18
19 if ( ! block_has_support( $block_type, 'customCSS', true ) ) {
20 return $parsed_block;
21 }
22
23 $custom_css = trim( $parsed_block['attrs']['style']['css'] ?? '' );
24
25 if ( empty( $custom_css ) ) {
26 return $parsed_block;
27 }
28
29 // Validate CSS doesn't contain HTML markup (same validation as global styles REST API).
30 if ( preg_match( '#</?\w+#', $custom_css ) ) {
31 return $parsed_block;
32 }
33
34 // Generate a unique class name for this block instance.
35 $class_name = wp_unique_id_from_values( $parsed_block, 'wp-custom-css-' );
36 $updated_class_name = isset( $parsed_block['attrs']['className'] )
37 ? $parsed_block['attrs']['className'] . " $class_name"
38 : $class_name;
39
40 _wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );
41
42 // Process the custom CSS using the same method as global styles.
43 $selector = '.' . $class_name;
44 $processed_css = WP_Theme_JSON_Gutenberg::process_blocks_custom_css( $custom_css, $selector );
45
46 if ( ! empty( $processed_css ) ) {
47 /*
48 * Register and add inline style for block custom CSS.
49 * The style depends on global-styles to ensure custom CSS loads after
50 * and can override global styles.
51 */
52 wp_register_style( 'wp-block-custom-css', false, array( 'global-styles' ) );
53 wp_add_inline_style( 'wp-block-custom-css', $processed_css );
54 }
55
56 return $parsed_block;
57 }
58
59 /**
60 * Enqueues the block custom CSS styles.
61 *
62 * @since 7.0.0
63 */
64 function gutenberg_enqueue_block_custom_css() {
65 wp_enqueue_style( 'wp-block-custom-css' );
66 }
67
68 /**
69 * Applies the custom CSS class name to the block's rendered HTML.
70 *
71 * The class name is generated in `gutenberg_render_custom_css_support_styles`
72 * and stored in block attributes. This filter adds it to the actual markup.
73 *
74 * @since 7.0.0
75 *
76 * @param string $block_content Rendered block content.
77 * @param array $block Block object.
78 * @return string Filtered block content.
79 */
80 function gutenberg_render_custom_css_class_name( $block_content, $block ) {
81 $class_string = $block['attrs']['className'] ?? '';
82 preg_match( '/\bwp-custom-css-\S+\b/', $class_string, $matches );
83
84 if ( empty( $matches ) ) {
85 return $block_content;
86 }
87
88 $tags = new WP_HTML_Tag_Processor( $block_content );
89
90 if ( $tags->next_tag() ) {
91 $tags->add_class( 'has-custom-css' );
92 $tags->add_class( $matches[0] );
93 }
94
95 return $tags->get_updated_html();
96 }
97
98 // Remove core filters and action to avoid rendering duplicate custom CSS styles.
99 if ( function_exists( 'wp_render_custom_css_class_name' ) ) {
100 remove_filter( 'render_block', 'wp_render_custom_css_class_name' );
101 }
102 if ( function_exists( 'wp_render_custom_css_support_styles' ) ) {
103 remove_filter( 'render_block_data', 'wp_render_custom_css_support_styles' );
104 }
105 if ( function_exists( 'wp_enqueue_block_custom_css' ) ) {
106 remove_action( 'wp_enqueue_scripts', 'wp_enqueue_block_custom_css' );
107 }
108
109 // Add Gutenberg filters and action.
110 add_filter( 'render_block', 'gutenberg_render_custom_css_class_name', 10, 2 );
111 add_filter( 'render_block_data', 'gutenberg_render_custom_css_support_styles', 10, 1 );
112 add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_block_custom_css', 1 );
113
114 /**
115 * Registers the style block attribute for block types that support it.
116 *
117 * @param WP_Block_Type $block_type Block Type.
118 */
119 function gutenberg_register_custom_css_support( $block_type ) {
120 // Setup attributes and styles within that if needed.
121 if ( ! $block_type->attributes ) {
122 $block_type->attributes = array();
123 }
124
125 // Check for existing style attribute definition e.g. from block.json.
126 if ( array_key_exists( 'style', $block_type->attributes ) ) {
127 return;
128 }
129
130 $has_custom_css_support = block_has_support( $block_type, array( 'customCSS' ), true );
131
132 if ( $has_custom_css_support ) {
133 $block_type->attributes['style'] = array(
134 'type' => 'object',
135 );
136 }
137 }
138
139 // Register the block support.
140 WP_Block_Supports::get_instance()->register(
141 'custom-css',
142 array(
143 'register_attribute' => 'gutenberg_register_custom_css_support',
144 )
145 );
146