Skip to content

Commit 2330b2e

Browse files
committed
Dynamically add CSS classe to Paragraph block
1 parent 1925623 commit 2330b2e

6 files changed

Lines changed: 149 additions & 9 deletions

File tree

packages/block-library/src/paragraph/block.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
"fontSize": true
7070
}
7171
},
72-
"__experimentalSelector": "p",
7372
"__unstablePasteTextInline": true,
7473
"interactivity": {
7574
"clientNavigation": true
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* Appending the wp-block-paragraph to before rendering the stored `core/paragraph` block contents.
4+
*
5+
* @package WordPress
6+
*/
7+
8+
/**
9+
* Adds a wp-block-paragraph class to the paragraph block content.
10+
*
11+
* For example, the following block content:
12+
* <p class="align-left">Hello World</p>
13+
*
14+
* Would be transformed to:
15+
* <p class="align-left wp-block-paragraph">Hello World</p>
16+
*
17+
* @since 7.0.0
18+
*
19+
* @param array $attributes Attributes of the block being rendered.
20+
* @param string $content Content of the block being rendered.
21+
*
22+
* @return string The content of the block being rendered.
23+
*/
24+
function block_core_paragraph_render( $attributes, $content ) {
25+
if ( ! $content ) {
26+
return $content;
27+
}
28+
29+
$p = new WP_HTML_Tag_Processor( $content );
30+
31+
while ( $p->next_tag() ) {
32+
if ( 'P' === $p->get_tag() ) {
33+
$p->add_class( 'wp-block-paragraph' );
34+
break;
35+
}
36+
}
37+
38+
return $p->get_updated_html();
39+
}
40+
41+
/**
42+
* Registers the `core/paragraph` block on server.
43+
*
44+
* @since 7.0.0
45+
*/
46+
function register_block_core_paragraph() {
47+
register_block_type_from_metadata(
48+
__DIR__ . '/paragraph',
49+
array(
50+
'render_callback' => 'block_core_paragraph_render',
51+
)
52+
);
53+
}
54+
55+
add_action( 'init', 'register_block_core_paragraph' );

phpunit/block-bindings-test.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public function data_update_block_with_value_from_source() {
8585
<!-- /wp:paragraph -->
8686
HTML
8787
,
88-
'<p>test source value</p>',
88+
'<p class="wp-block-paragraph">test source value</p>',
8989
),
9090
'button block' => array(
9191
'text',
@@ -162,19 +162,19 @@ function ( $source_args, $block_instance, $attribute_name ) {
162162
$value = $source_args['key'];
163163
return "The attribute name is '$attribute_name' and its binding has argument 'key' with value '$value'.";
164164
},
165-
"<p>The attribute name is 'content' and its binding has argument 'key' with value 'test'.</p>",
165+
"<p class=\"wp-block-paragraph\">The attribute name is 'content' and its binding has argument 'key' with value 'test'.</p>",
166166
),
167167
'unsafe HTML should be sanitized' => array(
168168
function () {
169169
return '<script>alert("Unsafe HTML")</script>';
170170
},
171-
'<p>alert("Unsafe HTML")</p>',
171+
'<p class="wp-block-paragraph">alert("Unsafe HTML")</p>',
172172
),
173173
'symbols and numbers should be rendered correctly' => array(
174174
function () {
175175
return '$12.50';
176176
},
177-
'<p>$12.50</p>',
177+
'<p class="wp-block-paragraph">$12.50</p>',
178178
),
179179
);
180180
}
@@ -386,7 +386,7 @@ public function test_filter_block_bindings_source_value() {
386386
remove_filter( 'block_bindings_source_value', $filter_value );
387387

388388
$this->assertSame(
389-
'<p>Filtered value: test_arg. Block instance: core/paragraph. Attribute name: content.</p>',
389+
'<p class="wp-block-paragraph">Filtered value: test_arg. Block instance: core/paragraph. Attribute name: content.</p>',
390390
trim( $result ),
391391
'The block content should show the filtered value.'
392392
);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/**
3+
* Paragraph block rendering tests.
4+
*
5+
* @package WordPress
6+
* @subpackage Blocks
7+
*/
8+
9+
/**
10+
* Tests for the Paragraph block.
11+
*
12+
* @group blocks
13+
*/
14+
class Render_Block_Paragraph_Test extends WP_UnitTestCase {
15+
16+
17+
/**
18+
* @covers ::gutenberg_block_core_paragraph_render
19+
* @dataProvider add_css_class_test_examples
20+
*/
21+
public function test_block_core_paragraph_render_appends_css_class_to_a_vanilla_element( $input, $expected_result ) {
22+
$actual = gutenberg_block_core_paragraph_render( array(), $input );
23+
$this->assertEquals( $expected_result, $actual );
24+
}
25+
26+
public function add_css_class_test_examples() {
27+
return array(
28+
'should add a class name to a vanilla p element' => array(
29+
'<p>Hello World</p>',
30+
'<p class="wp-block-paragraph">Hello World</p>',
31+
),
32+
'should not add a class name to a div element' => array(
33+
'<div>Hello World</div>',
34+
'<div>Hello World</div>',
35+
),
36+
'should not add a class name to a span element' => array(
37+
'<span>Hello World</span>',
38+
'<span>Hello World</span>',
39+
),
40+
'should not add a class name to a heading element' => array(
41+
'<h2>Hello World</h2>',
42+
'<h2>Hello World</h2>',
43+
),
44+
'should add a class name even when the class attribute is already defined' => array(
45+
'<p class="is-align-right">Hello World</p>',
46+
'<p class="is-align-right wp-block-paragraph">Hello World</p>',
47+
),
48+
'should handle single quotes' => array(
49+
"<p class='is-align-right'>Hello World</p>",
50+
'<p class="is-align-right wp-block-paragraph">Hello World</p>',
51+
),
52+
'should handle single quotes with double quotes inside' => array(
53+
"<p class='\" is-align-right'>Hello World</p>",
54+
'<p class="&quot; is-align-right wp-block-paragraph">Hello World</p>',
55+
),
56+
'should not add a class name even when it is already defined' => array(
57+
'<p class="is-align-right wp-block-paragraph">Hello World</p>',
58+
'<p class="is-align-right wp-block-paragraph">Hello World</p>',
59+
),
60+
'should add a class name even when there are other HTML attributes present' => array(
61+
'<p style="display: block">Hello World</p>',
62+
'<p class="wp-block-paragraph" style="display: block">Hello World</p>',
63+
),
64+
'should add a class name even when the class attribute is already defined and has many entries' => array(
65+
'<p class="is-align-right custom classes">Hello World</p>',
66+
'<p class="is-align-right custom classes wp-block-paragraph">Hello World</p>',
67+
),
68+
'should not add a class name to a nested p' => array(
69+
'<p class="is-align-right custom classes"><p>Hello World</p></p>',
70+
'<p class="is-align-right custom classes wp-block-paragraph"><p>Hello World</p></p>',
71+
),
72+
'should not add a class name to a nested p when the parent has another attribute' => array(
73+
'<p style="display: block" class="is-align-right"><p>Hello World</p></p>',
74+
'<p style="display: block" class="is-align-right wp-block-paragraph"><p>Hello World</p></p>',
75+
),
76+
'should add a class name even when the class attribute is surrounded by other attributes' => array(
77+
'<p style="display: block" class="is-align-right" data-class="corner case!"><p>Hello World</p></p>',
78+
'<p style="display: block" class="is-align-right wp-block-paragraph" data-class="corner case!"><p>Hello World</p></p>',
79+
),
80+
'should add a class name without getting confused when there is a tricky data-class attribute present' => array(
81+
'<p data-class="corner case!" style="display: block" class="is-align-right"><p>Hello World</p></p>',
82+
'<p data-class="corner case!" style="display: block" class="is-align-right wp-block-paragraph"><p>Hello World</p></p>',
83+
),
84+
);
85+
}
86+
}

phpunit/blocks/renderReusable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,6 @@ public function test_render_respects_custom_context() {
6363
);
6464

6565
$output = $synced_pattern_block_instance->render();
66-
$this->assertSame( '<p>Custom content set from block context</p>', $output );
66+
$this->assertSame( '<p class="wp-block-paragraph">Custom content set from block context</p>', $output );
6767
}
6868
}

phpunit/class-wp-theme-json-test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5153,7 +5153,7 @@ public function test_get_shadow_styles_for_blocks() {
51535153
);
51545154

51555155
$variable_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}';
5156-
$element_styles = 'a:where(:not(.wp-element-button)){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(p){box-shadow: var(--wp--preset--shadow--natural);}';
5156+
$element_styles = 'a:where(:not(.wp-element-button)){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-block-paragraph){box-shadow: var(--wp--preset--shadow--natural);}';
51575157
$expected_styles = $variable_styles . $element_styles;
51585158
$this->assertSameCSS( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) );
51595159
}
@@ -6347,7 +6347,7 @@ public function test_blocks_without_pseudo_support_ignore_pseudo_selectors() {
63476347
)
63486348
);
63496349

6350-
$expected = ':root :where(p){color: black;}';
6350+
$expected = ':root :where(.wp-block-paragraph){color: black;}';
63516351
$this->assertSameCSS( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) );
63526352
$this->assertStringNotContainsString( 'p:hover{', $theme_json->get_stylesheet( array( 'styles' ) ) );
63536353
}

0 commit comments

Comments
 (0)