@@ -49,18 +49,27 @@ class RsvTemplateEngine {
|
||||
|
||||
/**
|
||||
* Lists a template's problems without rendering it (empty = valid): empty
|
||||
* interpolations, unregistered custom elements, and attributes an element
|
||||
* does not declare.
|
||||
* interpolations, references to unknown symbols, unregistered custom
|
||||
* elements, and attributes an element does not declare.
|
||||
*
|
||||
* @param list<string>|null $symbols When given, the roots an interpolation may
|
||||
* reference; a path rooted outside the set is reported as unknown. Null
|
||||
* skips the reference check (any path is accepted).
|
||||
* @return list<string>
|
||||
*/
|
||||
public function validate(string $source): array {
|
||||
public function validate(string $source, ?array $symbols = null): array {
|
||||
$errors = [];
|
||||
|
||||
if (preg_match_all('/{{\s*([^}]*?)\s*}}/', $source, $matches)) {
|
||||
foreach ($matches[1] as $path) {
|
||||
if (trim($path) === '') {
|
||||
$expr = trim($path);
|
||||
if ($expr === '') {
|
||||
$errors[] = 'Empty interpolation: {{ }}';
|
||||
continue;
|
||||
}
|
||||
$root = $this->tokens($expr)[0] ?? null;
|
||||
if ($symbols !== null && $root !== null && !in_array($root, $symbols, true)) {
|
||||
$errors[] = "Unknown reference: {{ {$expr} }}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,14 +157,9 @@ class RsvTemplateEngine {
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private function resolve(string $path, array $data): mixed {
|
||||
$tokens = preg_split('/[\.\[\]]+/', $path, -1, PREG_SPLIT_NO_EMPTY) ?: [];
|
||||
$current = $data;
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
if ($token === '$') {
|
||||
continue; // root sigil
|
||||
}
|
||||
$token = trim($token, "'\""); // strip bracket-notation quotes
|
||||
foreach ($this->tokens($path) as $token) {
|
||||
if (!is_array($current) || !array_key_exists($token, $current)) {
|
||||
return null;
|
||||
}
|
||||
@@ -165,6 +169,24 @@ class RsvTemplateEngine {
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a JSON Path into its key tokens, dropping the root sigil and
|
||||
* bracket-notation quotes — e.g. "$.items[0]" yields ['items', '0'].
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function tokens(string $path): array {
|
||||
$raw = preg_split('/[\.\[\]]+/', $path, -1, PREG_SPLIT_NO_EMPTY) ?: [];
|
||||
$tokens = [];
|
||||
foreach ($raw as $token) {
|
||||
if ($token === '$') {
|
||||
continue; // root sigil
|
||||
}
|
||||
$tokens[] = trim($token, "'\""); // strip bracket-notation quotes
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// DOM helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user