@json-to-office/shared-docx 1.1.0 → 1.3.0
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/dist/{chunk-TODYYVZ4.js → chunk-5NLKSIS2.js} +2 -2
- package/dist/{chunk-6HFF6XZN.js → chunk-AH7DXSUV.js} +5 -5
- package/dist/chunk-AH7DXSUV.js.map +1 -0
- package/dist/{chunk-5KOKA5GY.js → chunk-EG5UTHFZ.js} +8 -1
- package/dist/{chunk-5KOKA5GY.js.map → chunk-EG5UTHFZ.js.map} +1 -1
- package/dist/{chunk-6B3LHADB.js → chunk-M4F3PWQR.js} +2 -2
- package/dist/chunk-M4F3PWQR.js.map +1 -0
- package/dist/{chunk-A2K66URO.js → chunk-MMD4A5LR.js} +157 -20
- package/dist/chunk-MMD4A5LR.js.map +1 -0
- package/dist/{chunk-BBFR3RRN.js → chunk-NT236J7G.js} +3 -3
- package/dist/{chunk-MYLVUQCN.js → chunk-P4FD5B7U.js} +2 -2
- package/dist/{chunk-LBXOAXMG.js → chunk-XEB3SHFQ.js} +4 -4
- package/dist/{chunk-6YMJWMEC.js → chunk-Z4L6TH5Y.js} +4 -4
- package/dist/chunk-Z4L6TH5Y.js.map +1 -0
- package/dist/index.d.ts +18 -5
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/schemas/api.js +4 -4
- package/dist/schemas/component-registry.d.ts +9 -0
- package/dist/schemas/component-registry.js +2 -2
- package/dist/schemas/components.d.ts +801 -57
- package/dist/schemas/components.js +5 -3
- package/dist/schemas/document.js +5 -5
- package/dist/schemas/export.js +3 -3
- package/dist/schemas/generator.js +3 -3
- package/dist/schemas/renderer.js +1 -1
- package/dist/validation/unified/index.js +5 -5
- package/package.json +2 -2
- package/dist/chunk-6B3LHADB.js.map +0 -1
- package/dist/chunk-6HFF6XZN.js.map +0 -1
- package/dist/chunk-6YMJWMEC.js.map +0 -1
- package/dist/chunk-A2K66URO.js.map +0 -1
- /package/dist/{chunk-TODYYVZ4.js.map → chunk-5NLKSIS2.js.map} +0 -0
- /package/dist/{chunk-BBFR3RRN.js.map → chunk-NT236J7G.js.map} +0 -0
- /package/dist/{chunk-MYLVUQCN.js.map → chunk-P4FD5B7U.js.map} +0 -0
- /package/dist/{chunk-LBXOAXMG.js.map → chunk-XEB3SHFQ.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ComponentDefinitionSchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-M4F3PWQR.js";
|
|
4
4
|
|
|
5
5
|
// src/schemas/api.ts
|
|
6
6
|
import { Type } from "@sinclair/typebox";
|
|
@@ -105,4 +105,4 @@ export {
|
|
|
105
105
|
GenerateDocumentResponseSchema,
|
|
106
106
|
ValidateDocumentResponseSchema
|
|
107
107
|
};
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-5NLKSIS2.js.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ComponentDefinitionSchema,
|
|
3
3
|
StandardComponentDefinitionSchema
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-M4F3PWQR.js";
|
|
5
5
|
import {
|
|
6
6
|
CustomComponentDefinitionSchema
|
|
7
7
|
} from "./chunk-7GGTZ4TA.js";
|
|
8
8
|
import {
|
|
9
9
|
ReportPropsSchema,
|
|
10
10
|
STANDARD_COMPONENTS_REGISTRY
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-MMD4A5LR.js";
|
|
12
12
|
import {
|
|
13
13
|
collectDocxRendererErrors
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-EG5UTHFZ.js";
|
|
15
15
|
|
|
16
16
|
// src/validation/unified/error-transformer.ts
|
|
17
17
|
import {
|
|
@@ -510,7 +510,7 @@ function walkComponentTree(node, path, opts, errors) {
|
|
|
510
510
|
return;
|
|
511
511
|
}
|
|
512
512
|
if (opts.knownCustomNames?.has(child.name)) return;
|
|
513
|
-
if (
|
|
513
|
+
if ("props" in child) {
|
|
514
514
|
errors.push(
|
|
515
515
|
...validateComponentProps(
|
|
516
516
|
child.name,
|
|
@@ -996,4 +996,4 @@ export {
|
|
|
996
996
|
validateJsonComponent,
|
|
997
997
|
validateDocumentWithSchema
|
|
998
998
|
};
|
|
999
|
-
//# sourceMappingURL=chunk-
|
|
999
|
+
//# sourceMappingURL=chunk-AH7DXSUV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/validation/unified/error-transformer.ts","../src/validation/unified/deep-validator.ts","../src/validation/unified/base-validator.ts","../src/validation/unified/document-validator.ts"],"sourcesContent":["/**\n * Unified error transformation utilities\n * Converts TypeBox ValueError objects to standardized ValidationError format\n */\n\nimport type { ValueError } from '@sinclair/typebox/value';\nimport type { ValidationError } from '@json-to-office/shared';\nimport { ReportPropsSchema } from '../../schemas/components/report';\nimport {\n isObjectSchema,\n getObjectSchemaPropertyNames,\n getLiteralValue,\n type ErrorFormatterConfig,\n createErrorConfig,\n formatErrorMessage,\n ERROR_EMOJIS,\n} from '@json-to-office/shared';\n\n/**\n * Generate enhanced error message based on error type and context\n */\nfunction generateEnhancedMessage(\n error: ValueError,\n _config: Required<ErrorFormatterConfig>\n): string {\n const typeStr = String(error.type || '');\n const path = error.path || 'root';\n\n // Handle union errors specially - these are the most common and least helpful\n if (typeStr === '62' || typeStr === 'union') {\n return generateUnionErrorMessage(error);\n }\n\n // Handle additional properties error\n if (error.message?.includes('additionalProperties')) {\n return generateAdditionalPropertiesMessage(error);\n }\n\n // Handle missing required properties\n if (error.message?.includes('Required property')) {\n return generateRequiredPropertyMessage(error);\n }\n\n // Handle type mismatches\n if (\n typeStr === 'string' ||\n typeStr === 'number' ||\n typeStr === 'boolean' ||\n typeStr === 'array' ||\n typeStr === 'object'\n ) {\n return generateTypeMismatchMessage(error);\n }\n\n // Handle literal value errors\n if (typeStr === 'literal') {\n return generateLiteralErrorMessage(error);\n }\n\n // Handle pattern/regex errors\n if (typeStr === 'pattern' || typeStr === 'RegExp') {\n return generatePatternErrorMessage(error);\n }\n\n // Default to original message with some context\n return `At ${path}: ${error.message}`;\n}\n\n/**\n * Generate message for union validation errors\n */\nfunction generateUnionErrorMessage(error: ValueError): string {\n const path = error.path || 'root';\n const value = error.value;\n\n // Try to determine what the user was attempting\n if (path === 'root' || path === '/' || path === '/jsonDefinition') {\n // Root level or jsonDefinition union error - likely a document type issue\n if (value && typeof value === 'object') {\n if ('name' in value) {\n const name = value.name;\n if (name === 'docx') {\n return 'Document structure appears valid but contains invalid component configurations. Check each component for errors.';\n }\n return `Unknown document name '${name}'. Expected 'docx'.`;\n }\n\n // Missing name field\n const valueAny = value as Record<string, unknown>;\n if ('children' in value && Array.isArray(valueAny.children)) {\n return 'Document is missing required \\'name\\' field. Add \"name\": \"docx\" at the root level.';\n }\n\n // Check if it might be a theme\n if ('name' in value || 'styles' in value) {\n return 'This appears to be a theme configuration. Use --type theme or ensure proper document structure.';\n }\n }\n return 'Invalid document structure. Expected a document with name=\"docx\" or a theme configuration.';\n }\n\n // Component-level union error\n if (path.includes('/children/')) {\n if (value && typeof value === 'object' && 'name' in value) {\n const componentType = (value as any).name;\n return `Invalid component configuration for type '${componentType}'. Check that all required fields are present and correctly formatted.`;\n }\n return 'Invalid component structure. Each component must have a \"name\" field and valid configuration.';\n }\n\n // Default union error message\n return `Value at ${path} doesn't match any of the expected formats. Check the structure and required fields.`;\n}\n\n/**\n * Generate message for additional properties errors\n */\nfunction generateAdditionalPropertiesMessage(error: ValueError): string {\n const path = error.path || 'root';\n const value = error.value;\n\n if (typeof value === 'object' && value !== null) {\n // Try to identify the unknown properties\n const schema = error.schema;\n if (schema && isObjectSchema(schema)) {\n const knownProps = getObjectSchemaPropertyNames(schema);\n const actualProps = Object.keys(value);\n const unknownProps = actualProps.filter((p) => !knownProps.includes(p));\n\n if (unknownProps.length > 0) {\n return (\n `Unknown properties at ${path}: ${unknownProps.join(', ')}. ` +\n `Allowed properties are: ${knownProps.join(', ')}`\n );\n }\n }\n }\n\n return `Additional properties not allowed at ${path}. Check for typos or unsupported fields.`;\n}\n\n/**\n * Generate message for required property errors\n */\nfunction generateRequiredPropertyMessage(error: ValueError): string {\n const path = error.path || 'root';\n const match = error.message?.match(/Required property '([^']+)'/);\n\n if (match) {\n const propName = match[1];\n return `Missing required field '${propName}' at ${path}. This field is mandatory for this configuration.`;\n }\n\n return `Missing required property at ${path}. Check that all mandatory fields are present.`;\n}\n\n/**\n * Generate message for type mismatch errors\n */\nfunction generateTypeMismatchMessage(error: ValueError): string {\n const path = error.path || 'root';\n const expectedType = String(error.type);\n const actualType = Array.isArray(error.value) ? 'array' : typeof error.value;\n\n // Provide context-specific messages\n if (path.includes('alignment')) {\n return `Invalid alignment value at ${path}. Expected one of: left, center, right, justify`;\n }\n\n if (path.includes('color')) {\n return `Invalid color value at ${path}. Use hex format (#RRGGBB), rgb(r,g,b), or a named color`;\n }\n\n if (path.includes('fontSize') || path.includes('size')) {\n return `Invalid size value at ${path}. Expected a number (in points)`;\n }\n\n if (\n path.includes('margin') ||\n path.includes('padding') ||\n path.includes('spacing')\n ) {\n return `Invalid spacing value at ${path}. Expected a number or spacing object with top/bottom/left/right`;\n }\n\n return `Type mismatch at ${path}: Expected ${expectedType} but got ${actualType}`;\n}\n\n/**\n * Generate message for literal value errors\n */\nfunction generateLiteralErrorMessage(error: ValueError): string {\n const path = error.path || 'root';\n const expected = error.schema\n ? JSON.stringify(getLiteralValue(error.schema))\n : 'specific value';\n const actual = JSON.stringify(error.value);\n\n return `Invalid value at ${path}: Expected exactly ${expected} but got ${actual}`;\n}\n\n/**\n * Generate message for pattern/regex errors\n */\nfunction generatePatternErrorMessage(error: ValueError): string {\n const path = error.path || 'root';\n\n // Try to provide helpful context based on the path\n if (path.includes('email')) {\n return `Invalid email format at ${path}. Use format: user@example.com`;\n }\n\n if (path.includes('url') || path.includes('link')) {\n return `Invalid URL format at ${path}. Use format: https://example.com`;\n }\n\n if (path.includes('date')) {\n return `Invalid date format at ${path}. Use ISO format: YYYY-MM-DD`;\n }\n\n if (path.includes('phone')) {\n return `Invalid phone number format at ${path}`;\n }\n\n return `Value at ${path} doesn't match the required pattern`;\n}\n\n/**\n * Transform TypeBox ValueError to standardized ValidationError\n */\nexport function transformValueError(\n error: ValueError,\n jsonString?: string,\n config?: ErrorFormatterConfig\n): ValidationError {\n const formatterConfig = createErrorConfig(config);\n\n // Generate enhanced message based on error type\n const enhancedMessage = generateEnhancedMessage(error, formatterConfig);\n\n const baseError: ValidationError = {\n path: error.path || 'root',\n message: formatErrorMessage(\n enhancedMessage || error.message,\n formatterConfig\n ),\n code: String(error.type || 'validation_error'),\n value: error.value,\n };\n\n // Add suggestion if available and configured\n if (formatterConfig.includeSuggestions) {\n const suggestion = getSuggestion(error, formatterConfig);\n if (suggestion) {\n baseError.suggestion = formatErrorMessage(suggestion, formatterConfig);\n }\n }\n\n // Calculate line and column if JSON string is provided\n if (jsonString && error.path) {\n const position = calculatePosition(jsonString, error.path);\n if (position) {\n baseError.line = position.line;\n baseError.column = position.column;\n }\n }\n\n return baseError;\n}\n\n/**\n * Transform multiple TypeBox errors to ValidationError array\n * Enhanced to collect ALL errors, not just stopping at union failures\n */\nexport function transformValueErrors(\n errors: ValueError[],\n options?: {\n jsonString?: string;\n maxErrors?: number;\n }\n): ValidationError[] {\n const maxErrors = options?.maxErrors ?? Number.MAX_SAFE_INTEGER;\n const result: ValidationError[] = [];\n const seenPaths = new Set<string>();\n\n // Collect all errors, but avoid duplicates at the same path\n for (const error of errors) {\n if (result.length >= maxErrors) break;\n\n // Create a unique key for this error based on path and type\n const errorKey = `${error.path}:${error.type}`;\n\n // Skip if we've already seen an error at this exact path and type\n // This helps avoid duplicate union errors while still showing all unique issues\n if (!seenPaths.has(errorKey)) {\n seenPaths.add(errorKey);\n result.push(transformValueError(error, options?.jsonString, undefined));\n }\n }\n\n return result;\n}\n\n/**\n * Calculate line and column position in JSON string\n */\nexport function calculatePosition(\n jsonString: string,\n path: string\n): { line: number; column: number } | null {\n try {\n // Convert path like \"/children/0/props/title\" to searchable parts\n const pathParts = path.split('/').filter(Boolean);\n if (pathParts.length === 0) {\n return { line: 1, column: 1 };\n }\n\n // Try to find the last part of the path in the JSON\n const lastPart = pathParts[pathParts.length - 1];\n const searchPattern = `\"${lastPart}\"`;\n const index = jsonString.indexOf(searchPattern);\n\n if (index === -1) {\n // Try to find just the value if it's a property name\n return { line: 1, column: 1 };\n }\n\n // Calculate line and column from index\n const beforeError = jsonString.substring(0, index);\n const lines = beforeError.split('\\n');\n const line = lines.length;\n const column = lines[lines.length - 1].length + 1;\n\n return { line, column };\n } catch {\n return null;\n }\n}\n\n/**\n * Get helpful suggestion based on error type and context\n */\nfunction getSuggestion(\n error: ValueError,\n config: Required<ErrorFormatterConfig>\n): string | undefined {\n const { type, path, value } = error;\n const typeStr = String(type);\n\n // Enhanced suggestions for union errors\n if (typeStr === '62' || typeStr === 'union') {\n if (path === 'root' || path === '/') {\n if (value && typeof value === 'object') {\n if (!('name' in value)) {\n const msg = 'Add a \"name\" field with value \"docx\" for documents';\n return config.includeEmojis ? `${ERROR_EMOJIS.FIX} ${msg}` : msg;\n }\n if ('props' in value && typeof value.props === 'object') {\n const knownFields = getObjectSchemaPropertyNames(ReportPropsSchema);\n return `Review the props section for unsupported fields. Allowed fields: ${knownFields.join(', ')}`;\n }\n }\n return 'Ensure the document has proper structure: { \"name\": \"docx\", \"props\": {...}, \"children\": [...] }';\n }\n if (path?.includes('/children/')) {\n return 'Check that the component has a valid \"name\" and all required fields for that component type';\n }\n return 'Review the structure and ensure all required fields are present with correct types';\n }\n\n // Suggestions for additional properties errors\n if (error.message?.includes('additionalProperties')) {\n return 'Remove any unknown or unsupported fields. Check documentation for allowed properties.';\n }\n\n // Suggestions for required properties\n if (error.message?.includes('Required property')) {\n return 'Add the missing required field to fix this error';\n }\n\n // Type-specific suggestions\n if (typeStr === 'string') {\n if (path?.includes('alignment')) {\n return 'Use one of: left, center, right, justify';\n }\n if (path?.includes('color')) {\n return 'Use a valid color format (hex: #RRGGBB, rgb: rgb(r,g,b), or named color)';\n }\n return 'Provide a text string value';\n }\n\n if (typeStr === 'number') {\n if (path?.includes('fontSize') || path?.includes('size')) {\n return 'Use a number in points (e.g., 12, 14, 16)';\n }\n if (path?.includes('margin') || path?.includes('padding')) {\n return 'Use a number for spacing in points';\n }\n return 'Provide a numeric value';\n }\n\n if (typeStr === 'boolean') {\n return 'Use true or false (without quotes)';\n }\n\n if (typeStr === 'array') {\n if (path?.includes('children')) {\n return 'Provide an array of component objects, each with a \"name\" field';\n }\n return 'Provide an array/list of values using square brackets []';\n }\n\n if (typeStr === 'object') {\n return 'Provide an object with key-value pairs using curly braces {}';\n }\n\n if (typeStr === 'literal') {\n const expected = error.schema\n ? JSON.stringify(getLiteralValue(error.schema))\n : 'specific value';\n return `Use exactly this value: ${expected}`;\n }\n\n if (typeStr === 'pattern' || typeStr === 'RegExp') {\n if (path?.includes('email')) {\n return 'Use valid email format: user@example.com';\n }\n if (path?.includes('url')) {\n return 'Use valid URL format: https://example.com';\n }\n if (path?.includes('date')) {\n return 'Use ISO date format: YYYY-MM-DD';\n }\n return 'Ensure the value matches the required format';\n }\n\n // Path-based suggestions\n if (path?.includes('name') || path?.includes('type')) {\n return 'Use a valid component name: docx, section, columns, heading, paragraph, image, statistic, table, list, toc, text-box, highcharts, or visual';\n }\n\n return undefined;\n}\n\n/**\n * Format validation errors as a summary string\n */\nexport function formatErrorSummary(errors: ValidationError[]): string {\n if (errors.length === 0) return 'No errors';\n\n if (errors.length === 1) {\n return errors[0].message;\n }\n\n const summary = errors\n .slice(0, 3)\n .map((e) => `${e.path}: ${e.message}`)\n .join(', ');\n\n if (errors.length > 3) {\n return `${summary} and ${errors.length - 3} more...`;\n }\n\n return summary;\n}\n\n/**\n * Group errors by path for better reporting\n */\nexport function groupErrorsByPath(\n errors: ValidationError[]\n): Map<string, ValidationError[]> {\n const grouped = new Map<string, ValidationError[]>();\n\n for (const error of errors) {\n const path = error.path || 'root';\n const group = grouped.get(path) || [];\n group.push(error);\n grouped.set(path, group);\n }\n\n return grouped;\n}\n\n/**\n * Create a JSON parse error\n */\nexport function createJsonParseError(\n error: Error,\n jsonString: string\n): ValidationError {\n // Try to extract position from error message\n const match = error.message.match(/position (\\d+)/);\n const position = match ? parseInt(match[1], 10) : 0;\n\n let line = 1;\n let column = 1;\n\n if (position > 0) {\n const lines = jsonString.substring(0, position).split('\\n');\n line = lines.length;\n column = lines[lines.length - 1].length + 1;\n }\n\n return {\n path: 'root',\n message: `JSON Parse Error: ${error.message}`,\n code: 'json_parse_error',\n line,\n column,\n suggestion: 'Check for missing commas, quotes, or brackets',\n };\n}\n","/**\n * Deep validation utilities for collecting ALL errors in nested structures\n * This bypasses TypeBox's union short-circuiting to provide comprehensive error reporting\n */\n\nimport { Value } from '@sinclair/typebox/value';\nimport type { TSchema } from '@sinclair/typebox';\nimport type { ValidationError } from '@json-to-office/shared';\nimport { STANDARD_COMPONENTS_REGISTRY } from '../../schemas/component-registry';\nimport { CustomComponentDefinitionSchema } from '../../schemas/custom-components';\nimport { transformValueErrors } from './error-transformer';\n\n// Map of component names to their props schemas, sourced from the registry.\n// This stays in sync as new standard components are added, so the document\n// root ('docx') and every standard child component are recognized here.\nconst COMPONENT_SCHEMAS: Record<string, TSchema> = Object.fromEntries([\n ...STANDARD_COMPONENTS_REGISTRY.map((c) => [c.name, c.propsSchema]),\n ['custom', CustomComponentDefinitionSchema],\n]);\n\n// Root component names that may appear at the top of a document.\nconst ROOT_COMPONENT_NAMES = new Set(\n STANDARD_COMPONENTS_REGISTRY.filter((c) =>\n Boolean(c.special?.hasSchemaField)\n ).map((c) => c.name)\n);\n\n/**\n * Options that tune deep validation.\n *\n * `knownCustomNames` — names of registered plugin components. The deep\n * validator neither flags these as \"unknown component\" nor validates their\n * props here; the plugin layer validates custom props version-aware separately.\n *\n * `allowUnknownFields` — when true, unknown properties are stripped before the\n * per-component check instead of being rejected. The escape hatch for callers\n * migrating onto strict schemas.\n */\nexport interface DeepValidateOptions {\n knownCustomNames?: Set<string>;\n allowUnknownFields?: boolean;\n}\n\n// Image source fields that are mutually exclusive: exactly one may be set.\nconst IMAGE_SOURCE_FIELDS = ['path', 'base64', 'svg'] as const;\n\n/**\n * Names of the image source fields that carry a non-empty value on a props object.\n */\nexport function presentImageSources(props: unknown): string[] {\n if (!props || typeof props !== 'object') return [];\n const p = props as Record<string, unknown>;\n return IMAGE_SOURCE_FIELDS.filter((f) => {\n const v = p[f];\n return typeof v === 'string' && v.trim().length > 0;\n });\n}\n\n/**\n * Collect \"more than one image source\" conflicts anywhere in a document.\n *\n * `path`, `base64`, and `svg` are mutually exclusive on the image component, but\n * all three are optional fields on a single object schema — so a multi-source\n * payload passes TypeBox's structural check and would otherwise be silently\n * resolved by runtime precedence (svg > base64 > path). This walk runs\n * unconditionally and rejects such payloads. It traverses every nested value, so\n * images inside columns, table cells, text boxes, headers/footers, and sections\n * are all covered regardless of container shape.\n */\nexport function collectImageSourceConflicts(data: unknown): ValidationError[] {\n const errors: ValidationError[] = [];\n\n const visit = (node: any, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, i) => visit(item, `${path}/${i}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n\n if (node.name === 'image') {\n const present = presentImageSources(node.props);\n if (present.length > 1) {\n errors.push({\n path: `${path}/props`,\n message: `Image component accepts only one source, but found ${present\n .map((f) => `\"${f}\"`)\n .join(', ')}. Use exactly one of \"path\", \"base64\", or \"svg\".`,\n code: 'mutually_exclusive',\n });\n }\n }\n\n for (const key of Object.keys(node)) {\n visit(node[key], `${path}/${key}`);\n }\n };\n\n visit(data, '');\n return errors;\n}\n\n// Components that accept a paragraph-style `indent` prop with the mutually\n// exclusive hanging/firstLine pair.\nconst INDENT_COMPONENT_NAMES = new Set(['paragraph', 'heading']);\n\n/**\n * Collect \"hanging and firstLine both set\" indent conflicts anywhere in a\n * document.\n *\n * `hanging` and `firstLine` are mutually exclusive on `props.indent` (they both\n * map to the same w:ind axis — Word keeps only one), but each is an optional\n * field on a single object schema, so a payload carrying both passes TypeBox's\n * structural check. Like the image-source walk above, this runs unconditionally\n * and traverses every nested value, so paragraphs inside columns, table cells,\n * text boxes, headers/footers, and sections are all covered.\n */\nexport function collectIndentConflicts(data: unknown): ValidationError[] {\n const errors: ValidationError[] = [];\n\n const visit = (node: any, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, i) => visit(item, `${path}/${i}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n\n if (INDENT_COMPONENT_NAMES.has(node.name)) {\n const indent = node.props?.indent;\n if (\n indent &&\n typeof indent === 'object' &&\n indent.hanging !== undefined &&\n indent.firstLine !== undefined\n ) {\n errors.push({\n path: `${path}/props/indent`,\n message:\n 'Indent accepts either \"hanging\" or \"firstLine\", not both. Use exactly one of the two.',\n code: 'mutually_exclusive',\n });\n }\n }\n\n for (const key of Object.keys(node)) {\n visit(node[key], `${path}/${key}`);\n }\n };\n\n visit(data, '');\n return errors;\n}\n\n/**\n * Collect \"notes declared on a revised paragraph\" conflicts anywhere in a\n * document.\n *\n * `revision` renders a paragraph's text from its segments as literal runs, so a\n * `[^id]` marker inside them never resolves and the declared note body is never\n * written. The combination is not expressible either: `InsertedTextRun` and\n * `DeletedTextRun` wrap exactly one `TextRun` built from their own options, so\n * `docx` offers no way to put a footnote reference inside `w:ins` / `w:del`\n * without reaching past its public API.\n *\n * Each half is an independent optional field, so a payload carrying both passes\n * TypeBox's structural check. Like the image-source and indent walks above,\n * this runs unconditionally and traverses every nested value, so paragraphs\n * inside columns, table cells, text boxes, headers/footers and sections are all\n * covered.\n */\nexport function collectNoteRevisionConflicts(data: unknown): ValidationError[] {\n const errors: ValidationError[] = [];\n\n const visit = (node: any, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, i) => visit(item, `${path}/${i}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n\n // A paragraph revised directly, or a table cell whose own revision drives\n // the runs of the paragraph inside it — both render the text from segments,\n // so neither can resolve a marker.\n const revisedNotes: { notes: unknown; path: string }[] = [];\n if (node.name === 'paragraph' && node.props?.revision) {\n for (const kind of ['footnotes', 'endnotes'] as const) {\n revisedNotes.push({\n notes: node.props[kind],\n path: `${path}/props/${kind}`,\n });\n }\n }\n if (node.revision && node.content?.name === 'paragraph') {\n for (const kind of ['footnotes', 'endnotes'] as const) {\n revisedNotes.push({\n notes: node.content.props?.[kind],\n path: `${path}/content/props/${kind}`,\n });\n }\n }\n\n for (const { notes, path: notesPath } of revisedNotes) {\n if (Array.isArray(notes) && notes.length > 0) {\n const kind = notesPath.endsWith('endnotes') ? 'endnotes' : 'footnotes';\n errors.push({\n path: notesPath,\n message:\n `\"revision\" and \"${kind}\" cannot apply to the same text. Tracked-change ` +\n 'text renders literally, so note markers inside it are not resolved and the ' +\n 'note bodies would be dropped. Move the notes to text without a revision.',\n code: 'mutually_exclusive',\n });\n }\n }\n\n for (const key of Object.keys(node)) {\n visit(node[key], `${path}/${key}`);\n }\n };\n\n visit(data, '');\n return errors;\n}\n\n/**\n * Collect `text-box` requests for a shape rendering that a shape cannot honour,\n * anywhere in a document.\n *\n * `renderAs: 'shape'` emits a WPS DrawingML shape, and two of its limits are\n * decidable from the props alone:\n *\n * - **Size.** A shape carries an absolute extent and has no autofit, so a box\n * without both `width` and `height` has no size to render at.\n * - **Border style.** docx's outline options carry width, cap, compound and\n * fill but no `a:prstDash`, so a dash pattern cannot be expressed at all; the\n * `compoundLine` that could stand in for `double` is emitted as the enum key\n * (`cmpd=\"DOUBLE\"`) rather than the OOXML value.\n *\n * Both are independently optional fields, so the combination passes TypeBox's\n * structural check. Reporting them here rather than warning at render time puts\n * the fault where the author can fix it — the renderer's own guards degrade to\n * the table rendering, which is silent in an editor that only shows the result.\n *\n * Like the walks above this runs unconditionally over every nested value, so a\n * text box inside columns, a table cell, a header/footer or another text box is\n * covered too. The third render-time fallback — content that renders as a table\n * rather than a paragraph — is deliberately absent: it depends on what the\n * children render to, which no static walk can know.\n */\nconst UNDASHABLE_BORDER_STYLES = new Set(['dashed', 'dotted', 'double']);\n\nexport function collectTextBoxShapeConflicts(data: unknown): ValidationError[] {\n const errors: ValidationError[] = [];\n\n const visit = (node: any, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((item, i) => visit(item, `${path}/${i}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n\n if (node.name === 'text-box' && node.props?.renderAs === 'shape') {\n const missing = (['width', 'height'] as const).filter(\n (axis) => node.props[axis] === undefined\n );\n if (missing.length > 0) {\n errors.push({\n path: `${path}/props/${missing[0]}`,\n message:\n `A text-box with renderAs \"shape\" requires ${missing.join(' and ')}: a shape ` +\n 'has no autofit, so its size cannot be derived from its content. Give it an ' +\n 'explicit size, or use renderAs \"table\", which grows to fit.',\n code: 'required',\n });\n }\n\n const border = node.props.style?.border;\n if (border && typeof border === 'object') {\n for (const side of ['top', 'right', 'bottom', 'left'] as const) {\n const style = border[side]?.style;\n if (\n typeof style === 'string' &&\n UNDASHABLE_BORDER_STYLES.has(style)\n ) {\n errors.push({\n path: `${path}/props/style/border/${side}/style`,\n message:\n `A text-box with renderAs \"shape\" cannot draw a \"${style}\" border: a shape ` +\n 'outline carries no dash pattern. Use \"solid\", or use renderAs \"table\", ' +\n 'which draws every border style.',\n code: 'unsupported_value',\n });\n }\n }\n }\n }\n\n for (const key of Object.keys(node)) {\n visit(node[key], `${path}/${key}`);\n }\n };\n\n visit(data, '');\n return errors;\n}\n\n/**\n * Deep validate a document to collect ALL errors, not just union-level errors\n */\nexport function deepValidateDocument(\n data: any,\n opts: DeepValidateOptions = {}\n): ValidationError[] {\n const allErrors: ValidationError[] = [];\n\n // Validate the document structure\n if (!data || typeof data !== 'object') {\n allErrors.push({\n path: 'root',\n message: 'Document must be an object',\n code: 'invalid_type',\n });\n return allErrors;\n }\n\n // Check name field\n if (!data.name) {\n allErrors.push({\n path: '/name',\n message: 'Missing required field \"name\"',\n code: 'required_property',\n });\n } else if (!ROOT_COMPONENT_NAMES.has(data.name)) {\n const expected = [...ROOT_COMPONENT_NAMES].map((n) => `\"${n}\"`).join(', ');\n allErrors.push({\n path: '/name',\n message: `Invalid name \"${data.name}\". Expected ${expected}`,\n code: 'invalid_value',\n });\n }\n\n // Validate props section when the key is present so explicit `null` (or any\n // falsy non-object) is checked against the component's schema instead of\n // silently passing.\n if (ROOT_COMPONENT_NAMES.has(data.name) && 'props' in data) {\n const propsErrors = validateComponentProps(\n data.name,\n data.props,\n '/props',\n opts\n );\n allErrors.push(...propsErrors);\n }\n\n // Validate the children array. The root component requires one; nested\n // containers may legitimately omit it.\n if (!data.children) {\n allErrors.push({\n path: '/children',\n message: 'Missing required field \"children\"',\n code: 'required_property',\n });\n } else if (!Array.isArray(data.children)) {\n allErrors.push({\n path: '/children',\n message: 'Field \"children\" must be an array',\n code: 'invalid_type',\n });\n }\n\n // Deep-validate the props of every component anywhere in the tree.\n //\n // The earlier implementation only re-validated the root's direct children\n // and one level of `section` children. Two whole-tree blind spots followed:\n // 1. component props nested inside `text-box`/`columns` children — the\n // content of every container lives in the shared `children` field, so\n // anything below the first level went unchecked; and\n // 2. the `header`/`footer` paragraph regions, which the section schema\n // types loosely as an array of `Type.Any()` (or the `'linkToPrevious'`\n // literal) — so their entries' props are never checked by the\n // per-section validation.\n // The in-editor (Monaco) validator runs the generated JSON Schema over the\n // entire document, so it flags both. This walk brings the CLI to parity.\n walkComponentTree(data, '', opts, allErrors);\n\n return allErrors;\n}\n\n/**\n * Recursively validate the props of every component nested under `node`.\n *\n * Walks two kinds of child position to any depth:\n * - the `children` array — the universal container field shared by `docx`,\n * `section`, `columns` and `text-box` (added by the component registry), so\n * a bad prop inside a `text-box` or `columns` child is caught however deeply\n * it is nested; and\n * - the `header` / `footer` paragraph regions under `props` — typed only\n * loosely on the section schema (an array of `Type.Any()`, or the\n * `'linkToPrevious'` literal, which is skipped), so their entries are not\n * deep-checked by the parent's per-component validation.\n *\n * The node's own props are NOT validated here — the caller validates the root\n * props, and every entry is validated as it is visited. `table` and `list`\n * nest their components inside their own recursive props schemas, so those are\n * already covered by `validateComponentProps` and are intentionally not\n * re-walked here.\n */\nfunction walkComponentTree(\n node: any,\n path: string,\n opts: DeepValidateOptions,\n errors: ValidationError[]\n): void {\n if (!node || typeof node !== 'object') return;\n\n // `strictStructure` controls whether a malformed entry (not an object, or\n // missing `name`) is reported here. It is ON for positions the per-component\n // schema leaves unchecked — the `children` array (a sibling field, never seen\n // by props validation) and the `header`/`footer` regions (typed `Type.Any()`\n // on the static section schema) — so the walk is their only structural\n // checker and must match the whole-tree schema the editor runs. It is OFF for\n // `table` cell content, whose structure the table's own props schema already\n // validates; there the walk only adds the prop-constraint errors the loose\n // cell-content ref misses, so reporting structure too would double-report.\n const validateEntry = (\n child: any,\n childPath: string,\n strictStructure: boolean\n ): void => {\n if (!child || typeof child !== 'object') {\n if (strictStructure) {\n errors.push({\n path: childPath,\n message: 'Component must be an object',\n code: 'invalid_type',\n });\n }\n return;\n }\n if (typeof child.name !== 'string' || child.name.length === 0) {\n if (strictStructure) {\n errors.push({\n path: `${childPath}/name`,\n message: 'Component missing required field \"name\"',\n code: 'required_property',\n });\n }\n return;\n }\n\n // Registered plugin components are validated version-aware by the plugin\n // layer; skip their props and subtree so they are neither double-validated\n // nor misreported as unknown.\n if (opts.knownCustomNames?.has(child.name)) return;\n\n // Validate props against the component's schema. When props is omitted,\n // validate an empty object so the schema decides whether props are\n // required (e.g. `section` needs none; `heading` requires text+level).\n //\n // Presence is `'props' in child`, matching the root check above: an\n // explicit `null` is a value the schema rejects (props must be an object),\n // so it has to reach the schema rather than be read as an omission.\n if ('props' in child) {\n errors.push(\n ...validateComponentProps(\n child.name,\n child.props,\n `${childPath}/props`,\n opts\n )\n );\n } else if (child.name !== 'custom') {\n errors.push(\n ...validateComponentProps(child.name, {}, `${childPath}/props`, opts)\n );\n }\n\n // Recurse so arbitrarily nested containers are covered.\n walkComponentTree(child, childPath, opts, errors);\n };\n\n // header/footer entries are validated strictly: the static section schema\n // types them as `Type.Any()`, so the editor's whole-tree schema (where they\n // resolve to the component union) is stricter than the per-component check —\n // the walk closes that gap, flagging non-component entries too. A bare\n // `'linkToPrevious'` value is not an array, so it is skipped here.\n for (const region of ['header', 'footer'] as const) {\n const entries = node.props?.[region];\n if (Array.isArray(entries)) {\n entries.forEach((child: any, i: number) =>\n validateEntry(child, `${path}/props/${region}/${i}`, true)\n );\n }\n }\n\n // `table` nests its cell content under `props` (not the shared `children`\n // field), and the static table schema types that content loosely — the\n // cell-content ref accepts any props object, just like the `Type.Any()`\n // header/footer above. So a bad prop deep in a cell (e.g. `font.size` over the\n // cap) slips past the per-component table check; walk each content component\n // so its props are validated against the real schema. Structural problems\n // with a cell are already reported by the table's own props validation, hence\n // the lenient (`false`) entry check to avoid double-reporting.\n if (node.name === 'table' && Array.isArray(node.props?.columns)) {\n node.props.columns.forEach((col: any, c: number) => {\n if (!col || typeof col !== 'object') return;\n const base = `${path}/props/columns/${c}`;\n const headerContent = col.header?.content;\n if (headerContent && typeof headerContent === 'object') {\n validateEntry(headerContent, `${base}/header/content`, false);\n }\n if (Array.isArray(col.cells)) {\n col.cells.forEach((cell: any, r: number) => {\n const content = cell?.content;\n if (content && typeof content === 'object') {\n validateEntry(content, `${base}/cells/${r}/content`, false);\n }\n });\n }\n });\n }\n\n if (Array.isArray(node.children)) {\n node.children.forEach((child: any, i: number) =>\n validateEntry(child, `${path}/children/${i}`, true)\n );\n } else if (node.children != null && path !== '') {\n // `children` is present but not an array on a nested container. The root's\n // `children` is already checked by deepValidateDocument (skipped here via\n // `path !== ''` so it is not reported twice); this branch covers every\n // deeper container (`section`/`columns`/`text-box`) the old one-level walk\n // never reached. Without it a malformed subtree slips through as valid:\n // TypeBox reports only a generic catch-all (which we strip), so an empty\n // error set would otherwise flip the document back to `valid`.\n errors.push({\n path: `${path}/children`,\n message: 'Field \"children\" must be an array',\n code: 'invalid_type',\n });\n }\n}\n\n/**\n * Validate a component's props against its schema\n */\nfunction validateComponentProps(\n componentName: string,\n props: any,\n basePath: string,\n opts: DeepValidateOptions = {}\n): ValidationError[] {\n const errors: ValidationError[] = [];\n\n // Get the schema for this component\n const schema = COMPONENT_SCHEMAS[componentName];\n if (!schema) {\n // Unknown component type. `basePath` always ends in `/props`; anchor the\n // swap to the end so a nested region path like `…/props/header/0/props`\n // becomes `…/props/header/0/name` rather than mangling an earlier `/props`.\n errors.push({\n path: basePath.replace(/\\/props$/, '/name'),\n message: `Unknown component \"${componentName}\"`,\n code: 'unknown_component',\n });\n return errors;\n }\n\n // A props schema may be a union — `visual` is one, discriminated on\n // `renderMode`. Checking the union itself collapses every nested complaint\n // into one generic failure at `/props`, which is the opposite of what deep\n // validation is for, so the branch the author clearly meant is resolved\n // first and the errors are collected against that.\n const branch = selectPropsBranch(schema, props);\n\n // When unknown fields are explicitly allowed, strip them before checking so\n // additionalProperties:false no longer rejects — required/typed fields are\n // still enforced.\n const toCheck = opts.allowUnknownFields\n ? Value.Clean(branch, Value.Clone(props))\n : props;\n\n // Use TypeBox to validate against the specific schema\n if (!Value.Check(branch, toCheck)) {\n const valueErrors = [...Value.Errors(branch, toCheck)];\n const transformedErrors = transformValueErrors(valueErrors, {\n maxErrors: 100,\n });\n\n // Adjust paths to be relative to the document root\n transformedErrors.forEach((error) => {\n // Combine base path with error path\n const fullPath =\n error.path === 'root'\n ? basePath\n : `${basePath}${error.path.startsWith('/') ? error.path : '/' + error.path}`;\n\n errors.push({\n ...error,\n path: fullPath,\n });\n });\n }\n\n return errors;\n}\n\n/**\n * The branch of a union props schema that an author's props were written\n * against.\n *\n * Resolved by literal discriminator first — a branch stating `renderMode:\n * \"native\"` claims props that say so, and disclaims props that do not. When no\n * single branch claims them (an unknown discriminator, or none at all), the\n * one that complains least is used: a specific list of what is wrong beats a\n * single \"does not match any of the expected formats\" every time.\n *\n * A non-union schema is returned untouched, so this costs nothing for the\n * components that are plain objects.\n */\nfunction selectPropsBranch(schema: TSchema, props: unknown): TSchema {\n const branches = (schema as { anyOf?: TSchema[] }).anyOf;\n if (!Array.isArray(branches) || branches.length === 0) return schema;\n\n const claimed = branches.filter((branch) => claimsProps(branch, props));\n if (claimed.length === 1) return claimed[0]!;\n\n const candidates = claimed.length > 1 ? claimed : branches;\n let best = candidates[0]!;\n let fewest = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const count = [...Value.Errors(candidate, props)].length;\n if (count < fewest) {\n fewest = count;\n best = candidate;\n }\n }\n return best;\n}\n\n/** True when every literal-valued property of `branch` agrees with `props`. */\nfunction claimsProps(branch: TSchema, props: unknown): boolean {\n const properties = (branch as { properties?: Record<string, TSchema> })\n .properties;\n if (!properties) return false;\n const required = new Set(\n ((branch as { required?: string[] }).required ?? []) as string[]\n );\n const value = (props ?? {}) as Record<string, unknown>;\n\n for (const [key, propertySchema] of Object.entries(properties)) {\n const literal = (propertySchema as { const?: unknown }).const;\n if (literal === undefined) continue;\n const present = value[key] !== undefined;\n if (!present) {\n if (required.has(key)) return false;\n continue;\n }\n if (value[key] !== literal) return false;\n }\n return true;\n}\n\n/**\n * Combine deep validation with standard validation.\n *\n * Deep validation produces precise, path-aware errors. TypeBox's discriminated-\n * union check, by contrast, often collapses any failure under the root document\n * into a single generic \"Invalid component configuration for 'docx'\" message at\n * `root` — useful as a signal that something is wrong, but actionable only via\n * the deep-validator's output. We always strip that catch-all so it doesn't\n * appear alongside (or, worse, instead of) the real diagnostics.\n */\nexport function comprehensiveValidateDocument(\n data: any,\n existingErrors: ValidationError[] = [],\n opts: DeepValidateOptions = {}\n): ValidationError[] {\n const deepErrors = deepValidateDocument(data, opts);\n\n const filteredExisting = existingErrors.filter(\n (e) => !isGenericUnionCatchAll(e)\n );\n\n return deduplicateErrors([...filteredExisting, ...deepErrors]);\n}\n\n/**\n * Detect TypeBox's generic union/discriminator catch-all error at the document\n * root. These messages name the component type ('docx') but give no actionable\n * detail — the deep validator emits the actual path-level errors instead.\n */\nfunction isGenericUnionCatchAll(error: ValidationError): boolean {\n const atRoot = !error.path || error.path === 'root' || error.path === '/';\n if (!atRoot) return false;\n const msg = error.message || '';\n return (\n /invalid component configurations?/i.test(msg) ||\n /invalid document structure/i.test(msg)\n );\n}\n\n/**\n * Deduplicate errors by path and message\n */\nfunction deduplicateErrors(errors: ValidationError[]): ValidationError[] {\n const seen = new Set<string>();\n const unique: ValidationError[] = [];\n\n for (const error of errors) {\n const key = `${error.path}:${error.message}`;\n if (!seen.has(key)) {\n seen.add(key);\n unique.push(error);\n }\n }\n\n return unique;\n}\n","/**\n * Base validator implementation\n * Core validation logic that eliminates duplication across the codebase\n */\n\nimport { Value } from '@sinclair/typebox/value';\nimport type { Static, TSchema } from '@sinclair/typebox';\nimport type {\n ValidationResult,\n ValidationOptions,\n JsonValidationResult,\n} from './types';\nimport {\n transformValueErrors,\n createJsonParseError,\n formatErrorSummary,\n} from '@json-to-office/shared';\n\n/**\n * Base validation function that all specific validators use\n * This eliminates the repeated Value.Check -> Value.Errors -> map pattern\n */\nexport function validateAgainstSchema<T extends TSchema>(\n schema: T,\n data: unknown,\n options?: ValidationOptions\n): ValidationResult<Static<T>> {\n try {\n // Check if data matches the schema\n if (!Value.Check(schema, data)) {\n // Collect ALL errors (not just the first one)\n const errors = [...Value.Errors(schema, data)];\n const transformedErrors = transformValueErrors(errors, {\n jsonString: options?.jsonString,\n maxErrors: options?.maxErrors || 100, // Default to 100 if not specified\n });\n\n return {\n valid: false,\n errors: transformedErrors,\n };\n }\n\n // Data is valid, apply transformations if requested\n let processedData = data;\n\n if (options?.clean) {\n // Remove unknown properties\n processedData = Value.Clean(schema, Value.Clone(processedData));\n }\n\n if (options?.applyDefaults) {\n // Apply default values\n processedData = Value.Default(schema, processedData);\n }\n\n return {\n valid: true,\n data: processedData as Static<T>,\n };\n } catch (error) {\n // Handle unexpected errors\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message:\n error instanceof Error ? error.message : 'Unknown validation error',\n code: 'validation_exception',\n },\n ],\n };\n }\n}\n\n/**\n * Validate JSON string or object with schema\n */\nexport function validateJson<T extends TSchema>(\n schema: T,\n jsonInput: string | object,\n options?: ValidationOptions\n): JsonValidationResult<Static<T>> {\n // Handle string input\n if (typeof jsonInput === 'string') {\n // Basic input validation\n if (!jsonInput.trim()) {\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: 'Input must be a non-empty string',\n code: 'empty_input',\n },\n ],\n isJsonError: true,\n };\n }\n\n // Try to parse JSON\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonInput);\n } catch (error) {\n if (error instanceof Error) {\n return {\n valid: false,\n errors: [createJsonParseError(error, jsonInput)],\n isJsonError: true,\n };\n }\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: 'Failed to parse JSON',\n code: 'json_parse_error',\n },\n ],\n isJsonError: true,\n };\n }\n\n // Validate parsed object with position calculation\n const result = validateAgainstSchema(schema, parsed, {\n ...options,\n jsonString: jsonInput,\n calculatePosition: true,\n });\n\n return {\n ...result,\n parsed,\n isJsonError: false,\n };\n }\n\n // Handle object input directly\n const result = validateAgainstSchema(schema, jsonInput, options);\n return {\n ...result,\n parsed: jsonInput,\n isJsonError: false,\n };\n}\n\n/**\n * Batch validate multiple items\n */\nexport function validateBatch<T extends TSchema>(\n schema: T,\n items: unknown[],\n options?: ValidationOptions\n): ValidationResult<Static<T>[]> {\n const results: Static<T>[] = [];\n const allErrors: any[] = [];\n let hasErrors = false;\n\n for (let i = 0; i < items.length; i++) {\n const result = validateAgainstSchema(schema, items[i], options);\n\n if (result.valid && result.data) {\n results.push(result.data);\n } else {\n hasErrors = true;\n if (result.errors) {\n // Prefix errors with item index\n const prefixedErrors = result.errors.map((e) => ({\n ...e,\n path: `[${i}]${e.path ? '/' + e.path : ''}`,\n }));\n allErrors.push(...prefixedErrors);\n }\n }\n\n // Stop if we've hit the max errors\n if (options?.maxErrors && allErrors.length >= options.maxErrors) {\n break;\n }\n }\n\n if (hasErrors) {\n return {\n valid: false,\n errors: allErrors.slice(0, options?.maxErrors),\n };\n }\n\n return {\n valid: true,\n data: results,\n };\n}\n\n/**\n * Validate with custom error enhancement\n */\nexport function validateWithEnhancement<T extends TSchema>(\n schema: T,\n data: unknown,\n enhancer: (errors: any[]) => any[],\n options?: ValidationOptions\n): ValidationResult<Static<T>> {\n const result = validateAgainstSchema(schema, data, options);\n\n if (!result.valid && result.errors) {\n result.errors = enhancer(result.errors);\n }\n\n return result;\n}\n\n/**\n * Create a validator function for a specific schema\n */\nexport function createValidator<T extends TSchema>(\n schema: T,\n defaultOptions?: ValidationOptions\n) {\n return (data: unknown, options?: ValidationOptions) => {\n return validateAgainstSchema(schema, data, {\n ...defaultOptions,\n ...options,\n });\n };\n}\n\n/**\n * Create a JSON validator function for a specific schema\n */\nexport function createJsonValidator<T extends TSchema>(\n schema: T,\n defaultOptions?: ValidationOptions\n) {\n return (jsonInput: string | object, options?: ValidationOptions) => {\n return validateJson(schema, jsonInput, {\n ...defaultOptions,\n ...options,\n });\n };\n}\n\n/**\n * Utility to check if validation result is successful with type guard\n */\nexport function isValidationSuccess<T>(\n result: ValidationResult<T>\n): result is ValidationResult<T> & { valid: true; data: T } {\n return result.valid === true && result.data !== undefined;\n}\n\n/**\n * Get validation error summary\n */\nexport function getValidationSummary(result: ValidationResult): string {\n if (result.valid) {\n return 'Validation successful';\n }\n\n if (!result.errors || result.errors.length === 0) {\n return 'Validation failed with unknown error';\n }\n\n return formatErrorSummary(result.errors);\n}\n","/**\n * Document validation implementation\n * Single source of truth for all document validation\n */\n\nimport type { Static } from '@sinclair/typebox';\nimport {\n ComponentDefinitionSchema,\n StandardComponentDefinitionSchema,\n} from '../../schemas/components';\nimport { extractStandardComponentNames } from '@json-to-office/shared';\nimport {\n comprehensiveValidateDocument,\n collectImageSourceConflicts,\n collectIndentConflicts,\n collectNoteRevisionConflicts,\n collectTextBoxShapeConflicts,\n} from './deep-validator';\n\n// JsonComponentDefinitionSchema is just an alias for ComponentDefinitionSchema\nconst JsonComponentDefinitionSchema = ComponentDefinitionSchema;\nimport type {\n DocumentValidationResult,\n ValidationError,\n ValidationOptions,\n} from './types';\nimport { validateAgainstSchema, validateJson } from './base-validator';\nimport { collectDocxRendererErrors } from '../../schemas/renderer';\n\n/**\n * The semantic rules the structural schema cannot express.\n *\n * Each entry runs unconditionally over the whole document, because every one of\n * them describes a payload TypeBox already accepted: the fields involved are\n * independently optional, and only their combination is wrong.\n *\n * They live in one list because both entry points below need all of them, and a\n * collector wired into only one of the two is invisible until a document takes\n * the other path.\n */\nconst SEMANTIC_COLLECTORS: readonly {\n readonly why: string;\n readonly collect: (document: unknown) => ValidationError[];\n}[] = [\n {\n // A multi-source image passes the structural check: each source is its own\n // optional field.\n why: 'image source mutual-exclusivity',\n collect: collectImageSourceConflicts,\n },\n {\n why: 'indent hanging/firstLine mutual-exclusivity',\n collect: collectIndentConflicts,\n },\n {\n // Tracked-change text renders literally, so a note marker inside it never\n // resolves and docx cannot express the pair anyway.\n why: 'notes on a revised paragraph',\n collect: collectNoteRevisionConflicts,\n },\n {\n // A shape has no autofit and its outline carries no dash pattern, so the\n // request could only ever come back as a table.\n why: 'a text box asking for a shape rendering a shape cannot give it',\n collect: collectTextBoxShapeConflicts,\n },\n {\n why: 'renderer profile compatibility',\n collect: collectDocxRendererErrors,\n },\n];\n\n/**\n * Run every semantic rule over an already-resolved document — `data` for the\n * object entry point, `result.parsed` for the JSON one.\n */\nfunction collectSemanticConflicts(document: unknown): ValidationError[] {\n return SEMANTIC_COLLECTORS.flatMap(({ collect }) => collect(document));\n}\n\n/**\n * Validate a document/report component definition\n */\nexport function validateDocument(\n data: unknown,\n options?: ValidationOptions\n): DocumentValidationResult {\n const result = validateAgainstSchema(\n ComponentDefinitionSchema,\n data,\n options\n );\n\n // If validation failed, use deep validation to get all detailed errors\n let finalErrors = result.errors || [];\n let finalValid = result.valid;\n if (!result.valid && data) {\n finalErrors = comprehensiveValidateDocument(data, result.errors, {\n allowUnknownFields: options?.allowUnknownFields,\n knownCustomNames: options?.knownCustomNames,\n });\n // If TypeBox's union check produced only generic catch-all errors and the\n // deep validator finds nothing actionable, treat the document as valid.\n if (finalErrors.length === 0) {\n finalValid = true;\n }\n }\n\n // Semantic rules run on every document, valid or not: they describe payloads\n // the structural check already accepted.\n const semanticConflicts = collectSemanticConflicts(data);\n if (semanticConflicts.length > 0) {\n finalErrors = [...finalErrors, ...semanticConflicts];\n finalValid = false;\n }\n\n // Add document-specific metadata. Keep `data` populated whenever `valid` is\n // true so `isValidDocument()` (which requires both) stays consistent — when\n // TypeBox failed and the deep validator cleared the doc, fall back to the\n // original input as the data payload.\n const resolvedData =\n result.data ??\n (finalValid\n ? (data as Static<typeof ComponentDefinitionSchema>)\n : undefined);\n const documentResult: DocumentValidationResult = {\n ...result,\n valid: finalValid,\n documentType: 'docx',\n errors: finalErrors,\n data: resolvedData,\n };\n\n // Check if document has custom components\n if (finalValid) {\n const doc = resolvedData as any;\n if (doc && doc.children && Array.isArray(doc.children)) {\n const hasCustom = doc.children.some(\n (c: any) => !isStandardComponentName(c.name)\n );\n documentResult.hasCustomComponents = hasCustom;\n }\n }\n\n return documentResult;\n}\n\n/**\n * Validate a JSON document (string or object)\n */\nexport function validateJsonDocument(\n jsonInput: string | object,\n options?: ValidationOptions\n): DocumentValidationResult {\n // Use the JSON-specific schema which includes the $schema field\n const result = validateJson(\n JsonComponentDefinitionSchema,\n jsonInput,\n options\n );\n\n // If validation failed, use deep validation to get all detailed errors\n let finalErrors = result.errors || [];\n let finalValid = result.valid;\n if (!result.valid && result.parsed) {\n finalErrors = comprehensiveValidateDocument(result.parsed, result.errors, {\n allowUnknownFields: options?.allowUnknownFields,\n knownCustomNames: options?.knownCustomNames,\n });\n if (finalErrors.length === 0) {\n finalValid = true;\n }\n }\n\n // Semantic rules run on every document, valid or not: they describe payloads\n // the structural check already accepted.\n const semanticConflicts = collectSemanticConflicts(result.parsed);\n if (semanticConflicts.length > 0) {\n finalErrors = [...finalErrors, ...semanticConflicts];\n finalValid = false;\n }\n\n // Add document-specific metadata. Keep `data` populated whenever `valid` is\n // true so `isValidDocument()` (which requires both) stays consistent — when\n // TypeBox failed and the deep validator cleared the doc, fall back to the\n // parsed input as the data payload.\n const resolvedData =\n result.data ??\n (finalValid\n ? (result.parsed as Static<typeof ComponentDefinitionSchema>)\n : undefined);\n const documentResult: DocumentValidationResult = {\n ...result,\n valid: finalValid,\n documentType: 'docx',\n errors: finalErrors,\n data: resolvedData,\n };\n\n // Check for custom components\n if (finalValid) {\n const doc = resolvedData as any;\n if (doc && doc.children && Array.isArray(doc.children)) {\n const hasCustom = doc.children.some(\n (c: any) => !isStandardComponentName(c.name)\n );\n documentResult.hasCustomComponents = hasCustom;\n }\n }\n\n return documentResult;\n}\n\n/**\n * Type guard for document validation result\n */\nexport function isValidDocument(\n result: DocumentValidationResult\n): result is DocumentValidationResult & {\n valid: true;\n data: Static<typeof ComponentDefinitionSchema>;\n} {\n return result.valid === true && result.data !== undefined;\n}\n\n/**\n * Extract standard component names from the schema (cached)\n */\nfunction getStandardComponentNames(): string[] {\n return extractStandardComponentNames(StandardComponentDefinitionSchema);\n}\n\n/**\n * Check if a component name is standard\n */\nfunction isStandardComponentName(name: string): boolean {\n const standardNames = getStandardComponentNames();\n return standardNames.includes(name);\n}\n\n/**\n * Create a document validator with default options\n */\nexport function createDocumentValidator(defaultOptions?: ValidationOptions) {\n return {\n validate: (data: unknown, options?: ValidationOptions) =>\n validateDocument(data, { ...defaultOptions, ...options }),\n validateJson: (jsonInput: string | object, options?: ValidationOptions) =>\n validateJsonDocument(jsonInput, { ...defaultOptions, ...options }),\n };\n}\n\n// Export convenient validators with common configurations\nexport const documentValidator = createDocumentValidator({\n clean: true,\n applyDefaults: true,\n maxErrors: 100, // Collect up to 100 errors to show all validation issues\n});\n\nexport const strictDocumentValidator = createDocumentValidator({\n clean: false,\n applyDefaults: false,\n maxErrors: 100, // Increased from 10 to show more errors\n});\n\n/**\n * Legacy compatibility exports\n */\nexport const validateJsonComponent = validateJsonDocument;\nexport const validateDocumentWithSchema = validateDocument;\n"],"mappings":"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","names":["Value","transformValueErrors","result"]}
|
|
@@ -568,6 +568,13 @@ function collectDocxRendererErrors(data) {
|
|
|
568
568
|
if (object.name === "visual") {
|
|
569
569
|
collectVisualErrors(object, `${path}`, isOfficeOpen, errors);
|
|
570
570
|
}
|
|
571
|
+
if (object.name === "chart" && !isOfficeOpen) {
|
|
572
|
+
errors.push({
|
|
573
|
+
path: `${path}/name`,
|
|
574
|
+
message: `Only the "office-open" renderer draws a native chart. Set the document's "renderer" to "office-open", or use "highcharts" to render one as an image.`,
|
|
575
|
+
code: "unsupported_renderer_feature"
|
|
576
|
+
});
|
|
577
|
+
}
|
|
571
578
|
for (const [key, value] of Object.entries(object)) {
|
|
572
579
|
if (key !== "renderer") visit(value, `${path}/${key}`);
|
|
573
580
|
}
|
|
@@ -684,4 +691,4 @@ export {
|
|
|
684
691
|
docxPropsSchemaForRenderer,
|
|
685
692
|
collectDocxRendererErrors
|
|
686
693
|
};
|
|
687
|
-
//# sourceMappingURL=chunk-
|
|
694
|
+
//# sourceMappingURL=chunk-EG5UTHFZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/components/visual.ts","../src/schemas/components/visual-native.ts","../src/schemas/renderer.ts"],"sourcesContent":["/**\n * Visual Component Schema\n *\n * A `visual` is a free-canvas graphic: absolute positioning, overlapping\n * shapes and layered art that the docx flow layout cannot express — think\n * infographics, diagrams and hero compositions.\n *\n * There are two ways to draw one, chosen by `renderMode`.\n *\n * `raster` (the default, and what an omitted `renderMode` means) authors the\n * canvas as a single pptx slide and embeds the result as a PNG. An injected\n * rasterization service renders it (see `PptxServiceConfig` in\n * @json-to-office/shared), exactly the way `highcharts` offloads chart\n * rendering to an export server; at render time the component desugars to a\n * plain `image`. Every pptx slide element is available, and the output is\n * pixels.\n *\n * `native` draws the same canvas as one Word DrawingML group — real text\n * boxes, real shapes, real pictures — with no pptx, no rasterizer and no PNG.\n * The text stays searchable and every object stays editable in Word. It needs\n * the `office-open` renderer, and its content model is the narrower, strictly\n * validated one in `./visual-native`.\n */\n\nimport { Type, Static } from '@sinclair/typebox';\nimport {\n MIN_VISUAL_DPI,\n MAX_VISUAL_DPI,\n DEFAULT_VISUAL_DPI,\n} from '@json-to-office/shared';\nimport { PptxSlideContentSchema } from '@json-to-office/shared/schemas/slide-content';\nimport {\n AlignmentSchema,\n SpacingSchema,\n FloatingPropertiesSchema,\n} from './common';\nimport {\n NativeVisualCanvasSchema,\n NativeVisualElementSchema,\n} from './visual-native';\n\nexport * from './visual-native';\n\n/**\n * Canvas background — a solid color and/or a background image.\n * Mirrors the pptx slide background shape (kept local to avoid coupling\n * shared-docx to shared-pptx; the rasterizer forwards it verbatim).\n */\nexport const VisualCanvasBackgroundSchema = Type.Object(\n {\n color: Type.Optional(\n Type.String({\n description:\n 'Background color (hex like \"#FFFFFF\" or a theme color name)',\n })\n ),\n image: Type.Optional(\n Type.Object(\n {\n path: Type.Optional(Type.String()),\n base64: Type.Optional(Type.String()),\n },\n { additionalProperties: false }\n )\n ),\n },\n { additionalProperties: false }\n);\n\n/**\n * The pptx canvas the visual is drawn on. Width/height are in inches and set\n * both the aspect ratio and the physical print size of the embedded image.\n */\nexport const VisualCanvasSchema = Type.Object(\n {\n width: Type.Number({\n minimum: 0.1,\n description: 'Canvas width in inches (pptx slideWidth)',\n }),\n height: Type.Number({\n minimum: 0.1,\n description: 'Canvas height in inches (pptx slideHeight)',\n }),\n theme: Type.Optional(\n Type.String({ description: 'pptx theme name applied to the slide' })\n ),\n background: Type.Optional(VisualCanvasBackgroundSchema),\n },\n {\n description: 'pptx canvas definition for the visual',\n additionalProperties: false,\n }\n);\n\n/**\n * Where the drawing sits on the page, and how big it is.\n *\n * Identical for both render modes: a visual is placed like an image whether\n * its pixels came from a rasterizer or its objects were drawn by Word.\n */\nconst PlacementProps = {\n width: Type.Optional(\n Type.Union(\n [\n Type.Number({ minimum: 1, description: 'Rendered width in pixels' }),\n Type.String({\n pattern: '^\\\\d+(\\\\.\\\\d+)?%$',\n description: 'Rendered width as percentage (e.g. \"90%\")',\n }),\n ],\n {\n description:\n 'Rendered width in the document, in pixels (number) or percentage string. Defaults to the canvas physical size.',\n }\n )\n ),\n height: Type.Optional(\n Type.Union([\n Type.Number({ minimum: 1, description: 'Rendered height in pixels' }),\n Type.String({\n pattern: '^\\\\d+(\\\\.\\\\d+)?%$',\n description: 'Rendered height as percentage (e.g. \"90%\")',\n }),\n ])\n ),\n alignment: Type.Optional(AlignmentSchema),\n caption: Type.Optional(\n Type.String({\n description:\n 'Caption (supports rich text with **bold**, *italic*, ***both***)',\n })\n ),\n alt: Type.Optional(\n Type.String({ description: 'Alternative text for accessibility' })\n ),\n spacing: Type.Optional(SpacingSchema),\n floating: Type.Optional(FloatingPropertiesSchema),\n keepNext: Type.Optional(\n Type.Boolean({\n description: 'Keep paragraph with next paragraph on same page',\n })\n ),\n keepLines: Type.Optional(\n Type.Boolean({\n description: 'Keep all lines of paragraph together on same page',\n })\n ),\n} as const;\n\n// A single pptx slide content element (text, image, shape, table, highcharts,\n// chart) is validated against the real PPTX slide-content union\n// (`PptxSlideContentSchema` from @json-to-office/shared/schemas/slide-content)\n// — same authoring fidelity as a standalone `.pptx.json`. Used directly as the\n// `elements` item schema below.\n\n/**\n * The rasterized form: a pptx slide rendered to a PNG.\n *\n * `renderMode` is optional here because omitting it has always meant raster,\n * and every document written before native mode existed must keep rendering\n * byte-for-byte the way it did.\n */\nexport const VisualRasterPropsSchema = Type.Object(\n {\n renderMode: Type.Optional(\n Type.Literal('raster', {\n description:\n 'Render as a rasterized pptx slide (the default when omitted).',\n })\n ),\n\n // ── canvas (drives aspect ratio + physical size) ──\n canvas: VisualCanvasSchema,\n // pptx slide content elements, absolutely positioned on the canvas\n elements: Type.Optional(\n Type.Array(PptxSlideContentSchema, {\n description:\n 'pptx slide content elements (text, image, shape, table, highcharts, chart), positioned with x/y/w/h in inches',\n })\n ),\n\n // ── rasterization ──\n dpi: Type.Optional(\n Type.Number({\n minimum: MIN_VISUAL_DPI,\n maximum: MAX_VISUAL_DPI,\n default: DEFAULT_VISUAL_DPI,\n description: `Raster resolution in DPI (default ${DEFAULT_VISUAL_DPI}, range ${MIN_VISUAL_DPI}-${MAX_VISUAL_DPI}). Higher = sharper + larger.`,\n })\n ),\n serverUrl: Type.Optional(\n Type.String({\n description:\n 'Rasterization service URL override (default from services.pptx)',\n })\n ),\n\n // ── placement in the document (mirrors `image`) ──\n ...PlacementProps,\n },\n {\n // Hoisted into its own JSON-Schema definition rather than inlined at every\n // position a component can appear. `visual.props` is by far the largest\n // props schema in the registry, and inlining two of them pushed the\n // exported `ComponentDefinition` past the depth Ajv can compile.\n $id: 'DocxVisualRasterProps',\n description: 'Visual component props (pptx-rendered graphic)',\n additionalProperties: false,\n }\n);\n\n/**\n * The native form: one Word DrawingML group.\n *\n * `dpi` and `serverUrl` are absent rather than ignored — nothing is\n * rasterized, so a resolution or a service URL would describe work that never\n * happens. `renderMode` is required, which is what makes this branch\n * unreachable by accident.\n */\nexport const VisualNativePropsSchema = Type.Object(\n {\n renderMode: Type.Literal('native', {\n description:\n 'Draw natively as a Word DrawingML group. Requires the \"office-open\" renderer.',\n }),\n canvas: NativeVisualCanvasSchema,\n elements: Type.Optional(\n Type.Array(NativeVisualElementSchema, {\n description:\n 'Native drawing elements (text, shape, image), positioned with x/y/w/h in inches or canvas percentages',\n })\n ),\n ...PlacementProps,\n },\n {\n // Hoisted for the same reason as the raster branch above.\n $id: 'DocxVisualNativeProps',\n description:\n 'Visual component props (native Word drawing group; requires renderer \"office-open\")',\n additionalProperties: false,\n }\n);\n\n/**\n * The authoring surface of `visual`, as a union discriminated on `renderMode`.\n *\n * Kept as one canonical schema rather than two registry entries because the\n * runtime validator checks an un-profiled schema: both shapes have to be\n * structurally valid here, and which one a *document* may use is decided by\n * its renderer, in `schemas/renderer.ts`.\n */\nexport const VisualPropsSchema = Type.Union(\n [VisualRasterPropsSchema, VisualNativePropsSchema],\n {\n description:\n 'Visual component props — rasterized pptx slide (default) or a native Word drawing group',\n }\n);\n\nexport type VisualRasterProps = Static<typeof VisualRasterPropsSchema>;\nexport type VisualNativeProps = Static<typeof VisualNativePropsSchema>;\nexport type VisualProps = VisualRasterProps | VisualNativeProps;\nexport type VisualCanvas = Static<typeof VisualCanvasSchema>;\n\n/** The `renderMode` value that selects the native drawing-group path. */\nexport const NATIVE_RENDER_MODE = 'native';\n\n/** True when these props ask for the native DrawingML path. */\nexport function isNativeVisualProps(\n props: VisualProps | undefined | null\n): props is VisualNativeProps {\n return (\n !!props &&\n (props as { renderMode?: unknown }).renderMode === NATIVE_RENDER_MODE\n );\n}\n","/**\n * Native visual content — the DrawingML side of the `visual` component.\n *\n * A raster visual is authored as a pptx slide because a pptx slide is what\n * rasterizes it. A *native* visual has no such intermediary: it becomes one\n * Word drawing group, so its content model is the subset of that pptx surface\n * Word can draw natively — three element kinds, and only the properties that\n * lower to real DrawingML.\n *\n * The surface is deliberately narrower than the raster one, and strict with it.\n * Every schema here is `additionalProperties: false`, so a property that native\n * mode would ignore is rejected at the authoring boundary instead of silently\n * doing nothing: an author who writes a gradient fill or a chart gets told it\n * is not drawn, rather than shipping a document missing the thing they asked\n * for.\n *\n * Geometry is inches, or a percentage of the canvas extent on that axis. The\n * raster path's \"a number below 100 is inches, at or above it is EMU\" rule is\n * deliberately not reproduced: nothing here is ever EMU.\n */\n\nimport { Type, Static, type TSchema } from '@sinclair/typebox';\nimport { ShapeTypeSchema } from '@json-to-office/shared/schemas/slide-content';\n\n/**\n * A colour anywhere inside a native visual.\n *\n * The same vocabulary the rest of a `.docx.json` uses — `#RRGGBB`, a bare\n * six-digit hex, or a docx theme colour name — because a native visual is\n * drawn by the docx pipeline against the docx theme. The pptx palette names\n * (`accent4`, `tx1`, `bg2`) belong to the raster path and do not resolve here.\n */\nexport const NativeVisualColorSchema = Type.String({\n pattern: '^(#?[0-9A-Fa-f]{6}|[a-zA-Z][a-zA-Z0-9]*)$',\n description:\n 'Hex colour (\"#0F172A\" or \"0F172A\") or a docx theme colour name (e.g. \"primary\")',\n});\n\n/**\n * A signed percentage, for a position: an element may legitimately start off\n * the left or top edge of the canvas.\n */\nconst SIGNED_PERCENT_PATTERN = '^-?\\\\d+(\\\\.\\\\d+)?%$';\n\n/**\n * An unsigned percentage, for a size.\n *\n * Separate from the signed pattern on purpose. The number branch below states\n * `minimum: 0`, and a size that could be negative in one spelling and not the\n * other would make the surface's strictness depend on how the author happened\n * to write it — a negative width has no drawing to refuse it, it just comes\n * out as a zero-size object nobody can see.\n */\nconst PERCENT_PATTERN = '^\\\\d+(\\\\.\\\\d+)?%$';\n\n/** A position on the canvas: inches, or a percentage of the canvas extent. */\nexport const NativeVisualOffsetSchema = Type.Union(\n [\n Type.Number({ description: 'Inches from the canvas origin' }),\n Type.String({\n pattern: SIGNED_PERCENT_PATTERN,\n description: 'Percentage of the canvas extent on this axis, e.g. \"25%\"',\n }),\n ],\n { description: 'Position in inches (number) or as a canvas percentage' }\n);\n\n/** An extent on the canvas: inches, or a percentage of the canvas extent. */\nexport const NativeVisualExtentSchema = Type.Union(\n [\n Type.Number({ minimum: 0, description: 'Size in inches' }),\n Type.String({\n pattern: PERCENT_PATTERN,\n description: 'Percentage of the canvas extent on this axis, e.g. \"50%\"',\n }),\n ],\n { description: 'Size in inches (number) or as a canvas percentage' }\n);\n\nconst FrameProps = {\n x: Type.Optional(NativeVisualOffsetSchema),\n y: Type.Optional(NativeVisualOffsetSchema),\n w: Type.Optional(NativeVisualExtentSchema),\n h: Type.Optional(NativeVisualExtentSchema),\n rotate: Type.Optional(\n Type.Number({ description: 'Clockwise rotation in degrees' })\n ),\n} as const;\n\n/**\n * Underline, as Word draws it.\n *\n * `true` is a single line in the run's own colour; the object form names the\n * line style and, optionally, a colour of its own.\n */\nexport const NativeVisualUnderlineSchema = Type.Union(\n [\n Type.Boolean({ description: 'Single underline in the text colour' }),\n Type.Object(\n {\n style: Type.Optional(\n Type.Union(\n [\n Type.Literal('sng'),\n Type.Literal('dbl'),\n Type.Literal('dash'),\n Type.Literal('dotted'),\n ],\n { description: 'Underline style (default \"sng\")' }\n )\n ),\n color: Type.Optional(NativeVisualColorSchema),\n },\n { additionalProperties: false }\n ),\n ],\n { description: 'Underline: true for a single line, or a style/colour object' }\n);\n\nconst InlineTextProps = {\n fontFace: Type.Optional(Type.String({ description: 'Font family name' })),\n fontSize: Type.Optional(\n Type.Number({ minimum: 1, description: 'Font size in points' })\n ),\n bold: Type.Optional(Type.Boolean()),\n italic: Type.Optional(Type.Boolean()),\n} as const;\n\n/** One formatted span inside a native `text` element. */\nexport const NativeVisualTextRunSchema = Type.Object(\n {\n text: Type.String({ description: 'Run text' }),\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n underline: Type.Optional(NativeVisualUnderlineSchema),\n strike: Type.Optional(Type.Boolean({ description: 'Strikethrough' })),\n breakLine: Type.Optional(\n Type.Boolean({ description: 'Start a new line after this run' })\n ),\n },\n {\n additionalProperties: false,\n description: 'A formatted run inside a native visual text element',\n }\n);\n\n/**\n * One span of a shape's text.\n *\n * Deliberately not the same shape as a text run: shape text carries no\n * underline or strikethrough in the raster surface either, and native mode\n * keeps the two surfaces aligned rather than quietly widening one.\n */\nexport const NativeVisualTextSegmentSchema = Type.Object(\n {\n text: Type.String({ description: 'Segment text' }),\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n breakLine: Type.Optional(\n Type.Boolean({ description: 'Start a new line after this segment' })\n ),\n },\n {\n additionalProperties: false,\n description: 'A formatted segment of a native visual shape’s text',\n }\n);\n\n/** A solid fill, or none at all. */\nexport const NativeVisualFillSchema = Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n transparency: Type.Optional(\n Type.Number({\n minimum: 0,\n maximum: 100,\n description: 'Fill transparency, 0 (opaque) to 100 (invisible)',\n })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Solid fill. Omit the whole property for no fill; gradients and patterns are raster-only.',\n }\n);\n\n/** A shape outline: solid or dashed, one uniform stroke. */\nexport const NativeVisualLineSchema = Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n width: Type.Optional(\n Type.Number({ minimum: 0, description: 'Outline width in points' })\n ),\n dashType: Type.Optional(\n Type.Union(\n [\n Type.Literal('solid'),\n Type.Literal('dash'),\n Type.Literal('dot'),\n Type.Literal('dashDot'),\n ],\n { description: 'Outline dash pattern (default \"solid\")' }\n )\n ),\n },\n { additionalProperties: false, description: 'Shape outline' }\n);\n\nexport const NativeVisualAlignmentSchema = Type.Union(\n [\n Type.Literal('left'),\n Type.Literal('center'),\n Type.Literal('right'),\n Type.Literal('justify'),\n ],\n { description: 'Horizontal text alignment' }\n);\n\nexport const NativeVisualVerticalAlignmentSchema = Type.Union(\n [Type.Literal('top'), Type.Literal('middle'), Type.Literal('bottom')],\n { description: 'Vertical text anchoring inside the box' }\n);\n\n/** Text inset, in points: one value for every side, or `[top, right, bottom, left]`. */\nexport const NativeVisualMarginSchema = Type.Union(\n [\n Type.Number({ minimum: 0, description: 'Inset on every side, in points' }),\n Type.Array(Type.Number({ minimum: 0 }), {\n minItems: 4,\n maxItems: 4,\n description: 'Insets as [top, right, bottom, left], in points',\n }),\n ],\n { description: 'Text insets in points' }\n);\n\nexport const NativeVisualTextPropsSchema = Type.Object(\n {\n text: Type.Optional(Type.String({ description: 'Plain text content' })),\n runs: Type.Optional(\n Type.Array(NativeVisualTextRunSchema, {\n minItems: 1,\n description: 'Formatted runs, as an alternative to \"text\"',\n })\n ),\n ...FrameProps,\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n underline: Type.Optional(NativeVisualUnderlineSchema),\n strike: Type.Optional(Type.Boolean({ description: 'Strikethrough' })),\n align: Type.Optional(NativeVisualAlignmentSchema),\n valign: Type.Optional(NativeVisualVerticalAlignmentSchema),\n margin: Type.Optional(NativeVisualMarginSchema),\n fill: Type.Optional(NativeVisualFillSchema),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual text element — becomes a Word text box (wps:wsp) inside the drawing group',\n }\n);\n\nexport const NativeVisualShapePropsSchema = Type.Object(\n {\n type: ShapeTypeSchema,\n ...FrameProps,\n fill: Type.Optional(NativeVisualFillSchema),\n line: Type.Optional(NativeVisualLineSchema),\n text: Type.Optional(\n Type.Union(\n [\n Type.String(),\n Type.Array(NativeVisualTextSegmentSchema, { minItems: 1 }),\n ],\n { description: 'Text drawn inside the shape' }\n )\n ),\n ...InlineTextProps,\n fontColor: Type.Optional(NativeVisualColorSchema),\n align: Type.Optional(NativeVisualAlignmentSchema),\n valign: Type.Optional(NativeVisualVerticalAlignmentSchema),\n margin: Type.Optional(NativeVisualMarginSchema),\n flipH: Type.Optional(Type.Boolean({ description: 'Mirror horizontally' })),\n flipV: Type.Optional(Type.Boolean({ description: 'Mirror vertically' })),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual shape element — becomes a preset-geometry shape (wps:wsp) inside the drawing group',\n }\n);\n\nexport const NativeVisualImagePropsSchema = Type.Object(\n {\n path: Type.Optional(\n Type.String({ description: 'File path or http(s) URL' })\n ),\n base64: Type.Optional(Type.String({ description: 'Base64 data URI' })),\n svg: Type.Optional(Type.String({ description: 'Raw SVG markup' })),\n ...FrameProps,\n sizing: Type.Optional(\n Type.Object(\n {\n type: Type.Union(\n [\n Type.Literal('contain'),\n Type.Literal('cover'),\n Type.Literal('crop'),\n ],\n { description: 'How the image fills its box' }\n ),\n w: Type.Optional(\n Type.Number({\n minimum: 0,\n description:\n 'Box width in inches; overrides the element’s own \"w\"',\n })\n ),\n h: Type.Optional(\n Type.Number({\n minimum: 0,\n description:\n 'Box height in inches; overrides the element’s own \"h\"',\n })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'How the image fills its box. \"w\"/\"h\" state the box itself, taking precedence over the element’s \"w\"/\"h\", as they do in raster mode.',\n }\n )\n ),\n alt: Type.Optional(\n Type.String({ description: 'Alternative text for accessibility' })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual image element — becomes a native picture inside the drawing group',\n }\n);\n\n/** The three element kinds a native visual can hold, in public schema order. */\nexport const NATIVE_VISUAL_ELEMENT_NAMES = ['text', 'shape', 'image'] as const;\n\nexport type NativeVisualElementName =\n (typeof NATIVE_VISUAL_ELEMENT_NAMES)[number];\n\nfunction nativeElement<\n const TName extends NativeVisualElementName,\n const TProps extends TSchema,\n>(name: TName, propsSchema: TProps, description: string) {\n return Type.Object(\n {\n name: Type.Literal(name),\n id: Type.Optional(Type.String()),\n enabled: Type.Optional(\n Type.Boolean({\n default: true,\n description:\n 'When false, this element is filtered out and not drawn. Defaults to true.',\n })\n ),\n props: propsSchema,\n },\n { additionalProperties: false, description }\n );\n}\n\n/**\n * A single element of a native visual.\n *\n * `table`, `chart` and `highcharts` are absent on purpose: a Word table cannot\n * live inside a drawing group, and neither chart kind has a native mapping\n * here yet. Naming one is a validation error rather than a silent drop.\n *\n * The `$id` is distinct from the raster union's `PptxSlideContent` so the two\n * never collide when the document schema hoists them into shared definitions.\n */\nexport const NativeVisualElementSchema = Type.Union(\n [\n nativeElement(\n 'text',\n NativeVisualTextPropsSchema,\n 'Text element - a native Word text box drawn on the visual canvas.'\n ),\n nativeElement(\n 'shape',\n NativeVisualShapePropsSchema,\n 'Shape element - a native preset-geometry shape, optionally holding text.'\n ),\n nativeElement(\n 'image',\n NativeVisualImagePropsSchema,\n 'Image element - a native picture; an SVG stays vector.'\n ),\n ],\n {\n $id: 'DocxNativeVisualContent',\n discriminator: { propertyName: 'name' },\n description: 'A single native visual element (text, shape, or image).',\n }\n);\n\n/**\n * The canvas a native visual is drawn on.\n *\n * No `theme`: the raster canvas names a *pptx* theme, which the docx pipeline\n * cannot resolve. Native colours resolve against the document's own docx theme\n * instead, so naming a pptx theme here would promise something that could not\n * be kept.\n */\nexport const NativeVisualCanvasSchema = Type.Object(\n {\n width: Type.Number({\n minimum: 0.1,\n description: 'Canvas width in inches',\n }),\n height: Type.Number({\n minimum: 0.1,\n description: 'Canvas height in inches',\n }),\n background: Type.Optional(\n Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n image: Type.Optional(\n Type.Object(\n {\n path: Type.Optional(Type.String()),\n base64: Type.Optional(Type.String()),\n },\n { additionalProperties: false }\n )\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Canvas background. A colour becomes the bottom-most rectangle; an image becomes the bottom-most picture.',\n }\n )\n ),\n },\n {\n additionalProperties: false,\n description: 'Drawing canvas for a native visual',\n }\n);\n\nexport type NativeVisualCanvas = Static<typeof NativeVisualCanvasSchema>;\nexport type NativeVisualElement = Static<typeof NativeVisualElementSchema>;\nexport type NativeVisualTextProps = Static<typeof NativeVisualTextPropsSchema>;\nexport type NativeVisualShapeProps = Static<\n typeof NativeVisualShapePropsSchema\n>;\nexport type NativeVisualImageProps = Static<\n typeof NativeVisualImagePropsSchema\n>;\nexport type NativeVisualTextRun = Static<typeof NativeVisualTextRunSchema>;\nexport type NativeVisualTextSegment = Static<\n typeof NativeVisualTextSegmentSchema\n>;\nexport type NativeVisualFill = Static<typeof NativeVisualFillSchema>;\nexport type NativeVisualLine = Static<typeof NativeVisualLineSchema>;\n","import type { TSchema } from '@sinclair/typebox';\nimport type { ValidationError } from '@json-to-office/shared';\nimport { NATIVE_RENDER_MODE } from './components/visual';\n\nexport const DOCX_RENDERER_IDS = ['docxjs', 'office-open'] as const;\nexport type DocxRendererId = (typeof DOCX_RENDERER_IDS)[number];\nexport const DEFAULT_DOCX_RENDERER_ID: DocxRendererId = 'docxjs';\n\n/** The element kinds a native `visual` can hold. */\nconst NATIVE_VISUAL_ELEMENTS: ReadonlySet<string> = new Set([\n 'text',\n 'shape',\n 'image',\n]);\n\n/**\n * The exported JSON-Schema definition name for one renderer's component union.\n *\n * One name per renderer, never a shared one. The two views differ wherever a\n * backend cannot draw something, so a single definition would hand every\n * position that goes through it — a section header or footer, a table cell's\n * content, `componentDefaults` — whichever view the exporter happened to walk\n * last, and give a schema-driven editor the wrong diagnostics for the other\n * renderer.\n */\nexport function docxComponentDefinitionName(renderer: DocxRendererId): string {\n return `ComponentDefinition_${renderer}`;\n}\n\n/**\n * Derive one renderer view from the canonical props schema.\n *\n * The canonical schema is the union of everything any backend can express, so\n * a profile is a *subtraction*: the branches and fields this renderer cannot\n * draw are removed, which is what makes a schema-driven editor offer only what\n * the chosen backend will actually render.\n */\nexport function docxPropsSchemaForRenderer(\n componentName: string,\n schema: TSchema,\n renderer: DocxRendererId\n): TSchema {\n const copy = cloneSchema(schema);\n nameComponentPlaceholders(copy, docxComponentDefinitionName(renderer));\n\n if (componentName === 'visual' && renderer !== 'office-open') {\n // Only `office-open` draws a native group, so every other backend sees the\n // raster branch alone — a plain object rather than a union, which is what\n // gives an editor one unambiguous completion set.\n return firstUnionBranch(copy) ?? copy;\n }\n\n if (renderer === 'office-open') pruneThreadFields(copy);\n return copy;\n}\n\n/** Static renderer-profile diagnostics used by CLI/library validation. */\nexport function collectDocxRendererErrors(data: unknown): ValidationError[] {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return [];\n const root = data as Record<string, any>;\n const renderer = root.renderer ?? DEFAULT_DOCX_RENDERER_ID;\n\n if (!DOCX_RENDERER_IDS.includes(renderer)) {\n return [\n {\n path: '/renderer',\n message: `Invalid renderer \"${String(renderer)}\". Expected \"docxjs\" or \"office-open\".`,\n code: 'invalid_value',\n },\n ];\n }\n\n const errors: ValidationError[] = [];\n const isOfficeOpen = renderer === 'office-open';\n\n const visit = (node: unknown, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((entry, index) => visit(entry, `${path}/${index}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n const object = node as Record<string, unknown>;\n\n if (isOfficeOpen) {\n const comment = object.comment;\n if (comment && typeof comment === 'object' && !Array.isArray(comment)) {\n const value = comment as Record<string, unknown>;\n for (const field of ['replies', 'resolved'] as const) {\n if (value[field] !== undefined) {\n errors.push({\n path: `${path}/comment/${field}`,\n message: `The \"office-open\" renderer does not support comment threads.`,\n code: 'unsupported_renderer_feature',\n });\n }\n }\n }\n }\n\n if (object.name === 'visual') {\n collectVisualErrors(object, `${path}`, isOfficeOpen, errors);\n }\n\n for (const [key, value] of Object.entries(object)) {\n if (key !== 'renderer') visit(value, `${path}/${key}`);\n }\n };\n\n visit(root, '');\n return errors;\n}\n\n/**\n * Native-mode rules for one `visual` node.\n *\n * Two separate concerns, and both have to name a path an editor can jump to.\n * A backend that cannot draw a group must reject the mode itself, at\n * `props/renderMode`. A backend that can must still reject element kinds that\n * have no native form — otherwise a `chart` inside a native visual would\n * validate and then vanish, which is exactly the failure mode strictness\n * exists to prevent.\n */\nfunction collectVisualErrors(\n node: Record<string, unknown>,\n path: string,\n isOfficeOpen: boolean,\n errors: ValidationError[]\n): void {\n const props = node.props;\n if (!props || typeof props !== 'object' || Array.isArray(props)) return;\n const value = props as Record<string, unknown>;\n if (value.renderMode !== NATIVE_RENDER_MODE) return;\n\n if (!isOfficeOpen) {\n errors.push({\n path: `${path}/props/renderMode`,\n message:\n 'Only the \"office-open\" renderer draws a native visual. Set the document\\'s \"renderer\" to \"office-open\", or drop \"renderMode\" to rasterize.',\n code: 'unsupported_renderer_feature',\n });\n return;\n }\n\n const elements = value.elements;\n if (!Array.isArray(elements)) return;\n elements.forEach((element, index) => {\n if (!element || typeof element !== 'object' || Array.isArray(element)) {\n return;\n }\n const name = (element as Record<string, unknown>).name;\n if (typeof name !== 'string' || NATIVE_VISUAL_ELEMENTS.has(name)) return;\n errors.push({\n path: `${path}/props/elements/${index}/name`,\n message:\n `A native visual cannot draw \"${name}\". Native mode holds \"text\", ` +\n '\"shape\" and \"image\"; use renderMode \"raster\" for anything else.',\n code: 'unsupported_renderer_feature',\n });\n });\n}\n\n/** The first branch of a union schema, if this is one. */\nfunction firstUnionBranch(schema: TSchema): TSchema | undefined {\n const branches = (schema as { anyOf?: TSchema[] }).anyOf;\n return Array.isArray(branches) && branches.length > 0\n ? branches[0]\n : undefined;\n}\n\nfunction pruneThreadFields(node: unknown): void {\n if (Array.isArray(node)) {\n node.forEach(pruneThreadFields);\n return;\n }\n if (!node || typeof node !== 'object') return;\n const schema = node as Record<PropertyKey, any>;\n const properties = schema.properties as Record<string, TSchema> | undefined;\n if (\n properties?.text &&\n properties?.author &&\n (properties.replies || properties.resolved) &&\n typeof schema.description === 'string' &&\n schema.description.includes('Word review comment')\n ) {\n delete properties.replies;\n delete properties.resolved;\n const required = schema.required as string[] | undefined;\n if (required) {\n schema.required = required.filter(\n (key) => key !== 'replies' && key !== 'resolved'\n );\n }\n }\n for (const key of Reflect.ownKeys(schema)) {\n pruneThreadFields(schema[key]);\n }\n}\n\n/**\n * Point a renderer's props at that renderer's component definition.\n *\n * A position that holds arbitrary components but is built from a *static*\n * schema carries an untyped item instead of a live recursive ref —\n * `componentDefaults.section.header` is the one that matters, because\n * `ComponentDefaultsSchema` is shared with the theme and so cannot be handed\n * the recursion. The export pass used to resolve those against one hard-coded\n * name; naming them here, while the renderer is still known and the schema is\n * still this renderer's private clone, is what keeps the two views apart.\n */\nfunction nameComponentPlaceholders(\n node: unknown,\n definitionName: string\n): void {\n if (Array.isArray(node)) {\n node.forEach((entry) => nameComponentPlaceholders(entry, definitionName));\n return;\n }\n if (!node || typeof node !== 'object') return;\n const schema = node as Record<PropertyKey, any>;\n\n if (\n schema.type === 'array' &&\n schema.items &&\n typeof schema.items === 'object' &&\n Object.keys(schema.items).length === 0\n ) {\n // A bare name, the same shape `Type.Recursive` emits for its own self\n // reference. `fixSchemaReferences` resolves both to `#/definitions/...`.\n schema.items = { $ref: definitionName };\n }\n\n for (const key of Reflect.ownKeys(schema)) {\n nameComponentPlaceholders(schema[key], definitionName);\n }\n}\n\nfunction cloneSchema<T>(value: T): T {\n if (Array.isArray(value)) return value.map(cloneSchema) as T;\n if (!value || typeof value !== 'object') return value;\n const copy = Object.create(Object.getPrototypeOf(value));\n for (const key of Reflect.ownKeys(value as object)) {\n copy[key] = cloneSchema((value as any)[key]);\n }\n return copy;\n}\n"],"mappings":"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","names":["Type","Type"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/components/visual.ts","../src/schemas/components/visual-native.ts","../src/schemas/renderer.ts"],"sourcesContent":["/**\n * Visual Component Schema\n *\n * A `visual` is a free-canvas graphic: absolute positioning, overlapping\n * shapes and layered art that the docx flow layout cannot express — think\n * infographics, diagrams and hero compositions.\n *\n * There are two ways to draw one, chosen by `renderMode`.\n *\n * `raster` (the default, and what an omitted `renderMode` means) authors the\n * canvas as a single pptx slide and embeds the result as a PNG. An injected\n * rasterization service renders it (see `PptxServiceConfig` in\n * @json-to-office/shared), exactly the way `highcharts` offloads chart\n * rendering to an export server; at render time the component desugars to a\n * plain `image`. Every pptx slide element is available, and the output is\n * pixels.\n *\n * `native` draws the same canvas as one Word DrawingML group — real text\n * boxes, real shapes, real pictures — with no pptx, no rasterizer and no PNG.\n * The text stays searchable and every object stays editable in Word. It needs\n * the `office-open` renderer, and its content model is the narrower, strictly\n * validated one in `./visual-native`.\n */\n\nimport { Type, Static } from '@sinclair/typebox';\nimport {\n MIN_VISUAL_DPI,\n MAX_VISUAL_DPI,\n DEFAULT_VISUAL_DPI,\n} from '@json-to-office/shared';\nimport { PptxSlideContentSchema } from '@json-to-office/shared/schemas/slide-content';\nimport {\n AlignmentSchema,\n SpacingSchema,\n FloatingPropertiesSchema,\n} from './common';\nimport {\n NativeVisualCanvasSchema,\n NativeVisualElementSchema,\n} from './visual-native';\n\nexport * from './visual-native';\n\n/**\n * Canvas background — a solid color and/or a background image.\n * Mirrors the pptx slide background shape (kept local to avoid coupling\n * shared-docx to shared-pptx; the rasterizer forwards it verbatim).\n */\nexport const VisualCanvasBackgroundSchema = Type.Object(\n {\n color: Type.Optional(\n Type.String({\n description:\n 'Background color (hex like \"#FFFFFF\" or a theme color name)',\n })\n ),\n image: Type.Optional(\n Type.Object(\n {\n path: Type.Optional(Type.String()),\n base64: Type.Optional(Type.String()),\n },\n { additionalProperties: false }\n )\n ),\n },\n { additionalProperties: false }\n);\n\n/**\n * The pptx canvas the visual is drawn on. Width/height are in inches and set\n * both the aspect ratio and the physical print size of the embedded image.\n */\nexport const VisualCanvasSchema = Type.Object(\n {\n width: Type.Number({\n minimum: 0.1,\n description: 'Canvas width in inches (pptx slideWidth)',\n }),\n height: Type.Number({\n minimum: 0.1,\n description: 'Canvas height in inches (pptx slideHeight)',\n }),\n theme: Type.Optional(\n Type.String({ description: 'pptx theme name applied to the slide' })\n ),\n background: Type.Optional(VisualCanvasBackgroundSchema),\n },\n {\n description: 'pptx canvas definition for the visual',\n additionalProperties: false,\n }\n);\n\n/**\n * Where the drawing sits on the page, and how big it is.\n *\n * Identical for both render modes: a visual is placed like an image whether\n * its pixels came from a rasterizer or its objects were drawn by Word.\n */\nconst PlacementProps = {\n width: Type.Optional(\n Type.Union(\n [\n Type.Number({ minimum: 1, description: 'Rendered width in pixels' }),\n Type.String({\n pattern: '^\\\\d+(\\\\.\\\\d+)?%$',\n description: 'Rendered width as percentage (e.g. \"90%\")',\n }),\n ],\n {\n description:\n 'Rendered width in the document, in pixels (number) or percentage string. Defaults to the canvas physical size.',\n }\n )\n ),\n height: Type.Optional(\n Type.Union([\n Type.Number({ minimum: 1, description: 'Rendered height in pixels' }),\n Type.String({\n pattern: '^\\\\d+(\\\\.\\\\d+)?%$',\n description: 'Rendered height as percentage (e.g. \"90%\")',\n }),\n ])\n ),\n alignment: Type.Optional(AlignmentSchema),\n caption: Type.Optional(\n Type.String({\n description:\n 'Caption (supports rich text with **bold**, *italic*, ***both***)',\n })\n ),\n alt: Type.Optional(\n Type.String({ description: 'Alternative text for accessibility' })\n ),\n spacing: Type.Optional(SpacingSchema),\n floating: Type.Optional(FloatingPropertiesSchema),\n keepNext: Type.Optional(\n Type.Boolean({\n description: 'Keep paragraph with next paragraph on same page',\n })\n ),\n keepLines: Type.Optional(\n Type.Boolean({\n description: 'Keep all lines of paragraph together on same page',\n })\n ),\n} as const;\n\n// A single pptx slide content element (text, image, shape, table, highcharts,\n// chart) is validated against the real PPTX slide-content union\n// (`PptxSlideContentSchema` from @json-to-office/shared/schemas/slide-content)\n// — same authoring fidelity as a standalone `.pptx.json`. Used directly as the\n// `elements` item schema below.\n\n/**\n * The rasterized form: a pptx slide rendered to a PNG.\n *\n * `renderMode` is optional here because omitting it has always meant raster,\n * and every document written before native mode existed must keep rendering\n * byte-for-byte the way it did.\n */\nexport const VisualRasterPropsSchema = Type.Object(\n {\n renderMode: Type.Optional(\n Type.Literal('raster', {\n description:\n 'Render as a rasterized pptx slide (the default when omitted).',\n })\n ),\n\n // ── canvas (drives aspect ratio + physical size) ──\n canvas: VisualCanvasSchema,\n // pptx slide content elements, absolutely positioned on the canvas\n elements: Type.Optional(\n Type.Array(PptxSlideContentSchema, {\n description:\n 'pptx slide content elements (text, image, shape, table, highcharts, chart), positioned with x/y/w/h in inches',\n })\n ),\n\n // ── rasterization ──\n dpi: Type.Optional(\n Type.Number({\n minimum: MIN_VISUAL_DPI,\n maximum: MAX_VISUAL_DPI,\n default: DEFAULT_VISUAL_DPI,\n description: `Raster resolution in DPI (default ${DEFAULT_VISUAL_DPI}, range ${MIN_VISUAL_DPI}-${MAX_VISUAL_DPI}). Higher = sharper + larger.`,\n })\n ),\n serverUrl: Type.Optional(\n Type.String({\n description:\n 'Rasterization service URL override (default from services.pptx)',\n })\n ),\n\n // ── placement in the document (mirrors `image`) ──\n ...PlacementProps,\n },\n {\n // Hoisted into its own JSON-Schema definition rather than inlined at every\n // position a component can appear. `visual.props` is by far the largest\n // props schema in the registry, and inlining two of them pushed the\n // exported `ComponentDefinition` past the depth Ajv can compile.\n $id: 'DocxVisualRasterProps',\n description: 'Visual component props (pptx-rendered graphic)',\n additionalProperties: false,\n }\n);\n\n/**\n * The native form: one Word DrawingML group.\n *\n * `dpi` and `serverUrl` are absent rather than ignored — nothing is\n * rasterized, so a resolution or a service URL would describe work that never\n * happens. `renderMode` is required, which is what makes this branch\n * unreachable by accident.\n */\nexport const VisualNativePropsSchema = Type.Object(\n {\n renderMode: Type.Literal('native', {\n description:\n 'Draw natively as a Word DrawingML group. Requires the \"office-open\" renderer.',\n }),\n canvas: NativeVisualCanvasSchema,\n elements: Type.Optional(\n Type.Array(NativeVisualElementSchema, {\n description:\n 'Native drawing elements (text, shape, image), positioned with x/y/w/h in inches or canvas percentages',\n })\n ),\n ...PlacementProps,\n },\n {\n // Hoisted for the same reason as the raster branch above.\n $id: 'DocxVisualNativeProps',\n description:\n 'Visual component props (native Word drawing group; requires renderer \"office-open\")',\n additionalProperties: false,\n }\n);\n\n/**\n * The authoring surface of `visual`, as a union discriminated on `renderMode`.\n *\n * Kept as one canonical schema rather than two registry entries because the\n * runtime validator checks an un-profiled schema: both shapes have to be\n * structurally valid here, and which one a *document* may use is decided by\n * its renderer, in `schemas/renderer.ts`.\n */\nexport const VisualPropsSchema = Type.Union(\n [VisualRasterPropsSchema, VisualNativePropsSchema],\n {\n description:\n 'Visual component props — rasterized pptx slide (default) or a native Word drawing group',\n }\n);\n\nexport type VisualRasterProps = Static<typeof VisualRasterPropsSchema>;\nexport type VisualNativeProps = Static<typeof VisualNativePropsSchema>;\nexport type VisualProps = VisualRasterProps | VisualNativeProps;\nexport type VisualCanvas = Static<typeof VisualCanvasSchema>;\n\n/** The `renderMode` value that selects the native drawing-group path. */\nexport const NATIVE_RENDER_MODE = 'native';\n\n/** True when these props ask for the native DrawingML path. */\nexport function isNativeVisualProps(\n props: VisualProps | undefined | null\n): props is VisualNativeProps {\n return (\n !!props &&\n (props as { renderMode?: unknown }).renderMode === NATIVE_RENDER_MODE\n );\n}\n","/**\n * Native visual content — the DrawingML side of the `visual` component.\n *\n * A raster visual is authored as a pptx slide because a pptx slide is what\n * rasterizes it. A *native* visual has no such intermediary: it becomes one\n * Word drawing group, so its content model is the subset of that pptx surface\n * Word can draw natively — three element kinds, and only the properties that\n * lower to real DrawingML.\n *\n * The surface is deliberately narrower than the raster one, and strict with it.\n * Every schema here is `additionalProperties: false`, so a property that native\n * mode would ignore is rejected at the authoring boundary instead of silently\n * doing nothing: an author who writes a gradient fill or a chart gets told it\n * is not drawn, rather than shipping a document missing the thing they asked\n * for.\n *\n * Geometry is inches, or a percentage of the canvas extent on that axis. The\n * raster path's \"a number below 100 is inches, at or above it is EMU\" rule is\n * deliberately not reproduced: nothing here is ever EMU.\n */\n\nimport { Type, Static, type TSchema } from '@sinclair/typebox';\nimport { ShapeTypeSchema } from '@json-to-office/shared/schemas/slide-content';\n\n/**\n * A colour anywhere inside a native visual.\n *\n * The same vocabulary the rest of a `.docx.json` uses — `#RRGGBB`, a bare\n * six-digit hex, or a docx theme colour name — because a native visual is\n * drawn by the docx pipeline against the docx theme. The pptx palette names\n * (`accent4`, `tx1`, `bg2`) belong to the raster path and do not resolve here.\n */\nexport const NativeVisualColorSchema = Type.String({\n pattern: '^(#?[0-9A-Fa-f]{6}|[a-zA-Z][a-zA-Z0-9]*)$',\n description:\n 'Hex colour (\"#0F172A\" or \"0F172A\") or a docx theme colour name (e.g. \"primary\")',\n});\n\n/**\n * A signed percentage, for a position: an element may legitimately start off\n * the left or top edge of the canvas.\n */\nconst SIGNED_PERCENT_PATTERN = '^-?\\\\d+(\\\\.\\\\d+)?%$';\n\n/**\n * An unsigned percentage, for a size.\n *\n * Separate from the signed pattern on purpose. The number branch below states\n * `minimum: 0`, and a size that could be negative in one spelling and not the\n * other would make the surface's strictness depend on how the author happened\n * to write it — a negative width has no drawing to refuse it, it just comes\n * out as a zero-size object nobody can see.\n */\nconst PERCENT_PATTERN = '^\\\\d+(\\\\.\\\\d+)?%$';\n\n/** A position on the canvas: inches, or a percentage of the canvas extent. */\nexport const NativeVisualOffsetSchema = Type.Union(\n [\n Type.Number({ description: 'Inches from the canvas origin' }),\n Type.String({\n pattern: SIGNED_PERCENT_PATTERN,\n description: 'Percentage of the canvas extent on this axis, e.g. \"25%\"',\n }),\n ],\n { description: 'Position in inches (number) or as a canvas percentage' }\n);\n\n/** An extent on the canvas: inches, or a percentage of the canvas extent. */\nexport const NativeVisualExtentSchema = Type.Union(\n [\n Type.Number({ minimum: 0, description: 'Size in inches' }),\n Type.String({\n pattern: PERCENT_PATTERN,\n description: 'Percentage of the canvas extent on this axis, e.g. \"50%\"',\n }),\n ],\n { description: 'Size in inches (number) or as a canvas percentage' }\n);\n\nconst FrameProps = {\n x: Type.Optional(NativeVisualOffsetSchema),\n y: Type.Optional(NativeVisualOffsetSchema),\n w: Type.Optional(NativeVisualExtentSchema),\n h: Type.Optional(NativeVisualExtentSchema),\n rotate: Type.Optional(\n Type.Number({ description: 'Clockwise rotation in degrees' })\n ),\n} as const;\n\n/**\n * Underline, as Word draws it.\n *\n * `true` is a single line in the run's own colour; the object form names the\n * line style and, optionally, a colour of its own.\n */\nexport const NativeVisualUnderlineSchema = Type.Union(\n [\n Type.Boolean({ description: 'Single underline in the text colour' }),\n Type.Object(\n {\n style: Type.Optional(\n Type.Union(\n [\n Type.Literal('sng'),\n Type.Literal('dbl'),\n Type.Literal('dash'),\n Type.Literal('dotted'),\n ],\n { description: 'Underline style (default \"sng\")' }\n )\n ),\n color: Type.Optional(NativeVisualColorSchema),\n },\n { additionalProperties: false }\n ),\n ],\n { description: 'Underline: true for a single line, or a style/colour object' }\n);\n\nconst InlineTextProps = {\n fontFace: Type.Optional(Type.String({ description: 'Font family name' })),\n fontSize: Type.Optional(\n Type.Number({ minimum: 1, description: 'Font size in points' })\n ),\n bold: Type.Optional(Type.Boolean()),\n italic: Type.Optional(Type.Boolean()),\n} as const;\n\n/** One formatted span inside a native `text` element. */\nexport const NativeVisualTextRunSchema = Type.Object(\n {\n text: Type.String({ description: 'Run text' }),\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n underline: Type.Optional(NativeVisualUnderlineSchema),\n strike: Type.Optional(Type.Boolean({ description: 'Strikethrough' })),\n breakLine: Type.Optional(\n Type.Boolean({ description: 'Start a new line after this run' })\n ),\n },\n {\n additionalProperties: false,\n description: 'A formatted run inside a native visual text element',\n }\n);\n\n/**\n * One span of a shape's text.\n *\n * Deliberately not the same shape as a text run: shape text carries no\n * underline or strikethrough in the raster surface either, and native mode\n * keeps the two surfaces aligned rather than quietly widening one.\n */\nexport const NativeVisualTextSegmentSchema = Type.Object(\n {\n text: Type.String({ description: 'Segment text' }),\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n breakLine: Type.Optional(\n Type.Boolean({ description: 'Start a new line after this segment' })\n ),\n },\n {\n additionalProperties: false,\n description: 'A formatted segment of a native visual shape’s text',\n }\n);\n\n/** A solid fill, or none at all. */\nexport const NativeVisualFillSchema = Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n transparency: Type.Optional(\n Type.Number({\n minimum: 0,\n maximum: 100,\n description: 'Fill transparency, 0 (opaque) to 100 (invisible)',\n })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Solid fill. Omit the whole property for no fill; gradients and patterns are raster-only.',\n }\n);\n\n/** A shape outline: solid or dashed, one uniform stroke. */\nexport const NativeVisualLineSchema = Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n width: Type.Optional(\n Type.Number({ minimum: 0, description: 'Outline width in points' })\n ),\n dashType: Type.Optional(\n Type.Union(\n [\n Type.Literal('solid'),\n Type.Literal('dash'),\n Type.Literal('dot'),\n Type.Literal('dashDot'),\n ],\n { description: 'Outline dash pattern (default \"solid\")' }\n )\n ),\n },\n { additionalProperties: false, description: 'Shape outline' }\n);\n\nexport const NativeVisualAlignmentSchema = Type.Union(\n [\n Type.Literal('left'),\n Type.Literal('center'),\n Type.Literal('right'),\n Type.Literal('justify'),\n ],\n { description: 'Horizontal text alignment' }\n);\n\nexport const NativeVisualVerticalAlignmentSchema = Type.Union(\n [Type.Literal('top'), Type.Literal('middle'), Type.Literal('bottom')],\n { description: 'Vertical text anchoring inside the box' }\n);\n\n/** Text inset, in points: one value for every side, or `[top, right, bottom, left]`. */\nexport const NativeVisualMarginSchema = Type.Union(\n [\n Type.Number({ minimum: 0, description: 'Inset on every side, in points' }),\n Type.Array(Type.Number({ minimum: 0 }), {\n minItems: 4,\n maxItems: 4,\n description: 'Insets as [top, right, bottom, left], in points',\n }),\n ],\n { description: 'Text insets in points' }\n);\n\nexport const NativeVisualTextPropsSchema = Type.Object(\n {\n text: Type.Optional(Type.String({ description: 'Plain text content' })),\n runs: Type.Optional(\n Type.Array(NativeVisualTextRunSchema, {\n minItems: 1,\n description: 'Formatted runs, as an alternative to \"text\"',\n })\n ),\n ...FrameProps,\n color: Type.Optional(NativeVisualColorSchema),\n ...InlineTextProps,\n underline: Type.Optional(NativeVisualUnderlineSchema),\n strike: Type.Optional(Type.Boolean({ description: 'Strikethrough' })),\n align: Type.Optional(NativeVisualAlignmentSchema),\n valign: Type.Optional(NativeVisualVerticalAlignmentSchema),\n margin: Type.Optional(NativeVisualMarginSchema),\n fill: Type.Optional(NativeVisualFillSchema),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual text element — becomes a Word text box (wps:wsp) inside the drawing group',\n }\n);\n\nexport const NativeVisualShapePropsSchema = Type.Object(\n {\n type: ShapeTypeSchema,\n ...FrameProps,\n fill: Type.Optional(NativeVisualFillSchema),\n line: Type.Optional(NativeVisualLineSchema),\n text: Type.Optional(\n Type.Union(\n [\n Type.String(),\n Type.Array(NativeVisualTextSegmentSchema, { minItems: 1 }),\n ],\n { description: 'Text drawn inside the shape' }\n )\n ),\n ...InlineTextProps,\n fontColor: Type.Optional(NativeVisualColorSchema),\n align: Type.Optional(NativeVisualAlignmentSchema),\n valign: Type.Optional(NativeVisualVerticalAlignmentSchema),\n margin: Type.Optional(NativeVisualMarginSchema),\n flipH: Type.Optional(Type.Boolean({ description: 'Mirror horizontally' })),\n flipV: Type.Optional(Type.Boolean({ description: 'Mirror vertically' })),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual shape element — becomes a preset-geometry shape (wps:wsp) inside the drawing group',\n }\n);\n\nexport const NativeVisualImagePropsSchema = Type.Object(\n {\n path: Type.Optional(\n Type.String({ description: 'File path or http(s) URL' })\n ),\n base64: Type.Optional(Type.String({ description: 'Base64 data URI' })),\n svg: Type.Optional(Type.String({ description: 'Raw SVG markup' })),\n ...FrameProps,\n sizing: Type.Optional(\n Type.Object(\n {\n type: Type.Union(\n [\n Type.Literal('contain'),\n Type.Literal('cover'),\n Type.Literal('crop'),\n ],\n { description: 'How the image fills its box' }\n ),\n w: Type.Optional(\n Type.Number({\n minimum: 0,\n description:\n 'Box width in inches; overrides the element’s own \"w\"',\n })\n ),\n h: Type.Optional(\n Type.Number({\n minimum: 0,\n description:\n 'Box height in inches; overrides the element’s own \"h\"',\n })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'How the image fills its box. \"w\"/\"h\" state the box itself, taking precedence over the element’s \"w\"/\"h\", as they do in raster mode.',\n }\n )\n ),\n alt: Type.Optional(\n Type.String({ description: 'Alternative text for accessibility' })\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Native visual image element — becomes a native picture inside the drawing group',\n }\n);\n\n/** The three element kinds a native visual can hold, in public schema order. */\nexport const NATIVE_VISUAL_ELEMENT_NAMES = ['text', 'shape', 'image'] as const;\n\nexport type NativeVisualElementName =\n (typeof NATIVE_VISUAL_ELEMENT_NAMES)[number];\n\nfunction nativeElement<\n const TName extends NativeVisualElementName,\n const TProps extends TSchema,\n>(name: TName, propsSchema: TProps, description: string) {\n return Type.Object(\n {\n name: Type.Literal(name),\n id: Type.Optional(Type.String()),\n enabled: Type.Optional(\n Type.Boolean({\n default: true,\n description:\n 'When false, this element is filtered out and not drawn. Defaults to true.',\n })\n ),\n props: propsSchema,\n },\n { additionalProperties: false, description }\n );\n}\n\n/**\n * A single element of a native visual.\n *\n * `table`, `chart` and `highcharts` are absent on purpose: a Word table cannot\n * live inside a drawing group, and neither chart kind has a native mapping\n * here yet. Naming one is a validation error rather than a silent drop.\n *\n * The `$id` is distinct from the raster union's `PptxSlideContent` so the two\n * never collide when the document schema hoists them into shared definitions.\n */\nexport const NativeVisualElementSchema = Type.Union(\n [\n nativeElement(\n 'text',\n NativeVisualTextPropsSchema,\n 'Text element - a native Word text box drawn on the visual canvas.'\n ),\n nativeElement(\n 'shape',\n NativeVisualShapePropsSchema,\n 'Shape element - a native preset-geometry shape, optionally holding text.'\n ),\n nativeElement(\n 'image',\n NativeVisualImagePropsSchema,\n 'Image element - a native picture; an SVG stays vector.'\n ),\n ],\n {\n $id: 'DocxNativeVisualContent',\n discriminator: { propertyName: 'name' },\n description: 'A single native visual element (text, shape, or image).',\n }\n);\n\n/**\n * The canvas a native visual is drawn on.\n *\n * No `theme`: the raster canvas names a *pptx* theme, which the docx pipeline\n * cannot resolve. Native colours resolve against the document's own docx theme\n * instead, so naming a pptx theme here would promise something that could not\n * be kept.\n */\nexport const NativeVisualCanvasSchema = Type.Object(\n {\n width: Type.Number({\n minimum: 0.1,\n description: 'Canvas width in inches',\n }),\n height: Type.Number({\n minimum: 0.1,\n description: 'Canvas height in inches',\n }),\n background: Type.Optional(\n Type.Object(\n {\n color: Type.Optional(NativeVisualColorSchema),\n image: Type.Optional(\n Type.Object(\n {\n path: Type.Optional(Type.String()),\n base64: Type.Optional(Type.String()),\n },\n { additionalProperties: false }\n )\n ),\n },\n {\n additionalProperties: false,\n description:\n 'Canvas background. A colour becomes the bottom-most rectangle; an image becomes the bottom-most picture.',\n }\n )\n ),\n },\n {\n additionalProperties: false,\n description: 'Drawing canvas for a native visual',\n }\n);\n\nexport type NativeVisualCanvas = Static<typeof NativeVisualCanvasSchema>;\nexport type NativeVisualElement = Static<typeof NativeVisualElementSchema>;\nexport type NativeVisualTextProps = Static<typeof NativeVisualTextPropsSchema>;\nexport type NativeVisualShapeProps = Static<\n typeof NativeVisualShapePropsSchema\n>;\nexport type NativeVisualImageProps = Static<\n typeof NativeVisualImagePropsSchema\n>;\nexport type NativeVisualTextRun = Static<typeof NativeVisualTextRunSchema>;\nexport type NativeVisualTextSegment = Static<\n typeof NativeVisualTextSegmentSchema\n>;\nexport type NativeVisualFill = Static<typeof NativeVisualFillSchema>;\nexport type NativeVisualLine = Static<typeof NativeVisualLineSchema>;\n","import type { TSchema } from '@sinclair/typebox';\nimport type { ValidationError } from '@json-to-office/shared';\nimport { NATIVE_RENDER_MODE } from './components/visual';\n\nexport const DOCX_RENDERER_IDS = ['docxjs', 'office-open'] as const;\nexport type DocxRendererId = (typeof DOCX_RENDERER_IDS)[number];\nexport const DEFAULT_DOCX_RENDERER_ID: DocxRendererId = 'docxjs';\n\n/** The element kinds a native `visual` can hold. */\nconst NATIVE_VISUAL_ELEMENTS: ReadonlySet<string> = new Set([\n 'text',\n 'shape',\n 'image',\n]);\n\n/**\n * The exported JSON-Schema definition name for one renderer's component union.\n *\n * One name per renderer, never a shared one. The two views differ wherever a\n * backend cannot draw something, so a single definition would hand every\n * position that goes through it — a section header or footer, a table cell's\n * content, `componentDefaults` — whichever view the exporter happened to walk\n * last, and give a schema-driven editor the wrong diagnostics for the other\n * renderer.\n */\nexport function docxComponentDefinitionName(renderer: DocxRendererId): string {\n return `ComponentDefinition_${renderer}`;\n}\n\n/**\n * Derive one renderer view from the canonical props schema.\n *\n * The canonical schema is the union of everything any backend can express, so\n * a profile is a *subtraction*: the branches and fields this renderer cannot\n * draw are removed, which is what makes a schema-driven editor offer only what\n * the chosen backend will actually render.\n */\nexport function docxPropsSchemaForRenderer(\n componentName: string,\n schema: TSchema,\n renderer: DocxRendererId\n): TSchema {\n const copy = cloneSchema(schema);\n nameComponentPlaceholders(copy, docxComponentDefinitionName(renderer));\n\n if (componentName === 'visual' && renderer !== 'office-open') {\n // Only `office-open` draws a native group, so every other backend sees the\n // raster branch alone — a plain object rather than a union, which is what\n // gives an editor one unambiguous completion set.\n return firstUnionBranch(copy) ?? copy;\n }\n\n if (renderer === 'office-open') pruneThreadFields(copy);\n return copy;\n}\n\n/** Static renderer-profile diagnostics used by CLI/library validation. */\nexport function collectDocxRendererErrors(data: unknown): ValidationError[] {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return [];\n const root = data as Record<string, any>;\n const renderer = root.renderer ?? DEFAULT_DOCX_RENDERER_ID;\n\n if (!DOCX_RENDERER_IDS.includes(renderer)) {\n return [\n {\n path: '/renderer',\n message: `Invalid renderer \"${String(renderer)}\". Expected \"docxjs\" or \"office-open\".`,\n code: 'invalid_value',\n },\n ];\n }\n\n const errors: ValidationError[] = [];\n const isOfficeOpen = renderer === 'office-open';\n\n const visit = (node: unknown, path: string): void => {\n if (Array.isArray(node)) {\n node.forEach((entry, index) => visit(entry, `${path}/${index}`));\n return;\n }\n if (!node || typeof node !== 'object') return;\n const object = node as Record<string, unknown>;\n\n if (isOfficeOpen) {\n const comment = object.comment;\n if (comment && typeof comment === 'object' && !Array.isArray(comment)) {\n const value = comment as Record<string, unknown>;\n for (const field of ['replies', 'resolved'] as const) {\n if (value[field] !== undefined) {\n errors.push({\n path: `${path}/comment/${field}`,\n message: `The \"office-open\" renderer does not support comment threads.`,\n code: 'unsupported_renderer_feature',\n });\n }\n }\n }\n }\n\n if (object.name === 'visual') {\n collectVisualErrors(object, `${path}`, isOfficeOpen, errors);\n }\n\n // A schema-driven editor already refuses `chart` outside office-open —\n // the component is absent from that branch entirely. This is the same\n // rule stated where a caller reaches validation without the schema, and\n // it names the path of the node rather than the document, so the error\n // lands on the component the author has to move or drop.\n if (object.name === 'chart' && !isOfficeOpen) {\n errors.push({\n path: `${path}/name`,\n message:\n 'Only the \"office-open\" renderer draws a native chart. Set the document\\'s \"renderer\" to \"office-open\", or use \"highcharts\" to render one as an image.',\n code: 'unsupported_renderer_feature',\n });\n }\n\n for (const [key, value] of Object.entries(object)) {\n if (key !== 'renderer') visit(value, `${path}/${key}`);\n }\n };\n\n visit(root, '');\n return errors;\n}\n\n/**\n * Native-mode rules for one `visual` node.\n *\n * Two separate concerns, and both have to name a path an editor can jump to.\n * A backend that cannot draw a group must reject the mode itself, at\n * `props/renderMode`. A backend that can must still reject element kinds that\n * have no native form — otherwise a `chart` inside a native visual would\n * validate and then vanish, which is exactly the failure mode strictness\n * exists to prevent.\n */\nfunction collectVisualErrors(\n node: Record<string, unknown>,\n path: string,\n isOfficeOpen: boolean,\n errors: ValidationError[]\n): void {\n const props = node.props;\n if (!props || typeof props !== 'object' || Array.isArray(props)) return;\n const value = props as Record<string, unknown>;\n if (value.renderMode !== NATIVE_RENDER_MODE) return;\n\n if (!isOfficeOpen) {\n errors.push({\n path: `${path}/props/renderMode`,\n message:\n 'Only the \"office-open\" renderer draws a native visual. Set the document\\'s \"renderer\" to \"office-open\", or drop \"renderMode\" to rasterize.',\n code: 'unsupported_renderer_feature',\n });\n return;\n }\n\n const elements = value.elements;\n if (!Array.isArray(elements)) return;\n elements.forEach((element, index) => {\n if (!element || typeof element !== 'object' || Array.isArray(element)) {\n return;\n }\n const name = (element as Record<string, unknown>).name;\n if (typeof name !== 'string' || NATIVE_VISUAL_ELEMENTS.has(name)) return;\n errors.push({\n path: `${path}/props/elements/${index}/name`,\n message:\n `A native visual cannot draw \"${name}\". Native mode holds \"text\", ` +\n '\"shape\" and \"image\"; use renderMode \"raster\" for anything else.',\n code: 'unsupported_renderer_feature',\n });\n });\n}\n\n/** The first branch of a union schema, if this is one. */\nfunction firstUnionBranch(schema: TSchema): TSchema | undefined {\n const branches = (schema as { anyOf?: TSchema[] }).anyOf;\n return Array.isArray(branches) && branches.length > 0\n ? branches[0]\n : undefined;\n}\n\nfunction pruneThreadFields(node: unknown): void {\n if (Array.isArray(node)) {\n node.forEach(pruneThreadFields);\n return;\n }\n if (!node || typeof node !== 'object') return;\n const schema = node as Record<PropertyKey, any>;\n const properties = schema.properties as Record<string, TSchema> | undefined;\n if (\n properties?.text &&\n properties?.author &&\n (properties.replies || properties.resolved) &&\n typeof schema.description === 'string' &&\n schema.description.includes('Word review comment')\n ) {\n delete properties.replies;\n delete properties.resolved;\n const required = schema.required as string[] | undefined;\n if (required) {\n schema.required = required.filter(\n (key) => key !== 'replies' && key !== 'resolved'\n );\n }\n }\n for (const key of Reflect.ownKeys(schema)) {\n pruneThreadFields(schema[key]);\n }\n}\n\n/**\n * Point a renderer's props at that renderer's component definition.\n *\n * A position that holds arbitrary components but is built from a *static*\n * schema carries an untyped item instead of a live recursive ref —\n * `componentDefaults.section.header` is the one that matters, because\n * `ComponentDefaultsSchema` is shared with the theme and so cannot be handed\n * the recursion. The export pass used to resolve those against one hard-coded\n * name; naming them here, while the renderer is still known and the schema is\n * still this renderer's private clone, is what keeps the two views apart.\n */\nfunction nameComponentPlaceholders(\n node: unknown,\n definitionName: string\n): void {\n if (Array.isArray(node)) {\n node.forEach((entry) => nameComponentPlaceholders(entry, definitionName));\n return;\n }\n if (!node || typeof node !== 'object') return;\n const schema = node as Record<PropertyKey, any>;\n\n if (\n schema.type === 'array' &&\n schema.items &&\n typeof schema.items === 'object' &&\n Object.keys(schema.items).length === 0\n ) {\n // A bare name, the same shape `Type.Recursive` emits for its own self\n // reference. `fixSchemaReferences` resolves both to `#/definitions/...`.\n schema.items = { $ref: definitionName };\n }\n\n for (const key of Reflect.ownKeys(schema)) {\n nameComponentPlaceholders(schema[key], definitionName);\n }\n}\n\nfunction cloneSchema<T>(value: T): T {\n if (Array.isArray(value)) return value.map(cloneSchema) as T;\n if (!value || typeof value !== 'object') return value;\n const copy = Object.create(Object.getPrototypeOf(value));\n for (const key of Reflect.ownKeys(value as object)) {\n copy[key] = cloneSchema((value as any)[key]);\n }\n return copy;\n}\n"],"mappings":"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","names":["Type","Type"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAllComponentSchemas,
|
|
3
3
|
createAllComponentSchemasNarrowed
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MMD4A5LR.js";
|
|
5
5
|
|
|
6
6
|
// src/schemas/components.ts
|
|
7
7
|
import { Type } from "@sinclair/typebox";
|
|
@@ -31,4 +31,4 @@ export {
|
|
|
31
31
|
StandardComponentDefinitionSchema,
|
|
32
32
|
ComponentDefinitionSchema
|
|
33
33
|
};
|
|
34
|
-
//# sourceMappingURL=chunk-
|
|
34
|
+
//# sourceMappingURL=chunk-M4F3PWQR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schemas/components.ts"],"sourcesContent":["/**\n * TypeBox Component Schemas\n *\n * Complete component definitions with discriminated unions for perfect\n * JSON schema autocompletion and validation.\n *\n * IMPORTANT: Standard components are defined in component-registry.ts (SINGLE SOURCE OF TRUTH).\n * This file uses that registry to generate TypeBox schemas.\n */\n\nimport { Type, Static } from '@sinclair/typebox';\nimport {\n createAllComponentSchemas,\n createAllComponentSchemasNarrowed,\n} from './component-registry';\n\n// Re-export all schemas from individual component files\nexport * from './components/common';\nexport * from './components/revision';\nexport * from './components/comment';\nexport * from './components/note';\nexport * from './components/report';\nexport * from './components/section';\nexport * from './components/columns';\nexport * from './components/heading';\nexport * from './components/paragraph';\nexport * from './components/image';\nexport * from './components/highcharts';\nexport * from './components/chart';\nexport * from './components/visual';\nexport * from './components/statistic';\nexport * from './components/table';\nexport * from './components/list';\nexport * from './components/toc';\nexport * from './components/text-box';\n\n// ============================================================================\n// Component Definitions with Discriminated Union\n// ============================================================================\n\n// StandardComponentDefinitionSchema - Union of all standard component types\n// Generated from the component registry (SINGLE SOURCE OF TRUTH)\nexport const StandardComponentDefinitionSchema = Type.Union(\n // Use Type.Any() for non-recursive standard components\n // Convert readonly array to mutable array for Type.Union\n [...createAllComponentSchemas(Type.Any())],\n {\n discriminator: { propertyName: 'name' },\n description: 'Standard component definition with discriminated union',\n }\n);\n\nexport const ComponentDefinitionSchema = Type.Recursive((This) =>\n Type.Union(\n [\n // Standard components from registry with per-container narrowed children\n ...createAllComponentSchemasNarrowed(This).schemas,\n ],\n {\n discriminator: { propertyName: 'name' },\n description: 'Component definition with discriminated union',\n }\n )\n);\n\n// ============================================================================\n// TypeScript Types\n// ============================================================================\n\nexport type ComponentDefinition = Static<typeof ComponentDefinitionSchema>;\n"],"mappings":";;;;;;AAUA,SAAS,YAAoB;AAgCtB,IAAM,oCAAoC,KAAK;AAAA;AAAA;AAAA,EAGpD,CAAC,GAAG,0BAA0B,KAAK,IAAI,CAAC,CAAC;AAAA,EACzC;AAAA,IACE,eAAe,EAAE,cAAc,OAAO;AAAA,IACtC,aAAa;AAAA,EACf;AACF;AAEO,IAAM,4BAA4B,KAAK;AAAA,EAAU,CAAC,SACvD,KAAK;AAAA,IACH;AAAA;AAAA,MAEE,GAAG,kCAAkC,IAAI,EAAE;AAAA,IAC7C;AAAA,IACA;AAAA,MACE,eAAe,EAAE,cAAc,OAAO;AAAA,MACtC,aAAa;AAAA,IACf;AAAA,EACF;AACF;","names":[]}
|