Validation for WordPress block trees - schema, nesting, and token validation
npm install @10up/block-renderer-validatorValidate JSON block trees against schemas, nesting rules, and theme tokens. This package ensures block trees are valid before rendering.
``bash`
npm install @10up/block-renderer-validatoror
pnpm add @10up/block-renderer-validator
This package provides comprehensive validation for block trees:
1. Schema Validation - Validates block props against Zod schemas from block definitions
2. Nesting Validation - Checks parent/ancestor/allowedBlocks constraints
3. Token Validation - Verifies theme token references (colors, spacing, etc.)
4. Pattern Validation - Confirms pattern slugs exist in the registry
The main entry point - validates a tree with all available validators:
`typescript
import { validateTree } from '@10up/block-renderer-validator';
const tree = {
root: 'para-1',
elements: {
'para-1': {
key: 'para-1',
type: 'core/paragraph',
props: {
content: 'Hello',
style: { color: { background: 'var:preset|color|primary' } }
}
}
}
};
const result = validateTree(tree, {
catalog: blockCatalog, // Block definitions for schema/nesting
tokens: themeTokens, // Theme tokens for color/spacing validation
patterns: patternRegistry // Pattern definitions
});
if (result.valid) {
console.log('Tree is valid');
} else {
console.log('Errors:', result.errors);
// ['Unknown color token: primary', 'Invalid block type: core/unknown']
}
`
`typescript`
interface ValidateTreeOptions {
/* Block catalog for schema and nesting validation /
catalog?: BlockCatalog;
/* Theme tokens for token validation /
tokens?: ThemeTokens;
/* Pattern registry for pattern validation /
patterns?: PatternRegistry;
/* Whether to validate schemas (default: true if catalog provided) /
validateSchemas?: boolean;
/* Whether to validate nesting rules (default: true if catalog provided) /
validateNesting?: boolean;
/* Whether to validate theme tokens (default: true if tokens provided) /
validateTokens?: boolean;
/* Whether to validate pattern references (default: true if patterns provided) /
validatePatterns?: boolean;
}
`typescript
import { createTreeValidator } from '@10up/block-renderer-validator';
const validator = createTreeValidator({
catalog: blockCatalog,
tokens: themeTokens,
patterns: patternRegistry,
});
// Use the pre-configured validator
const result1 = validator(tree1);
const result2 = validator(tree2);
`
Validate block props against their Zod schemas:
`typescript
import { validateBlockProps, validateTreeSchemas } from '@10up/block-renderer-validator';
// Validate a single element's props
const result = validateBlockProps(element.props, blockDefinition.schema);
if (!result.valid) {
console.log(result.errors);
// ['content: Expected string, received number']
}
// Validate all elements in a tree
const treeResult = validateTreeSchemas(tree, catalog);
`
Create a validator for a specific block:
`typescript
import { createBlockValidator } from '@10up/block-renderer-validator';
const validateParagraph = createBlockValidator(paragraphDefinition);
const result = validateParagraph({ content: 'Hello', dropCap: true });
`
Filter props to only include valid attributes:
`typescript
import { getValidAttributes } from '@10up/block-renderer-validator';
const cleanProps = getValidAttributes(props, blockDefinition.schema);
// Returns only props that match the schema
`
Validate block nesting rules:
`typescript
import { validateTreeNesting } from '@10up/block-renderer-validator';
const result = validateTreeNesting(tree, catalog);
if (!result.valid) {
console.log(result.errors);
// ['core/column must be inside core/columns']
}
`
`typescript
import {
validateParent,
validateAncestor,
validateChildren,
validateMultiple,
} from '@10up/block-renderer-validator';
// Check if element has valid parent
validateParent(element, parentElement, blockDefinition);
// Check if element has valid ancestor chain
validateAncestor(element, ancestorChain, blockDefinition);
// Check if children are valid for this block
validateChildren(element, childElements, blockDefinition);
// Check if multiple instances are allowed
validateMultiple(elements, blockDefinition);
`
Validate theme token references in block props:
`typescript
import { validateTreeTokens, validateElementTokens } from '@10up/block-renderer-validator';
// Validate all tokens in a tree
const result = validateTreeTokens(tree, themeTokens);
if (!result.valid) {
console.log(result.errors);
// ['Unknown color token: invalid-color']
}
// Validate a single element's tokens
const elementResult = validateElementTokens(element, themeTokens);
`
`typescript
import {
validateColorTokens,
validateTypographyTokens,
validateSpacingTokens,
} from '@10up/block-renderer-validator';
// Validate specific token types
validateColorTokens(props, themeTokens);
validateTypographyTokens(props, themeTokens);
validateSpacingTokens(props, themeTokens);
`
Validate pattern block references:
`typescript
import {
validatePatternReference,
validateTreePatterns,
isPatternReference,
getPatternReferences,
} from '@10up/block-renderer-validator';
// Check if an element is a pattern reference
if (isPatternReference(element)) {
const result = validatePatternReference(element, patternRegistry);
if (!result.valid) {
console.log(result.errors);
// ['Unknown pattern: theme/nonexistent-pattern']
}
}
// Validate all patterns in a tree
const treeResult = validateTreePatterns(tree, patternRegistry);
// Get all pattern references from a tree
const patternRefs = getPatternReferences(tree);
// ['theme/hero-section', 'theme/footer']
`
Validate BlockTemplate format (PHP-style nested arrays):
`typescript
import {
validateTemplate,
validateTemplateStructure,
validateTemplateBlockTypes,
validateTemplateNesting,
} from '@10up/block-renderer-validator';
const template = [
['core/group', { layout: { type: 'constrained' } }, [
['core/heading', { content: 'Title', level: 2 }],
['core/paragraph', { content: 'Content' }],
]],
];
// Full template validation
const result = validateTemplate(template, {
catalog: blockCatalog,
});
if (!result.valid) {
console.log('Errors:', result.errors);
}
// Validate just structure (correct array format)
const structureResult = validateTemplateStructure(template);
// Validate block types exist
const typesResult = validateTemplateBlockTypes(template, catalog);
// Validate nesting rules
const nestingResult = validateTemplateNesting(template, catalog);
`
`typescript`
interface ValidateTemplateOptions {
/* Block catalog for type and nesting validation /
catalog?: BlockCatalog;
/* Whether to validate that block types exist (default: true if catalog provided) /
validateBlockTypes?: boolean;
/* Whether to validate nesting rules (default: true if catalog provided) /
validateNesting?: boolean;
}
| Function | Description |
|----------|-------------|
| validateTree(tree, options) | Full tree validation with all validators |createTreeValidator(options)
| | Create reusable validator function |
| Function | Description |
|----------|-------------|
| validateBlockProps(props, schema) | Validate props against Zod schema |validateTreeSchemas(tree, catalog)
| | Validate all elements in tree |createBlockValidator(definition)
| | Create validator for specific block |getValidAttributes(props, schema)
| | Filter to valid attributes only |
| Function | Description |
|----------|-------------|
| validateTreeNesting(tree, catalog) | Validate all nesting rules in tree |validateParent(element, parent, def)
| | Check valid parent constraint |validateAncestor(element, ancestors, def)
| | Check valid ancestor constraint |validateChildren(element, children, def)
| | Check valid children constraint |validateMultiple(elements, def)
| | Check multiple instance constraint |
| Function | Description |
|----------|-------------|
| validateTreeTokens(tree, tokens) | Validate all tokens in tree |validateElementTokens(element, tokens)
| | Validate single element tokens |validateColorTokens(props, tokens)
| | Validate color token references |validateTypographyTokens(props, tokens)
| | Validate typography tokens |validateSpacingTokens(props, tokens)
| | Validate spacing tokens |
| Function | Description |
|----------|-------------|
| validateTreePatterns(tree, patterns) | Validate all pattern refs in tree |validatePatternReference(element, patterns)
| | Validate single pattern ref |isPatternReference(element)
| | Check if element is a pattern |getPatternReferences(tree)
| | Get all pattern slugs from tree |
| Function | Description |
|----------|-------------|
| validateTemplate(template, options) | Full template validation |validateTemplateStructure(template)
| | Validate template array structure |validateTemplateBlockTypes(template, catalog)
| | Validate block types exist |validateTemplateNesting(template, catalog)
| | Validate nesting rules |
| Type | Description |
|------|-------------|
| ValidateTreeOptions | Options for validateTree |ValidateTemplateOptions
| | Options for validateTemplate |TemplateValidationResult` | Result from template validation |
|
MIT