Skip to content

Commit eca3244

Browse files
authored
Merge pull request #6 from imagewize/fix/border-html-serialization-rules
Fix/border Html Serialization Rules
2 parents b23f16a + 43f219e commit eca3244

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [2.2.2] - 2026-05-12
8+
9+
### Added
10+
11+
- **`border-style-solid-in-html` rule** (`BaseRules`) — detects `border-style:solid` in `<div>` inline styles. WordPress's save function does not emit this property when border color uses `var:preset|color|`, so its presence in the pattern HTML guarantees a block validation mismatch.
12+
- **`border-property-order-in-html` rule** (`BaseRules`) — detects `border-width` appearing before `border-color` in a `<div>` inline style. WordPress always serializes `border-color` first; wrong order causes a block validation mismatch on template reset.
13+
714
## [2.2.1] - 2026-05-12
815

916
### Added

src/Compliance/Rules/BaseRules.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public function check(string $filePath): array
6464
$violations = array_merge($violations, $this->checkCoverBlockMinHeight($content));
6565
$violations = array_merge($violations, $this->checkEmptyBorderSideObjects($content));
6666
$violations = array_merge($violations, $this->checkBorderColorRawSlug($content));
67+
$violations = array_merge($violations, $this->checkBorderStyleSolidInHtml($content));
68+
$violations = array_merge($violations, $this->checkBorderPropertyOrderInHtml($content));
6769
$violations = array_merge($violations, $this->checkButtonsWrapper($content));
6870
$violations = array_merge($violations, $this->checkGroupOverflowHidden($content));
6971
$violations = array_merge($violations, $this->checkOpacityInlineStyle($content));
@@ -276,6 +278,36 @@ private function checkBorderColorRawSlug(string $content): array
276278
return [];
277279
}
278280

