Skip to main content
Glama
helpers.ts5.87 kB
/** * Gutenberg Tool Helpers * * Utility functions for Gutenberg MCP tools: * - IR node building * - Path validation * - Block structure helpers * * @package WP_Navigator_Pro * @since 1.3.0 */ /** * Build IR node from block type and attributes * * Creates a properly structured IR node for Gutenberg blocks. * * @param blockType Block type (e.g., "core/heading", "core/paragraph") * @param attrs Block attributes * @param children Optional child nodes (default: empty array) * @returns IR node object */ export function buildIRNode(blockType: string, attrs: any, children: any[] = []): any { return { type: blockType, id: null, attrs: attrs, children: children, meta: { innerHTML: '', innerContent: [], }, }; } /** * Validate path array * * Ensures path is a valid array of non-negative integers. * * @param path Path array to validate * @returns True if valid, false otherwise */ export function validatePath(path: number[]): boolean { if (!Array.isArray(path)) { return false; } if (path.length === 0) { return false; } return path.every(n => Number.isInteger(n) && n >= 0); } /** * Parse IR document from API response * * Extracts IR document from REST API response, handling both * success and error cases. * * @param response API response object * @returns IR document or throws error * @throws Error if response invalid or missing ir_document */ export function parseIRDocument(response: any): any { if (!response) { throw new Error('Invalid response: response is null or undefined'); } if (response.success === false) { throw new Error(`API Error: ${response.error || 'Unknown error'}`); } if (!response.ir_document) { throw new Error('Invalid response: missing ir_document'); } return response.ir_document; } /** * Format IR document for Claude Code output * * Creates a human-readable summary of the IR document structure. * * @param ir IR document to format * @returns Formatted string */ export function formatIRSummary(ir: any): string { if (!ir || !ir.root) { return 'Empty IR document'; } const blockCount = countBlocks(ir.root.children); const blockTypes = getBlockTypes(ir.root.children); return `IR Document Summary: - Total blocks: ${blockCount} - Block types: ${blockTypes.join(', ')} - Root children: ${ir.root.children.length}`; } /** * Count total blocks in IR tree * * Recursively counts all blocks including nested children. * * @param nodes Array of IR nodes * @returns Total block count */ function countBlocks(nodes: any[]): number { let count = nodes.length; for (const node of nodes) { if (node.children && node.children.length > 0) { count += countBlocks(node.children); } } return count; } /** * Get unique block types in IR tree * * @param nodes Array of IR nodes * @returns Array of unique block types */ function getBlockTypes(nodes: any[]): string[] { const types = new Set<string>(); function collectTypes(nodeList: any[]) { for (const node of nodeList) { if (node.type) { types.add(node.type); } if (node.children && node.children.length > 0) { collectTypes(node.children); } } } collectTypes(nodes); return Array.from(types); } /** * Validate block attributes for specific block type * * Ensures required attributes are present for common block types. * * @param blockType Block type * @param attrs Attributes object * @returns True if valid, throws error otherwise * @throws Error if required attributes missing */ export function validateBlockAttributes(blockType: string, attrs: any): boolean { // Common required attributes by block type const requiredAttrs: Record<string, string[]> = { 'core/heading': ['level', 'content'], 'core/paragraph': ['content'], 'core/button': ['text', 'url'], 'core/image': ['url'], 'core/list': ['values'], }; const required = requiredAttrs[blockType]; if (!required) { // Unknown block type, allow any attributes return true; } for (const attr of required) { if (!(attr in attrs)) { throw new Error(`Missing required attribute "${attr}" for block type "${blockType}"`); } } return true; } /** * Build common block presets * * Helper functions to create commonly used blocks with proper attributes. */ export const blockPresets = { /** * Create heading block */ heading(level: number, content: string): any { if (level < 1 || level > 6) { throw new Error('Heading level must be between 1 and 6'); } return buildIRNode('core/heading', { level, content }); }, /** * Create paragraph block */ paragraph(content: string): any { return buildIRNode('core/paragraph', { content }); }, /** * Create button block */ button(text: string, url: string, linkTarget: string = '_self'): any { return buildIRNode('core/button', { text, url, linkTarget }); }, /** * Create image block */ image(url: string, alt: string = '', caption: string = ''): any { return buildIRNode('core/image', { url, alt, caption }); }, /** * Create columns container with specified number of columns */ columns(columnCount: number): any { if (columnCount < 1 || columnCount > 6) { throw new Error('Column count must be between 1 and 6'); } const children: any[] = []; for (let i = 0; i < columnCount; i++) { children.push(buildIRNode('core/column', {})); } return buildIRNode('core/columns', { columns: columnCount }, children); }, /** * Create separator block */ separator(): any { return buildIRNode('core/separator', {}); }, /** * Create spacer block */ spacer(height: number = 20): any { return buildIRNode('core/spacer', { height }); }, };

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/littlebearapps/wp-navigator-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server