fix: Task 3 review round 1 - strip control chars before the sanitizer (S32a), S34 minors

Control characters now go on the raw value in AttrWriter::cleanNode and
VariableRef::setting; after the sanitizer only rejection remains ('<' + VT/FF
no longer turns into a tag). VALUE_KEY anchored with D, exact column-width
fractions, nested rows in columns, specialty columns refused, fullwidth by
catalog category, preset ambiguity in DesignSystem::modulePresetId().

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 14:26:18 +02:00
co-authored by Claude Opus 5.5
parent 4b72c2bb42
commit 8688a02402
13 changed files with 278 additions and 104 deletions
+29 -8
View File
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Design;
use InvalidArgumentException;
/**
* The site's Divi design system as read live from Divi (spec §2 principle 2, §5.7): global
* colors, global variables, theme fonts and sizes, module and group presets. Pure PHP –
@@ -162,21 +164,40 @@ final class DesignSystem
return null;
}
/** Module preset ID by name or ID for a full module name ("divi/button"); null when unknown. */
/**
* Module preset ID for a full module name ("divi/button"): an exact ID first, else the one
* preset of that name (case-insensitive); null when unknown.
*
* @throws InvalidArgumentException When several presets of the module share the name (ruling S13a).
*/
public function modulePresetId(string $module, string $name): ?string
{
$key = mb_strtolower(trim($name));
$wanted = trim($name);
$key = mb_strtolower($wanted);
$ids = [];
foreach ($this->presets as $preset) {
if (
$preset['kind'] === 'module'
&& $preset['module'] === $module
&& ($preset['id'] === trim($name) || mb_strtolower($preset['name']) === $key)
) {
if ($preset['kind'] !== 'module' || $preset['module'] !== $module) {
continue;
}
if ($preset['id'] === $wanted) {
return $preset['id'];
}
if (mb_strtolower($preset['name']) === $key) {
$ids[] = $preset['id'];
}
}
return null;
if (count($ids) > 1) {
throw new InvalidArgumentException(sprintf(
'Preset-Name "%s" ist mehrdeutig; bitte die ID angeben: %s.',
$wanted,
implode(', ', $ids)
));
}
return $ids[0] ?? null;
}
/** @return list<string> Names of the module presets of $module. */