281+
private function checkBorderStyleSolidInHtml(string $content): array
282+
{
283+
// WordPress's block save function does not emit border-style:solid when border color is set
284+
// via a var:preset reference. Its presence in a <div> inline style means the HTML was written
285+
// against an older serialization and will cause a block validation mismatch.
286+
foreach (explode("\n", $content) as $line) {
287+
$trimmed = ltrim($line);
288+
if (str_starts_with($trimmed, '<div') && str_contains($line, 'border-style:solid')) {
289+
return [$this->violation('border-style-solid-in-html', 'Found "border-style:solid" in a <div> inline style — WordPress\'s save function does not generate this when border color uses var:preset|color|. Its presence causes a block validation mismatch. Remove border-style:solid from the HTML.')];
290+
}
291+
}
292+
return [];
293+
}
294+
295+
private function checkBorderPropertyOrderInHtml(string $content): array
296+
{
297+
// WordPress serializes border-color before border-width in inline styles.
298+
// border-width appearing before border-color in a <div> style attribute means the HTML
299+
// was written against the old serialization order and will cause a block validation mismatch.
300+
foreach (explode("\n", $content) as $line) {
301+
if (!str_starts_with(ltrim($line), '<div')) {
302+
continue;
303+
}
304+
if (preg_match('/style="[^"]*border-width:[^"]*border-color:[^"]*"/', $line)) {
305+
return [$this->violation('border-property-order-in-html', 'Found "border-width" before "border-color" in a <div> inline style — WordPress serializes border-color first. Wrong order causes a block validation mismatch. Reorder to: border-color:...;border-width:...;border-radius:...')];
306+
}
307+
}
308+
return [];
309+
}
310+
279311
private function checkButtonsWrapper(string $content): array
280312
{
281313
$lines = explode("\n", $content);

tests/Compliance/Rules/BaseRulesTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,92 @@ public function testBorderColorEmptyObjectPassesClean(): void
366366
$ruleNames = array_column($violations, 'rule');
367367
$this->assertNotContains('border-color-raw-slug', $ruleNames);
368368
}
369+
370+
// ========================================================================
371+
// Border Style Solid in HTML Tests
372+
// ========================================================================
373+
374+
public function testBorderStyleSolidInHtmlIsViolation(): void
375+
{
376+
$content = <<<'PHP'
377+
<?php ?>
378+
<!-- wp:group {"style":{"border":{"width":"1px","color":"var:preset|color|border-light","radius":"0"}}} -->
379+
<div class="wp-block-group has-border-color" style="border-width:1px;border-style:solid;border-radius:0;border-color:var(--wp--preset--color--border-light)"></div>
380+
<!-- /wp:group -->
381+
PHP;
382+
383+
$file = $this->createTempFile($content);
384+
$violations = $this->rules->check($file);
385+
386+
$ruleNames = array_column($violations, 'rule');
387+
$this->assertContains('border-style-solid-in-html', $ruleNames);
388+
}
389+
390+
public function testBorderStyleSolidInHtmlPassesClean(): void
391+
{
392+
$content = <<<'PHP'
393+
<?php ?>
394+
<!-- wp:group {"style":{"border":{"width":"1px","color":"var:preset|color|border-light","radius":"0"}}} -->
395+
<div class="wp-block-group has-border-color" style="border-color:var(--wp--preset--color--border-light);border-width:1px;border-radius:0"></div>
396+
<!-- /wp:group -->
397+
PHP;
398+
399+
$file = $this->createTempFile($content);
400+
$violations = $this->rules->check($file);
401+
402+
$ruleNames = array_column($violations, 'rule');
403+
$this->assertNotContains('border-style-solid-in-html', $ruleNames);
404+
}
405+
406+
public function testBorderStyleSolidInBlockCommentIsIgnored(): void
407+
{
408+
$content = <<<'PHP'
409+
<?php ?>
410+
<!-- wp:group {"note":"border-style:solid is fine in comments"} -->
411+
<div class="wp-block-group"></div>
412+
<!-- /wp:group -->
413+
PHP;
414+
415+
$file = $this->createTempFile($content);
416+
$violations = $this->rules->check($file);
417+
418+
$ruleNames = array_column($violations, 'rule');
419+
$this->assertNotContains('border-style-solid-in-html', $ruleNames);
420+
}
421+
422+
// ========================================================================
423+
// Border Property Order in HTML Tests
424+
// ========================================================================
425+
426+
public function testBorderWidthBeforeBorderColorIsViolation(): void
427+
{
428+
$content = <<<'PHP'
429+
<?php ?>
430+
<!-- wp:group {"style":{"border":{"width":"1px","color":"var:preset|color|border-light","radius":"0"}}} -->
431+
<div class="wp-block-group has-border-color" style="border-width:1px;border-radius:0;border-color:var(--wp--preset--color--border-light)"></div>
432+
<!-- /wp:group -->
433+
PHP;
434+
435+
$file = $this->createTempFile($content);
436+
$violations = $this->rules->check($file);
437+
438+
$ruleNames = array_column($violations, 'rule');
439+
$this->assertContains('border-property-order-in-html', $ruleNames);
440+
}
441+
442+
public function testBorderColorBeforeBorderWidthPassesClean(): void
443+
{
444+
$content = <<<'PHP'
445+
<?php ?>
446+
<!-- wp:group {"style":{"border":{"width":"1px","color":"var:preset|color|border-light","radius":"0"}}} -->
447+
<div class="wp-block-group has-border-color" style="border-color:var(--wp--preset--color--border-light);border-width:1px;border-radius:0"></div>
448+
<!-- /wp:group -->
449+
PHP;
450+
451+
$file = $this->createTempFile($content);
452+
$violations = $this->rules->check($file);
453+
454+
$ruleNames = array_column($violations, 'rule');
455+
$this->assertNotContains('border-property-order-in-html', $ruleNames);
456+
}
369457
}

0 commit comments

Comments
 (0)