refactor: ColumnWidths holds the column-width rules (H5)

Composer::row uses ColumnWidths::parse; rowWidthsError and its error-state
save/restore are gone. The update width check moves out of
DiviUpdateAbility into ColumnWidths::updateErrors. Behaviour unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 18:21:03 +02:00
co-authored by Claude Opus 5.5
parent 6cf0a565e6
commit 9da236b0e3
5 changed files with 267 additions and 219 deletions
@@ -298,19 +298,6 @@ final class ComposerTest extends TestCase
self::assertSame('h3', $explicit['blocks'][0]->attrs()['title']['decoration']['font']['font']['desktop']['value']['headingLevel']);
}
/** Ruling S41: column widths on update follow the rules of "columns". */
public function testRowWidthsAreChecked(): void
{
$composer = ComposeFixture::composer();
self::assertNull($composer->rowWidthsError(['8_24', '16_24']));
self::assertNull($composer->rowWidthsError(['1_5', '1_5', '1_5', '1_5', '1_5']));
self::assertNotNull($composer->rowWidthsError(['12_24', '16_24']));
self::assertNotNull($composer->rowWidthsError(['1_13', '12_13']));
self::assertNotNull($composer->rowWidthsError(['x', '24_24']));
self::assertNotNull($composer->rowWidthsError([]));
}
/** Ruling S13: labels go through the choke point; a label that fails is an error, never stored raw. */
public function testLabelsAreCleanedOrReported(): void
{