@10up/block-renderer-validator 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,352 @@
1
+ # @10up/block-renderer-validator
2
+
3
+ Validate JSON block trees against schemas, nesting rules, and theme tokens. This package ensures block trees are valid before rendering.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @10up/block-renderer-validator
9
+ # or
10
+ pnpm add @10up/block-renderer-validator
11
+ ```
12
+
13
+ ## Overview
14
+
15
+ This package provides comprehensive validation for block trees:
16
+
17
+ 1. **Schema Validation** - Validates block props against Zod schemas from block definitions
18
+ 2. **Nesting Validation** - Checks parent/ancestor/allowedBlocks constraints
19
+ 3. **Token Validation** - Verifies theme token references (colors, spacing, etc.)
20
+ 4. **Pattern Validation** - Confirms pattern slugs exist in the registry
21
+
22
+ ## Usage
23
+
24
+ ### Full Tree Validation
25
+
26
+ The main entry point - validates a tree with all available validators:
27
+
28
+ ```typescript
29
+ import { validateTree } from '@10up/block-renderer-validator';
30
+
31
+ const tree = {
32
+ root: 'para-1',
33
+ elements: {
34
+ 'para-1': {
35
+ key: 'para-1',
36
+ type: 'core/paragraph',
37
+ props: {
38
+ content: 'Hello',
39
+ style: { color: { background: 'var:preset|color|primary' } }
40
+ }
41
+ }
42
+ }
43
+ };
44
+
45
+ const result = validateTree(tree, {
46
+ catalog: blockCatalog, // Block definitions for schema/nesting
47
+ tokens: themeTokens, // Theme tokens for color/spacing validation
48
+ patterns: patternRegistry // Pattern definitions
49
+ });
50
+
51
+ if (result.valid) {
52
+ console.log('Tree is valid');
53
+ } else {
54
+ console.log('Errors:', result.errors);
55
+ // ['Unknown color token: primary', 'Invalid block type: core/unknown']
56
+ }
57
+ ```
58
+
59
+ ### Validation Options
60
+
61
+ ```typescript
62
+ interface ValidateTreeOptions {
63
+ /** Block catalog for schema and nesting validation */
64
+ catalog?: BlockCatalog;
65
+ /** Theme tokens for token validation */
66
+ tokens?: ThemeTokens;
67
+ /** Pattern registry for pattern validation */
68
+ patterns?: PatternRegistry;
69
+ /** Whether to validate schemas (default: true if catalog provided) */
70
+ validateSchemas?: boolean;
71
+ /** Whether to validate nesting rules (default: true if catalog provided) */
72
+ validateNesting?: boolean;
73
+ /** Whether to validate theme tokens (default: true if tokens provided) */
74
+ validateTokens?: boolean;
75
+ /** Whether to validate pattern references (default: true if patterns provided) */
76
+ validatePatterns?: boolean;
77
+ }
78
+ ```
79
+
80
+ ### Create Reusable Validator
81
+
82
+ ```typescript
83
+ import { createTreeValidator } from '@10up/block-renderer-validator';
84
+
85
+ const validator = createTreeValidator({
86
+ catalog: blockCatalog,
87
+ tokens: themeTokens,
88
+ patterns: patternRegistry,
89
+ });
90
+
91
+ // Use the pre-configured validator
92
+ const result1 = validator(tree1);
93
+ const result2 = validator(tree2);
94
+ ```
95
+
96
+ ## Schema Validation
97
+
98
+ Validate block props against their Zod schemas:
99
+
100
+ ```typescript
101
+ import { validateBlockProps, validateTreeSchemas } from '@10up/block-renderer-validator';
102
+
103
+ // Validate a single element's props
104
+ const result = validateBlockProps(element.props, blockDefinition.schema);
105
+ if (!result.valid) {
106
+ console.log(result.errors);
107
+ // ['content: Expected string, received number']
108
+ }
109
+
110
+ // Validate all elements in a tree
111
+ const treeResult = validateTreeSchemas(tree, catalog);
112
+ ```
113
+
114
+ ### Create Block Validator
115
+
116
+ Create a validator for a specific block:
117
+
118
+ ```typescript
119
+ import { createBlockValidator } from '@10up/block-renderer-validator';
120
+
121
+ const validateParagraph = createBlockValidator(paragraphDefinition);
122
+ const result = validateParagraph({ content: 'Hello', dropCap: true });
123
+ ```
124
+
125
+ ### Get Valid Attributes
126
+
127
+ Filter props to only include valid attributes:
128
+
129
+ ```typescript
130
+ import { getValidAttributes } from '@10up/block-renderer-validator';
131
+
132
+ const cleanProps = getValidAttributes(props, blockDefinition.schema);
133
+ // Returns only props that match the schema
134
+ ```
135
+
136
+ ## Nesting Validation
137
+
138
+ Validate block nesting rules:
139
+
140
+ ```typescript
141
+ import { validateTreeNesting } from '@10up/block-renderer-validator';
142
+
143
+ const result = validateTreeNesting(tree, catalog);
144
+ if (!result.valid) {
145
+ console.log(result.errors);
146
+ // ['core/column must be inside core/columns']
147
+ }
148
+ ```
149
+
150
+ ### Individual Nesting Validators
151
+
152
+ ```typescript
153
+ import {
154
+ validateParent,
155
+ validateAncestor,
156
+ validateChildren,
157
+ validateMultiple,
158
+ } from '@10up/block-renderer-validator';
159
+
160
+ // Check if element has valid parent
161
+ validateParent(element, parentElement, blockDefinition);
162
+
163
+ // Check if element has valid ancestor chain
164
+ validateAncestor(element, ancestorChain, blockDefinition);
165
+
166
+ // Check if children are valid for this block
167
+ validateChildren(element, childElements, blockDefinition);
168
+
169
+ // Check if multiple instances are allowed
170
+ validateMultiple(elements, blockDefinition);
171
+ ```
172
+
173
+ ## Token Validation
174
+
175
+ Validate theme token references in block props:
176
+
177
+ ```typescript
178
+ import { validateTreeTokens, validateElementTokens } from '@10up/block-renderer-validator';
179
+
180
+ // Validate all tokens in a tree
181
+ const result = validateTreeTokens(tree, themeTokens);
182
+ if (!result.valid) {
183
+ console.log(result.errors);
184
+ // ['Unknown color token: invalid-color']
185
+ }
186
+
187
+ // Validate a single element's tokens
188
+ const elementResult = validateElementTokens(element, themeTokens);
189
+ ```
190
+
191
+ ### Specific Token Validators
192
+
193
+ ```typescript
194
+ import {
195
+ validateColorTokens,
196
+ validateTypographyTokens,
197
+ validateSpacingTokens,
198
+ } from '@10up/block-renderer-validator';
199
+
200
+ // Validate specific token types
201
+ validateColorTokens(props, themeTokens);
202
+ validateTypographyTokens(props, themeTokens);
203
+ validateSpacingTokens(props, themeTokens);
204
+ ```
205
+
206
+ ## Pattern Validation
207
+
208
+ Validate pattern block references:
209
+
210
+ ```typescript
211
+ import {
212
+ validatePatternReference,
213
+ validateTreePatterns,
214
+ isPatternReference,
215
+ getPatternReferences,
216
+ } from '@10up/block-renderer-validator';
217
+
218
+ // Check if an element is a pattern reference
219
+ if (isPatternReference(element)) {
220
+ const result = validatePatternReference(element, patternRegistry);
221
+ if (!result.valid) {
222
+ console.log(result.errors);
223
+ // ['Unknown pattern: theme/nonexistent-pattern']
224
+ }
225
+ }
226
+
227
+ // Validate all patterns in a tree
228
+ const treeResult = validateTreePatterns(tree, patternRegistry);
229
+
230
+ // Get all pattern references from a tree
231
+ const patternRefs = getPatternReferences(tree);
232
+ // ['theme/hero-section', 'theme/footer']
233
+ ```
234
+
235
+ ## Template Validation
236
+
237
+ Validate BlockTemplate format (PHP-style nested arrays):
238
+
239
+ ```typescript
240
+ import {
241
+ validateTemplate,
242
+ validateTemplateStructure,
243
+ validateTemplateBlockTypes,
244
+ validateTemplateNesting,
245
+ } from '@10up/block-renderer-validator';
246
+
247
+ const template = [
248
+ ['core/group', { layout: { type: 'constrained' } }, [
249
+ ['core/heading', { content: 'Title', level: 2 }],
250
+ ['core/paragraph', { content: 'Content' }],
251
+ ]],
252
+ ];
253
+
254
+ // Full template validation
255
+ const result = validateTemplate(template, {
256
+ catalog: blockCatalog,
257
+ });
258
+
259
+ if (!result.valid) {
260
+ console.log('Errors:', result.errors);
261
+ }
262
+
263
+ // Validate just structure (correct array format)
264
+ const structureResult = validateTemplateStructure(template);
265
+
266
+ // Validate block types exist
267
+ const typesResult = validateTemplateBlockTypes(template, catalog);
268
+
269
+ // Validate nesting rules
270
+ const nestingResult = validateTemplateNesting(template, catalog);
271
+ ```
272
+
273
+ ### Template Validation Options
274
+
275
+ ```typescript
276
+ interface ValidateTemplateOptions {
277
+ /** Block catalog for type and nesting validation */
278
+ catalog?: BlockCatalog;
279
+ /** Whether to validate that block types exist (default: true if catalog provided) */
280
+ validateBlockTypes?: boolean;
281
+ /** Whether to validate nesting rules (default: true if catalog provided) */
282
+ validateNesting?: boolean;
283
+ }
284
+ ```
285
+
286
+ ## Complete Exports
287
+
288
+ ### Main Functions
289
+
290
+ | Function | Description |
291
+ |----------|-------------|
292
+ | `validateTree(tree, options)` | Full tree validation with all validators |
293
+ | `createTreeValidator(options)` | Create reusable validator function |
294
+
295
+ ### Schema Validation
296
+
297
+ | Function | Description |
298
+ |----------|-------------|
299
+ | `validateBlockProps(props, schema)` | Validate props against Zod schema |
300
+ | `validateTreeSchemas(tree, catalog)` | Validate all elements in tree |
301
+ | `createBlockValidator(definition)` | Create validator for specific block |
302
+ | `getValidAttributes(props, schema)` | Filter to valid attributes only |
303
+
304
+ ### Nesting Validation
305
+
306
+ | Function | Description |
307
+ |----------|-------------|
308
+ | `validateTreeNesting(tree, catalog)` | Validate all nesting rules in tree |
309
+ | `validateParent(element, parent, def)` | Check valid parent constraint |
310
+ | `validateAncestor(element, ancestors, def)` | Check valid ancestor constraint |
311
+ | `validateChildren(element, children, def)` | Check valid children constraint |
312
+ | `validateMultiple(elements, def)` | Check multiple instance constraint |
313
+
314
+ ### Token Validation
315
+
316
+ | Function | Description |
317
+ |----------|-------------|
318
+ | `validateTreeTokens(tree, tokens)` | Validate all tokens in tree |
319
+ | `validateElementTokens(element, tokens)` | Validate single element tokens |
320
+ | `validateColorTokens(props, tokens)` | Validate color token references |
321
+ | `validateTypographyTokens(props, tokens)` | Validate typography tokens |
322
+ | `validateSpacingTokens(props, tokens)` | Validate spacing tokens |
323
+
324
+ ### Pattern Validation
325
+
326
+ | Function | Description |
327
+ |----------|-------------|
328
+ | `validateTreePatterns(tree, patterns)` | Validate all pattern refs in tree |
329
+ | `validatePatternReference(element, patterns)` | Validate single pattern ref |
330
+ | `isPatternReference(element)` | Check if element is a pattern |
331
+ | `getPatternReferences(tree)` | Get all pattern slugs from tree |
332
+
333
+ ### Template Validation
334
+
335
+ | Function | Description |
336
+ |----------|-------------|
337
+ | `validateTemplate(template, options)` | Full template validation |
338
+ | `validateTemplateStructure(template)` | Validate template array structure |
339
+ | `validateTemplateBlockTypes(template, catalog)` | Validate block types exist |
340
+ | `validateTemplateNesting(template, catalog)` | Validate nesting rules |
341
+
342
+ ### Types
343
+
344
+ | Type | Description |
345
+ |------|-------------|
346
+ | `ValidateTreeOptions` | Options for validateTree |
347
+ | `ValidateTemplateOptions` | Options for validateTemplate |
348
+ | `TemplateValidationResult` | Result from template validation |
349
+
350
+ ## License
351
+
352
+ MIT
@@ -0,0 +1,44 @@
1
+ import type { BlockTree, BlockCatalog, TreeValidationResult } from '@10up/block-renderer-core';
2
+ import type { ThemeTokens } from '@10up/block-renderer-theme-json';
3
+ import type { PatternRegistry } from '@10up/block-renderer-patterns';
4
+ export { validateBlockProps, validateTreeSchemas, createBlockValidator, getValidAttributes, } from './schema-validator.js';
5
+ export { validateParent, validateAncestor, validateChildren, validateMultiple, validateTreeNesting, } from './tree-validator.js';
6
+ export { validateColorTokens, validateTypographyTokens, validateSpacingTokens, validateElementTokens, validateTreeTokens, } from './token-validator.js';
7
+ export { isPatternReference, validatePatternReference, validateTreePatterns, getPatternReferences, } from './pattern-validator.js';
8
+ export { validateTemplateStructure, validateTemplateBlockTypes, validateTemplateNesting, validateTemplate, } from './template-validator.js';
9
+ export type { TemplateValidationResult, ValidateTemplateOptions, } from './template-validator.js';
10
+ /**
11
+ * Options for full tree validation.
12
+ */
13
+ export interface ValidateTreeOptions {
14
+ /** Block catalog for schema and nesting validation */
15
+ catalog?: BlockCatalog;
16
+ /** Theme tokens for token validation */
17
+ tokens?: ThemeTokens;
18
+ /** Pattern registry for pattern validation */
19
+ patterns?: PatternRegistry;
20
+ /** Whether to validate schemas (default: true if catalog provided) */
21
+ validateSchemas?: boolean;
22
+ /** Whether to validate nesting rules (default: true if catalog provided) */
23
+ validateNesting?: boolean;
24
+ /** Whether to validate theme tokens (default: true if tokens provided) */
25
+ validateTokens?: boolean;
26
+ /** Whether to validate pattern references (default: true if patterns provided) */
27
+ validatePatterns?: boolean;
28
+ }
29
+ /**
30
+ * Validates a complete block tree with all available validations.
31
+ *
32
+ * @param tree - The block tree to validate
33
+ * @param options - Validation options
34
+ * @returns Combined validation result
35
+ */
36
+ export declare function validateTree(tree: BlockTree, options?: ValidateTreeOptions): TreeValidationResult;
37
+ /**
38
+ * Creates a tree validator with pre-configured options.
39
+ *
40
+ * @param options - Default validation options
41
+ * @returns A validator function
42
+ */
43
+ export declare function createTreeValidator(options: ValidateTreeOptions): (tree: BlockTree) => TreeValidationResult;
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EAEZ,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAQrE,OAAO,EAEL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEL,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAEL,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,wCAAwC;IACxC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,EACf,OAAO,GAAE,mBAAwB,GAChC,oBAAoB,CA4CtB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,mBAAmB,GAC3B,CAAC,IAAI,EAAE,SAAS,KAAK,oBAAoB,CAE3C"}
package/dist/index.js ADDED
@@ -0,0 +1,77 @@
1
+ import { validateTreeSchemas } from './schema-validator.js';
2
+ import { validateTreeNesting } from './tree-validator.js';
3
+ import { validateTreeTokens } from './token-validator.js';
4
+ import { validateTreePatterns } from './pattern-validator.js';
5
+ // Re-export individual validators
6
+ export {
7
+ // Schema validation
8
+ validateBlockProps, validateTreeSchemas, createBlockValidator, getValidAttributes, } from './schema-validator.js';
9
+ export {
10
+ // Nesting validation
11
+ validateParent, validateAncestor, validateChildren, validateMultiple, validateTreeNesting, } from './tree-validator.js';
12
+ export {
13
+ // Token validation
14
+ validateColorTokens, validateTypographyTokens, validateSpacingTokens, validateElementTokens, validateTreeTokens, } from './token-validator.js';
15
+ export {
16
+ // Pattern validation
17
+ isPatternReference, validatePatternReference, validateTreePatterns, getPatternReferences, } from './pattern-validator.js';
18
+ export {
19
+ // Template validation
20
+ validateTemplateStructure, validateTemplateBlockTypes, validateTemplateNesting, validateTemplate, } from './template-validator.js';
21
+ /**
22
+ * Validates a complete block tree with all available validations.
23
+ *
24
+ * @param tree - The block tree to validate
25
+ * @param options - Validation options
26
+ * @returns Combined validation result
27
+ */
28
+ export function validateTree(tree, options = {}) {
29
+ const errors = [];
30
+ const warnings = [];
31
+ const elementResults = {};
32
+ // Schema validation
33
+ if (options.catalog && options.validateSchemas !== false) {
34
+ const schemaResult = validateTreeSchemas(tree, options.catalog);
35
+ errors.push(...schemaResult.errors);
36
+ if (schemaResult.warnings) {
37
+ warnings.push(...schemaResult.warnings);
38
+ }
39
+ }
40
+ // Nesting validation
41
+ if (options.catalog && options.validateNesting !== false) {
42
+ const nestingResult = validateTreeNesting(tree, options.catalog);
43
+ errors.push(...nestingResult.errors);
44
+ if (nestingResult.warnings) {
45
+ warnings.push(...nestingResult.warnings);
46
+ }
47
+ }
48
+ // Token validation
49
+ if (options.tokens && options.validateTokens !== false) {
50
+ const tokenResult = validateTreeTokens(tree, options.tokens);
51
+ errors.push(...tokenResult.errors);
52
+ if (tokenResult.warnings) {
53
+ warnings.push(...tokenResult.warnings);
54
+ }
55
+ }
56
+ // Pattern validation
57
+ if (options.patterns && options.validatePatterns !== false) {
58
+ const patternResult = validateTreePatterns(tree, options.patterns);
59
+ errors.push(...patternResult.errors);
60
+ }
61
+ return {
62
+ valid: errors.length === 0,
63
+ errors,
64
+ warnings: warnings.length > 0 ? warnings : undefined,
65
+ elementResults: Object.keys(elementResults).length > 0 ? elementResults : undefined,
66
+ };
67
+ }
68
+ /**
69
+ * Creates a tree validator with pre-configured options.
70
+ *
71
+ * @param options - Default validation options
72
+ * @returns A validator function
73
+ */
74
+ export function createTreeValidator(options) {
75
+ return (tree) => validateTree(tree, options);
76
+ }
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { BlockTree, BlockElement, ValidationResult } from '@10up/block-renderer-core';
2
+ import type { PatternRegistry } from '@10up/block-renderer-patterns';
3
+ /**
4
+ * Checks if a block element is a pattern reference.
5
+ */
6
+ export declare function isPatternReference(element: BlockElement): boolean;
7
+ /**
8
+ * Validates a pattern reference exists in the registry.
9
+ */
10
+ export declare function validatePatternReference(element: BlockElement, registry: PatternRegistry): ValidationResult;
11
+ /**
12
+ * Validates all pattern references in a block tree.
13
+ */
14
+ export declare function validateTreePatterns(tree: BlockTree, registry: PatternRegistry): ValidationResult;
15
+ /**
16
+ * Gets all pattern references from a block tree.
17
+ */
18
+ export declare function getPatternReferences(tree: BlockTree): string[];
19
+ //# sourceMappingURL=pattern-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-validator.d.ts","sourceRoot":"","sources":["../src/pattern-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAEjE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,eAAe,GACxB,gBAAgB,CAiBlB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,eAAe,GACxB,gBAAgB,CAYlB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,CAU9D"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Checks if a block element is a pattern reference.
3
+ */
4
+ export function isPatternReference(element) {
5
+ return element.type === 'core/pattern' && typeof element.props.slug === 'string';
6
+ }
7
+ /**
8
+ * Validates a pattern reference exists in the registry.
9
+ */
10
+ export function validatePatternReference(element, registry) {
11
+ const errors = [];
12
+ if (!isPatternReference(element)) {
13
+ return { valid: true, errors: [] };
14
+ }
15
+ const slug = element.props.slug;
16
+ if (!registry.has(slug)) {
17
+ errors.push(`[${element.key}] Unknown pattern slug "${slug}". ` +
18
+ `Available patterns: ${Array.from(registry.keys()).join(', ')}`);
19
+ }
20
+ return { valid: errors.length === 0, errors };
21
+ }
22
+ /**
23
+ * Validates all pattern references in a block tree.
24
+ */
25
+ export function validateTreePatterns(tree, registry) {
26
+ const errors = [];
27
+ for (const element of Object.values(tree.elements)) {
28
+ const result = validatePatternReference(element, registry);
29
+ if (!result.valid) {
30
+ errors.push(...result.errors);
31
+ }
32
+ }
33
+ return { valid: errors.length === 0, errors };
34
+ }
35
+ /**
36
+ * Gets all pattern references from a block tree.
37
+ */
38
+ export function getPatternReferences(tree) {
39
+ const patterns = [];
40
+ for (const element of Object.values(tree.elements)) {
41
+ if (isPatternReference(element)) {
42
+ patterns.push(element.props.slug);
43
+ }
44
+ }
45
+ return patterns;
46
+ }
47
+ //# sourceMappingURL=pattern-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-validator.js","sourceRoot":"","sources":["../src/pattern-validator.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAqB;IACtD,OAAO,OAAO,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;AACnF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAqB,EACrB,QAAyB;IAEzB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAc,CAAC;IAE1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CACT,IAAI,OAAO,CAAC,GAAG,2BAA2B,IAAI,KAAK;YACjD,uBAAuB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAe,EACf,QAAyB;IAEzB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAe;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,IAAI,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAc,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { BlockTree, BlockElement, BlockDefinition, BlockCatalog, ValidationResult } from '@10up/block-renderer-core';
2
+ /**
3
+ * Validates a block element's props against its schema.
4
+ */
5
+ export declare function validateBlockProps(element: BlockElement, definition: BlockDefinition): ValidationResult;
6
+ /**
7
+ * Validates all blocks in a tree against their schemas.
8
+ */
9
+ export declare function validateTreeSchemas(tree: BlockTree, catalog: BlockCatalog): ValidationResult;
10
+ /**
11
+ * Creates a validator function for a specific block type.
12
+ */
13
+ export declare function createBlockValidator(definition: BlockDefinition): (props: unknown) => ValidationResult;
14
+ /**
15
+ * Gets a list of valid attribute names for a block.
16
+ */
17
+ export declare function getValidAttributes(definition: BlockDefinition): string[];
18
+ //# sourceMappingURL=schema-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../src/schema-validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,eAAe,GAC1B,gBAAgB,CA8BlB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,YAAY,GACpB,gBAAgB,CA6BlB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,GAC1B,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAetC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,EAAE,CAGxE"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Validates a block element's props against its schema.
3
+ */
4
+ export function validateBlockProps(element, definition) {
5
+ const errors = [];
6
+ const warnings = [];
7
+ try {
8
+ // Validate props against the schema
9
+ const result = definition.schema.safeParse(element.props);
10
+ if (!result.success) {
11
+ // Extract error messages from Zod
12
+ for (const issue of result.error.issues) {
13
+ const path = issue.path.join('.');
14
+ errors.push(`[${element.key}] Invalid prop "${path}": ${issue.message}`);
15
+ }
16
+ }
17
+ }
18
+ catch (error) {
19
+ errors.push(`[${element.key}] Schema validation error: ${error instanceof Error ? error.message : String(error)}`);
20
+ }
21
+ return {
22
+ valid: errors.length === 0,
23
+ errors,
24
+ warnings: warnings.length > 0 ? warnings : undefined,
25
+ };
26
+ }
27
+ /**
28
+ * Validates all blocks in a tree against their schemas.
29
+ */
30
+ export function validateTreeSchemas(tree, catalog) {
31
+ const errors = [];
32
+ const warnings = [];
33
+ for (const element of Object.values(tree.elements)) {
34
+ const definition = catalog.get(element.type);
35
+ if (!definition) {
36
+ // Unknown block type - could be a 3rd party block
37
+ warnings.push(`[${element.key}] Unknown block type: ${element.type}`);
38
+ continue;
39
+ }
40
+ const result = validateBlockProps(element, definition);
41
+ if (!result.valid) {
42
+ errors.push(...result.errors);
43
+ }
44
+ if (result.warnings) {
45
+ warnings.push(...result.warnings);
46
+ }
47
+ }
48
+ return {
49
+ valid: errors.length === 0,
50
+ errors,
51
+ warnings: warnings.length > 0 ? warnings : undefined,
52
+ };
53
+ }
54
+ /**
55
+ * Creates a validator function for a specific block type.
56
+ */
57
+ export function createBlockValidator(definition) {
58
+ return (props) => {
59
+ const result = definition.schema.safeParse(props);
60
+ if (result.success) {
61
+ return { valid: true, errors: [] };
62
+ }
63
+ return {
64
+ valid: false,
65
+ errors: result.error.issues.map(issue => `Invalid prop "${issue.path.join('.')}": ${issue.message}`),
66
+ };
67
+ };
68
+ }
69
+ /**
70
+ * Gets a list of valid attribute names for a block.
71
+ */
72
+ export function getValidAttributes(definition) {
73
+ const shape = definition.schema.shape;
74
+ return Object.keys(shape);
75
+ }
76
+ //# sourceMappingURL=schema-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../src/schema-validator.ts"],"names":[],"mappings":"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"}