@json-to-office/shared 2.6.0 → 3.0.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.
@@ -59,6 +59,7 @@ function restructureNameDiscriminatedUnions(schema) {
59
59
  obj.required = ["name"];
60
60
  obj.properties = {
61
61
  name: {
62
+ description: "Component or registered plugin to render.",
62
63
  anyOf: [...groups.entries()].map(
63
64
  ([name, group]) => nameEntry(name, group)
64
65
  )
@@ -168,7 +169,8 @@ function convertToJsonSchema(schema, options = {}) {
168
169
  $id,
169
170
  title,
170
171
  description,
171
- definitions = {}
172
+ definitions = {},
173
+ enrich
172
174
  } = options;
173
175
  const schemaJson = JSON.parse(JSON.stringify(schema));
174
176
  if (schemaJson.$id && typeof schemaJson.$id === "string" && /^T\d+$/.test(schemaJson.$id)) {
@@ -214,6 +216,7 @@ function convertToJsonSchema(schema, options = {}) {
214
216
  jsonSchema.definitions = extractedDefinitions;
215
217
  }
216
218
  fixSchemaReferences(jsonSchema);
219
+ enrich?.(jsonSchema);
217
220
  restructureNameDiscriminatedUnions(jsonSchema);
218
221
  return jsonSchema;
219
222
  }
@@ -294,4 +297,4 @@ export {
294
297
  exportSchemaToFile,
295
298
  createComponentSchemaObject
296
299
  };
297
- //# sourceMappingURL=chunk-6TNT7DGC.js.map
300
+ //# sourceMappingURL=chunk-LFHU4EOV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas/schema-utils.ts","../src/schemas/discriminated-unions.ts"],"sourcesContent":["import { Type, TSchema } from '@sinclair/typebox';\nimport { restructureNameDiscriminatedUnions } from './discriminated-unions';\nimport type { ComponentDefinition } from '../types/components';\n\nexport interface ComponentSchemaConfig {\n schema: TSchema;\n title: string;\n description: string;\n requiresName?: boolean;\n enhanceForRichContent?: boolean;\n}\n\nfunction replaceRefs(\n obj: Record<string, unknown>,\n target: string,\n replacement: string\n): void {\n if (typeof obj !== 'object' || obj === null) return;\n if (Array.isArray(obj)) {\n obj.forEach((item) => {\n if (typeof item === 'object' && item !== null) {\n replaceRefs(item as Record<string, unknown>, target, replacement);\n }\n });\n return;\n }\n if (obj.$ref === target) {\n obj.$ref = replacement;\n }\n for (const value of Object.values(obj)) {\n if (typeof value === 'object' && value !== null) {\n replaceRefs(value as Record<string, unknown>, target, replacement);\n }\n }\n}\n\n/**\n * Resolve the bare `$ref` values TypeBox leaves behind into JSON Pointers.\n *\n * `rootDefinitionName` is only the fallback for a reference that names nothing\n * hoisted. A schema may carry several recursive definitions — the DOCX\n * document schema carries one per renderer — so a bare reference that matches\n * an actual definition resolves to *that* one, which is what keeps the two\n * renderer views from collapsing into whichever was walked last.\n */\nexport function fixSchemaReferences(\n schema: Record<string, unknown>,\n rootDefinitionName = 'ComponentDefinition'\n): void {\n const definitionNames = new Set(\n Object.keys(\n (schema.definitions as Record<string, unknown> | undefined) ?? {}\n )\n );\n // Undefined when nothing by either name was hoisted. Substituting the root\n // name regardless is how a reference to a definition that does not exist got\n // written, and Ajv refuses to compile a schema containing one — so an\n // unresolved reference is dropped rather than invented.\n const definitionRef = (name: string): string | undefined => {\n const target = definitionNames.has(name) ? name : rootDefinitionName;\n return definitionNames.has(target) ? `#/definitions/${target}` : undefined;\n };\n const isBareDefinitionRef = (value: unknown): value is string =>\n typeof value === 'string' &&\n (/^T\\d+$/.test(value) ||\n value === rootDefinitionName ||\n definitionNames.has(value));\n\n function traverse(obj: Record<string, unknown>, path = ''): void {\n if (typeof obj !== 'object' || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = path ? `${path}.${key}` : key;\n\n if (value && typeof value === 'object') {\n const schemaValue = value as Record<string, unknown>;\n\n // Only when there is something to point at. A schema that holds\n // components without embedding their definition (the theme schema\n // holds `componentDefaults` but cannot carry a renderer's component\n // union) keeps its untyped item: a `$ref` to a definition that was\n // never hoisted is unresolvable, and Ajv refuses to compile the whole\n // schema over it.\n if (\n schemaValue.type === 'array' &&\n schemaValue.items &&\n Object.keys(schemaValue.items).length === 0 &&\n definitionNames.has(rootDefinitionName)\n ) {\n schemaValue.items = {\n $ref: `#/definitions/${rootDefinitionName}`,\n };\n }\n\n if (\n schemaValue.type === 'array' &&\n schemaValue.items &&\n typeof schemaValue.items === 'object' &&\n '$ref' in schemaValue.items &&\n isBareDefinitionRef(\n (schemaValue.items as Record<string, unknown>).$ref\n )\n ) {\n const name = (schemaValue.items as Record<string, unknown>)\n .$ref as string;\n const ref = definitionRef(name);\n // Untyped rather than dangling when the target was never hoisted.\n schemaValue.items = ref ? { $ref: ref } : {};\n }\n\n if (isBareDefinitionRef(schemaValue.$ref)) {\n const ref = definitionRef(schemaValue.$ref as string);\n if (ref) schemaValue.$ref = ref;\n else delete schemaValue.$ref;\n }\n\n if (\n key === '$id' &&\n isBareDefinitionRef(value) &&\n currentPath !== `definitions.${value}.$id`\n ) {\n delete obj[key];\n continue;\n }\n\n traverse(value as Record<string, unknown>, currentPath);\n }\n }\n }\n\n traverse(schema);\n}\n\nexport function convertToJsonSchema(\n schema: TSchema,\n options: {\n $schema?: string;\n $id?: string;\n title?: string;\n description?: string;\n definitions?: Record<string, unknown>;\n /**\n * Format-specific enrichment applied once references resolve and before\n * the name-discriminated unions are restructured — the point at which a\n * component union is still a flat `anyOf` a derivation can filter and\n * copy. The PPTX block-body authoring schemas are added here.\n */\n enrich?: (schema: Record<string, unknown>) => void;\n } = {}\n): Record<string, unknown> {\n const {\n $schema = 'http://json-schema.org/draft-07/schema#',\n $id,\n title,\n description,\n definitions = {},\n enrich,\n } = options;\n\n const schemaJson = JSON.parse(JSON.stringify(schema));\n\n if (\n schemaJson.$id &&\n typeof schemaJson.$id === 'string' &&\n /^T\\d+$/.test(schemaJson.$id)\n ) {\n const recursiveId = schemaJson.$id;\n delete schemaJson.$id;\n replaceRefs(schemaJson, recursiveId, '#');\n }\n\n const extractedDefinitions: Record<string, unknown> = { ...definitions };\n\n function extractRecursiveSchemas(\n obj: Record<string, unknown>,\n path = ''\n ): void {\n if (typeof obj !== 'object' || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n if (value && typeof value === 'object') {\n const schemaValue = value as Record<string, unknown>;\n\n if (schemaValue.$id && typeof schemaValue.$id === 'string') {\n const definitionName = schemaValue.$id;\n\n if (path !== `definitions.${definitionName}`) {\n const { $id: _id, ...schemaWithoutId } = schemaValue; // eslint-disable-line @typescript-eslint/no-unused-vars\n extractedDefinitions[definitionName] = schemaWithoutId;\n obj[key] = { $ref: `#/definitions/${definitionName}` };\n extractRecursiveSchemas(\n schemaWithoutId,\n `definitions.${definitionName}`\n );\n continue;\n }\n }\n\n extractRecursiveSchemas(\n value as Record<string, unknown>,\n path ? `${path}.${key}` : key\n );\n }\n }\n }\n\n extractRecursiveSchemas(schemaJson);\n\n const jsonSchema: Record<string, unknown> = { $schema };\n\n if ($id) jsonSchema.$id = $id;\n\n Object.assign(jsonSchema, schemaJson);\n\n jsonSchema.$schema = $schema;\n if ($id) jsonSchema.$id = $id;\n if (title !== undefined) jsonSchema.title = title;\n if (description !== undefined) jsonSchema.description = description;\n\n if (Object.keys(extractedDefinitions).length > 0) {\n jsonSchema.definitions = extractedDefinitions;\n }\n\n fixSchemaReferences(jsonSchema);\n enrich?.(jsonSchema);\n restructureNameDiscriminatedUnions(jsonSchema);\n\n return jsonSchema;\n}\n\nexport function createComponentSchema(\n name: string,\n config: ComponentSchemaConfig,\n containerNames: string[],\n componentDefinitionSchema?: TSchema,\n // The definition the recursive children reference. Callers whose component\n // union is renderer-specific pass that renderer's name so the embedded\n // definition and the `$ref` pointing at it agree.\n rootDefinitionName = 'ComponentDefinition'\n): Record<string, unknown> {\n const componentStructure: Record<string, unknown> = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: `${name}.schema.json`,\n title: config.title,\n description: config.description,\n type: 'object',\n required: ['name', 'props'],\n properties: {\n name: {\n type: 'string',\n const: name,\n description: `Component name identifier (must be \"${name}\")`,\n },\n id: {\n type: 'string',\n description: 'Optional unique identifier for the component',\n },\n props: JSON.parse(JSON.stringify(config.schema)),\n },\n };\n\n if (containerNames.includes(name)) {\n (componentStructure.properties as Record<string, unknown>).children = {\n type: 'array',\n description: 'Children within this container',\n items: {\n $ref: `#/definitions/${rootDefinitionName}`,\n },\n };\n\n if (componentDefinitionSchema) {\n componentStructure.definitions = {\n [rootDefinitionName]: JSON.parse(\n JSON.stringify(componentDefinitionSchema)\n ),\n };\n }\n }\n\n fixSchemaReferences(componentStructure, rootDefinitionName);\n componentStructure.additionalProperties = false;\n\n return componentStructure;\n}\n\nexport async function exportSchemaToFile(\n schema: Record<string, unknown>,\n outputPath: string,\n options: { prettyPrint?: boolean } = {}\n): Promise<void> {\n const { prettyPrint = true } = options;\n const jsonSchema = prettyPrint\n ? JSON.stringify(schema, null, 2)\n : JSON.stringify(schema);\n const fs = await import('fs/promises');\n await fs.writeFile(outputPath, jsonSchema, 'utf-8');\n}\n\n/**\n * Create a TypeBox schema object for any component definition.\n * Works for both docx and pptx components.\n */\nexport function createComponentSchemaObject(\n component: ComponentDefinition,\n recursiveRef?: TSchema\n): TSchema {\n const schema: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n id: Type.Optional(Type.String()),\n enabled: Type.Optional(\n Type.Boolean({\n default: true,\n description:\n 'When false, this component is filtered out and not rendered. Defaults to true.',\n })\n ),\n };\n\n if (component.special?.hasSchemaField) {\n schema.$schema = Type.Optional(Type.String({ format: 'uri' }));\n }\n\n schema.props = component.propsSchema;\n\n if (component.hasChildren && recursiveRef) {\n schema.children = Type.Optional(Type.Array(recursiveRef));\n }\n\n return Type.Object(schema, { additionalProperties: false });\n}\n","/**\n * Canonical `if/then` restructuring for name-discriminated component unions.\n *\n * The generators export component unions as a flat `anyOf`. Schema-driven\n * editors (Monaco, VS Code — vscode-json-languageservice) resolve a partially\n * typed node against an `anyOf` by picking the single best-matching branch:\n * while typing `{ \"name\": | }`, every branch requiring `props` fails\n * validation, so its name const never reached autocomplete, and diagnostics\n * reported one arbitrary branch's complaints (\"Value must be \\\"heading\\\"\",\n * \"Missing property \\\"props\\\"\") instead of the real problem.\n *\n * This transform rewrites each such union — at JSON-Schema export time only,\n * the runtime TypeBox validators are untouched — into the standard\n * discriminated-union dispatch:\n *\n * {\n * type: \"object\",\n * required: [\"name\"],\n * properties: { name: { anyOf: [{ const, description }, …] } },\n * allOf: [\n * { if: { properties: { name: { const } }, required: [\"name\"] },\n * then: <branch> },\n * …\n * ]\n * }\n *\n * The accepted set of documents is exactly the same — `properties.name` is\n * the enum the branches already imply, and each `then` is the original\n * branch — but editors now behave deterministically:\n * - completing `name` offers every component, with its description\n * - an empty object reports only `Missing property \"name\"`\n * - a wrong name reports only `Value is not accepted. Valid values: …`\n * - a valid name activates exactly its branch for keys, props and errors\n *\n * Standard draft-07 keywords only, so ajv and every schema-aware editor\n * agree. Versioned plugin branches share a name; they stay grouped in a\n * small `anyOf` inside their `then`, containing best-match ambiguity to the\n * component's own versions.\n */\n\ninterface SchemaNode {\n [key: string]: unknown;\n}\n\ninterface NameConstEntry {\n const: string;\n type: 'string';\n description?: string;\n}\n\n/** A union branch shaped `{ properties: { name: { const: \"...\" } } }`. */\nfunction branchNameConst(branch: unknown): string | undefined {\n if (typeof branch !== 'object' || branch === null || Array.isArray(branch))\n return undefined;\n const name = ((branch as SchemaNode).properties as SchemaNode | undefined)\n ?.name as SchemaNode | undefined;\n return typeof name?.const === 'string' ? name.const : undefined;\n}\n\n/** True when the branch also discriminates on a `version` const (plugins). */\nfunction isVersionedBranch(branch: SchemaNode): boolean {\n const version = (branch.properties as SchemaNode | undefined)?.version as\n | SchemaNode\n | undefined;\n return typeof version?.const === 'string';\n}\n\nfunction branchRequiresName(branch: SchemaNode): boolean {\n return Array.isArray(branch.required) && branch.required.includes('name');\n}\n\n/** Group branches by their name const, preserving union order. */\nfunction groupByName(branches: SchemaNode[]): Map<string, SchemaNode[]> {\n const groups = new Map<string, SchemaNode[]>();\n for (const branch of branches) {\n const name = branchNameConst(branch)!;\n const group = groups.get(name);\n if (group) group.push(branch);\n else groups.set(name, [branch]);\n }\n return groups;\n}\n\nfunction nameEntry(name: string, group: SchemaNode[]): NameConstEntry {\n // Versioned plugins repeat the same name across version branches; the\n // un-versioned fallback carries the cleanest component description.\n const source =\n group.find(\n (b) => !isVersionedBranch(b) && typeof b.description === 'string'\n ) ?? group.find((b) => typeof b.description === 'string');\n return {\n const: name,\n type: 'string',\n ...(source ? { description: source.description as string } : {}),\n };\n}\n\n/**\n * Walk a JSON Schema and restructure every `anyOf` union whose branches are\n * all name-discriminated objects into the `if/then` dispatch shape above.\n *\n * Mutates in place. Conservative by design — a union is only restructured\n * when the rewrite is provably equivalent:\n * - every branch is an object with a `name` const that lists `name` as\n * required (unions containing `$ref` or free-form branches are left alone;\n * a `$ref`'s target union is restructured where it is defined)\n * - the node declares no `properties`, `allOf`, `if`, `required`,\n * `additionalProperties` or `type` of its own that the rewrite would have\n * to merge with\n * - at least two distinct names; single-name unions (a versioned plugin's\n * variants) validate and complete fine as a plain anyOf\n */\nexport function restructureNameDiscriminatedUnions(schema: unknown): void {\n const visited = new WeakSet<object>();\n\n function walk(node: unknown): void {\n if (typeof node !== 'object' || node === null) return;\n if (visited.has(node)) return;\n visited.add(node);\n\n if (Array.isArray(node)) {\n node.forEach(walk);\n return;\n }\n\n const obj = node as SchemaNode;\n const anyOf = obj.anyOf;\n const isCandidate =\n Array.isArray(anyOf) &&\n anyOf.length >= 2 &&\n anyOf.every(\n (b) => branchNameConst(b) !== undefined && branchRequiresName(b)\n ) &&\n obj.properties === undefined &&\n obj.allOf === undefined &&\n obj.if === undefined &&\n obj.required === undefined &&\n // A sibling `additionalProperties` evaluates against the node's own\n // (absent) `properties`; declaring `name` here would change what it\n // rejects, so such unions are left alone.\n obj.additionalProperties === undefined &&\n (obj.type === undefined || obj.type === 'object');\n // Dispatch needs at least two distinct names. Same-name groups (a\n // versioned plugin's variants) stay a plain anyOf — restructuring them\n // would recurse forever on the group it just created.\n const groups = isCandidate ? groupByName(anyOf as SchemaNode[]) : undefined;\n if (groups && groups.size >= 2) {\n obj.type = 'object';\n obj.required = ['name'];\n obj.properties = {\n name: {\n description: 'Component or registered plugin to render.',\n anyOf: [...groups.entries()].map(([name, group]) =>\n nameEntry(name, group)\n ),\n },\n };\n obj.allOf = [...groups.entries()].map(([name, group]) => ({\n if: {\n properties: { name: { const: name } },\n required: ['name'],\n },\n then: group.length === 1 ? group[0] : { anyOf: group },\n }));\n delete obj.anyOf;\n }\n\n for (const value of Object.values(obj)) walk(value);\n }\n\n walk(schema);\n}\n\n/**\n * Iterate the component branches of an exported union, whichever shape it is\n * in — the flat `anyOf` the generators emit, or the `if/then` dispatch this\n * module rewrites it into. For consumers that post-process branch objects\n * (description enhancement, theme-name injection, …).\n */\nexport function unionBranches(schema: unknown): SchemaNode[] {\n if (typeof schema !== 'object' || schema === null) return [];\n const obj = schema as SchemaNode;\n if (Array.isArray(obj.anyOf)) {\n return obj.anyOf.filter(\n (b): b is SchemaNode => typeof b === 'object' && b !== null\n );\n }\n if (Array.isArray(obj.allOf)) {\n return obj.allOf.flatMap((entry): SchemaNode[] => {\n const then = (entry as SchemaNode | null)?.then;\n if (typeof then !== 'object' || then === null) return [];\n const inner = (then as SchemaNode).anyOf;\n return Array.isArray(inner)\n ? inner.filter(\n (b): b is SchemaNode => typeof b === 'object' && b !== null\n )\n : [then as SchemaNode];\n });\n }\n return [];\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- export { C as ComponentDefinition, a as ComponentSchemaConfig, c as convertToJsonSchema, b as createComponentSchema, d as createComponentSchemaObject, e as exportSchemaToFile, f as fixSchemaReferences } from './schema-utils-C5Qdzsgy.js';
1
+ export { C as ComponentDefinition, a as ComponentSchemaConfig, c as convertToJsonSchema, b as createComponentSchema, d as createComponentSchemaObject, e as exportSchemaToFile, f as fixSchemaReferences } from './schema-utils-B2i75lAT.js';
2
2
  export { AddWarningFunction, GenerationWarning } from './types/warnings.js';
3
3
  import { F as FontRegistryEntry, c as FontRuntimeOpts, R as ResolvedFontSource, b as ResolvedFont, a as RasterizeFontFace } from './types-kcQwhOlf.js';
4
4
  export { D as DEFAULT_VISUAL_DPI, d as FontFamilyNameSchema, e as FontRegistryDefinition, f as FontRegistryEntrySchema, g as FontRegistrySchema, h as FontSource, i as FontSourceSchema, H as HighchartsHeaders, j as HighchartsHeadersResolver, k as HighchartsServiceConfig, M as MAX_RASTERIZE_BATCH_SLIDES, l as MAX_RASTERIZE_FONTS, m as MAX_RASTERIZE_FONT_BYTES, n as MAX_VISUAL_DPI, o as MIN_VISUAL_DPI, P as PptxBatchRasterizer, p as PptxRasterizeBatchRequest, q as PptxRasterizeBatchResult, r as PptxRasterizeBatchSlide, s as PptxRasterizeBatchSlideResult, t as PptxRasterizeFailureStage, u as PptxRasterizeRequest, v as PptxRasterizeResult, w as PptxRasterizer, x as PptxServiceConfig, y as PptxServiceHeaders, z as PptxServiceHeadersResolver, S as SAFE_FONTS, A as SafeFontName, B as ServicesConfig, C as clampVisualDpi, E as isSafeFont } from './types-kcQwhOlf.js';
5
- export { F as FeatureRequirement, a as FeatureRequirementCollector, O as OfficeFormat, b as OfficeRenderer, R as RENDERER_DEPENDENCY_MISSING, c as RenderOptions, d as RendererDiagnostic, e as RendererDiagnosticSeverity, f as RendererRegistry, g as RendererStatus, h as UnsupportedRendererFeatureError, i as UnsupportedRendererFeatureErrorInit, j as assertNever, k as assertRendererSupports, l as diagnoseUnsupportedFeatures, p as partitionDiagnostics, r as rendererError, m as rendererWarning } from './capabilities-DtPF3aBj.js';
5
+ import { O as OfficeFormat } from './capabilities-DtPF3aBj.js';
6
+ export { F as FeatureRequirement, a as FeatureRequirementCollector, b as OfficeRenderer, R as RENDERER_DEPENDENCY_MISSING, c as RenderOptions, d as RendererDiagnostic, e as RendererDiagnosticSeverity, f as RendererRegistry, g as RendererStatus, h as UnsupportedRendererFeatureError, i as UnsupportedRendererFeatureErrorInit, j as assertNever, k as assertRendererSupports, l as diagnoseUnsupportedFeatures, p as partitionDiagnostics, r as rendererError, m as rendererWarning } from './capabilities-DtPF3aBj.js';
6
7
  export { DEFAULT_ERROR_CONFIG, ERROR_EMOJIS, ErrorFormatterConfig, calculatePosition, clearComponentNamesCache, createErrorConfig, createJsonParseError, extractStandardComponentNames, formatErrorMessage, formatErrorSummary, getLiteralValue, getObjectSchemaPropertyNames, getSchemaMetadata, groupErrorsByPath, isLiteralSchema, isObjectSchema, isUnionSchema, transformValueError, transformValueErrors } from './validation/unified/index.js';
7
8
  export { T as TransformedError, V as ValidationError, a as ValidationResult } from './types-BWFZ7OaO.js';
8
9
  export { ComponentValidationError, ComponentValidationResult, ComponentVersion, ComponentVersionMap, CustomComponent, DuplicateComponentError, PluginValidationOptions, PluginValidationResult, RenderContext, RenderFunction, UnknownPreservedComponentError, createComponent, createVersion, getValidationSummary, isValidationSuccess, resolveComponentVersion, validateCustomComponentProps } from './plugin/index.js';
9
10
  import * as _sinclair_typebox from '@sinclair/typebox';
10
- import { Static } from '@sinclair/typebox';
11
+ import { Static, TSchema } from '@sinclair/typebox';
11
12
  export { ParsedSemver, compareSemver, isValidSemver, latestVersion, parseSemver } from './utils/semver.js';
12
13
  import '@sinclair/typebox/value';
13
14
 
@@ -1699,6 +1700,323 @@ declare function withChartFontFaceCss<T extends {
1699
1700
  };
1700
1701
  }>(props: T, faces: readonly RasterizeFontFace[], families: readonly string[]): T;
1701
1702
 
1703
+ /**
1704
+ * Content roles a definition may assign to a slot. A quality profile reads
1705
+ * them to require or measure content (an action title at most two lines, a
1706
+ * source under every chart); the theme only styles them. No role adds a
1707
+ * requirement on its own.
1708
+ */
1709
+ declare const BLOCK_SLOT_ROLES: readonly ["actionTitle", "takeaway", "source", "tracker", "footer"];
1710
+ type BlockSlotRole = (typeof BLOCK_SLOT_ROLES)[number];
1711
+ interface BlockSlot {
1712
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'component';
1713
+ description?: string;
1714
+ required?: boolean;
1715
+ default?: unknown;
1716
+ enum?: (string | number | boolean)[];
1717
+ minItems?: number;
1718
+ maxItems?: number;
1719
+ minLength?: number;
1720
+ maxLength?: number;
1721
+ minimum?: number;
1722
+ maximum?: number;
1723
+ maxWords?: number;
1724
+ oneLine?: boolean;
1725
+ items?: BlockSlot;
1726
+ properties?: Record<string, BlockSlot>;
1727
+ role?: BlockSlotRole;
1728
+ }
1729
+ /** Definitions are authored data. No concrete block is registered by the core. */
1730
+ interface JsonBlockDefinition {
1731
+ description?: string;
1732
+ slots: Record<string, BlockSlot>;
1733
+ body: unknown[];
1734
+ /** DOCX section state, applied before rendering its header and footer. */
1735
+ section?: {
1736
+ tracker?: unknown;
1737
+ header?: unknown[];
1738
+ footer?: unknown[];
1739
+ pageBreak?: boolean;
1740
+ scope?: 'section' | 'following';
1741
+ };
1742
+ /** PPTX slide settings the invocation's slide inherits unless it states its own. */
1743
+ slide?: {
1744
+ background?: unknown;
1745
+ grid?: unknown;
1746
+ notes?: unknown;
1747
+ };
1748
+ }
1749
+ declare const BlockSlotSchema: TSchema;
1750
+ declare const JsonBlockDefinitionSchema: _sinclair_typebox.TUnsafe<JsonBlockDefinition>;
1751
+ declare const BlockDefinitionsSchema: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnsafe<JsonBlockDefinition>>;
1752
+ declare const BlockInvocationPropsSchema: _sinclair_typebox.TObject<{
1753
+ ref: _sinclair_typebox.TString;
1754
+ slots: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnknown>>;
1755
+ }>;
1756
+ /** Portable JSON Schema for a single slot, also used by catalog/inspect clients. */
1757
+ declare function blockSlotJsonSchema(slot: BlockSlot): Record<string, unknown>;
1758
+
1759
+ type Rec$1 = Record<string, unknown>;
1760
+ interface BlockIssue {
1761
+ path: string;
1762
+ code: string;
1763
+ message: string;
1764
+ }
1765
+ declare class BlockEvaluationError extends Error {
1766
+ readonly issues: BlockIssue[];
1767
+ constructor(issues: BlockIssue[]);
1768
+ }
1769
+ declare const isBlockRecord: (v: unknown) => v is Rec$1;
1770
+ declare const blockPointerKey: (s: string) => string;
1771
+ declare function blockValueAt(root: unknown, path: string): unknown;
1772
+ declare function toAuthoredBlockPointer(map: Readonly<Record<string, string>>, pointer: string): string;
1773
+ /**
1774
+ * Props a component placed in a slot may not carry: placement and group
1775
+ * layout belong to the definition. Read by the runtime check below and by the
1776
+ * editor schema that flags them inline.
1777
+ */
1778
+ declare const BLOCK_SLOT_PLACEMENT_PROPS: readonly string[];
1779
+ declare const blockWordCount: (text: string) => number;
1780
+ /** Slot constraints and defaults are shared by validation and evaluation. */
1781
+ declare function resolveBlockSlot(slot: BlockSlot, input: unknown, path: string, issues: BlockIssue[]): unknown;
1782
+ declare function readBlockDefinitions(document: unknown): Record<string, JsonBlockDefinition>;
1783
+ declare function validateBlockDefinitions(definitions: unknown, format: 'docx' | 'pptx', reservedNames?: readonly string[]): BlockIssue[];
1784
+ declare function validateBlockInvocations(document: unknown, definitions: Record<string, JsonBlockDefinition>, format: 'docx' | 'pptx', reservedNames?: readonly string[]): BlockIssue[];
1785
+ interface BlockEnvironment {
1786
+ slots: Rec$1;
1787
+ slotSources?: Record<string, string>;
1788
+ source: string;
1789
+ definition: string;
1790
+ context: Rec$1;
1791
+ contextSources?: Record<string, string>;
1792
+ item?: unknown;
1793
+ itemSource?: string;
1794
+ }
1795
+ interface BlockSectionEffect {
1796
+ settings: NonNullable<JsonBlockDefinition['section']>;
1797
+ environment: BlockEnvironment;
1798
+ path: string;
1799
+ }
1800
+ interface BlockSlideEffect {
1801
+ settings: NonNullable<JsonBlockDefinition['slide']>;
1802
+ environment: BlockEnvironment;
1803
+ path: string;
1804
+ }
1805
+ interface BlockEvaluatorOptions {
1806
+ format: 'docx' | 'pptx';
1807
+ theme?: unknown;
1808
+ context?: Rec$1;
1809
+ contextSources?: Record<string, string>;
1810
+ reservedNames?: readonly string[];
1811
+ contextAt?: (path: string) => Rec$1;
1812
+ measure?: (axis: 'width' | 'height', unit: 'pt' | 'twip' | 'in', context: Rec$1) => number;
1813
+ onSection?: (effect: BlockSectionEffect) => void;
1814
+ onSlide?: (effect: BlockSlideEffect) => void;
1815
+ }
1816
+ /** Pure bounded JSON composition. Plugins are expanded by the host, never evaluated here. */
1817
+ declare class JsonBlockEvaluator {
1818
+ readonly definitions: Record<string, JsonBlockDefinition>;
1819
+ readonly options: BlockEvaluatorOptions;
1820
+ readonly sourceMap: Record<string, string>;
1821
+ readonly blocks: string[];
1822
+ private nodes;
1823
+ constructor(definitions: Record<string, JsonBlockDefinition>, options: BlockEvaluatorOptions);
1824
+ private guard;
1825
+ evaluate(value: unknown, env: BlockEnvironment, out: string, definitionPath: string, depth?: number): unknown;
1826
+ expand(value: unknown, path?: string, depth?: number): unknown;
1827
+ }
1828
+
1829
+ declare function blockSlotsJsonSchema(definition: JsonBlockDefinition): Record<string, unknown>;
1830
+ /** Authored definitions and fill pointers for exactly this document revision. */
1831
+ declare function documentBlockMetadata(document: unknown): {
1832
+ definitions: {
1833
+ name: string;
1834
+ definitionPointer: string;
1835
+ definition: JsonBlockDefinition;
1836
+ slotsSchema: Record<string, unknown>;
1837
+ }[];
1838
+ invocations: {
1839
+ ref: string;
1840
+ path: string;
1841
+ slotsPath: string;
1842
+ defined: boolean;
1843
+ }[];
1844
+ invalidDefinitions: boolean;
1845
+ };
1846
+ /** Compiled pointer → authored pointer. */
1847
+ type BlockSourceMap = Readonly<Record<string, string>>;
1848
+ /** A document with every block lowered in place, and how to get back. */
1849
+ interface ExpandedBlocks<T> {
1850
+ document: T;
1851
+ sourceMap: BlockSourceMap;
1852
+ /** Authored pointers of every expanded invocation, in document order. */
1853
+ blocks: readonly string[];
1854
+ }
1855
+ interface BlockSlotBudget {
1856
+ block: string;
1857
+ slot: string;
1858
+ path: string;
1859
+ words: number;
1860
+ maxWords: number;
1861
+ }
1862
+ interface BlockSlotRoleValue {
1863
+ block: string;
1864
+ /** Authored pointer of the invocation. */
1865
+ invocation: string;
1866
+ slot: string;
1867
+ role: BlockSlotRole;
1868
+ /** Authored pointer of the slot value, whether or not one was supplied. */
1869
+ path: string;
1870
+ /** The resolved value after defaults; undefined when absent. */
1871
+ value: unknown;
1872
+ }
1873
+ /** Metadata is always read from authored definitions, never from a named catalog. */
1874
+ declare function blockSlotBudgets(document: unknown, blocks: readonly string[]): BlockSlotBudget[];
1875
+ /**
1876
+ * Every role-bearing slot of every invocation, present or not, so a profile
1877
+ * can require one (a source under a chart) and measure another (an action
1878
+ * title's length) at the authored pointer the author can patch.
1879
+ */
1880
+ declare function blockSlotRoles(document: unknown, blocks: readonly string[]): BlockSlotRoleValue[];
1881
+
1882
+ type Schema$1 = Record<string, any>;
1883
+ /**
1884
+ * Derive authoring from the renderer/plugin schemas without weakening ordinary
1885
+ * documents. Each value retains its literal schema and receives only directives
1886
+ * whose result family can fit. Defaults and conditional branches recurse into
1887
+ * that same value schema; repetition templates use the actual array item schema.
1888
+ *
1889
+ * Dispatch uses standard draft-07 conditionals, not overlapping anyOf branches:
1890
+ * existing literal keys keep literal completion, and a directive selects only
1891
+ * its own options. Empty/incomplete objects offer literal keys and directive
1892
+ * starters. Memoized references keep recursive schemas finite and avoid copying
1893
+ * the component graph into every default/then/else branch.
1894
+ */
1895
+ declare function createBlockAuthoringSchema(definitions: Record<string, Schema$1>, componentDefinition: string, excludedComponents?: readonly string[], format?: OfficeFormat): Schema$1;
1896
+
1897
+ type Rec = Record<string, unknown>;
1898
+ interface BlockCompositionOptions {
1899
+ /** Registered code component names. JSON never loads or installs them. */
1900
+ plugins: ReadonlySet<string>;
1901
+ /** Expand one registered component at its authored path into standard output. */
1902
+ render: (component: Rec, path: string) => Promise<unknown[]>;
1903
+ /** Plugin names kept unexpanded in the `preserved` tree (schema export, inspection). */
1904
+ preserve?: ReadonlySet<string>;
1905
+ }
1906
+ interface BlockComposition {
1907
+ /** Every block and plugin lowered to standard components. */
1908
+ standard: unknown;
1909
+ /** The same tree with preserved plugins left as authored. */
1910
+ preserved: unknown;
1911
+ }
1912
+ /**
1913
+ * One bounded expansion for document-local JSON and registered code, in both
1914
+ * directions: a plugin can emit a block, a block body or component slot can
1915
+ * name a plugin, and either can nest. Provenance survives each boundary
1916
+ * through the evaluator's source map; emitted output is wrapped in a `group`
1917
+ * whose pointer maps back to the plugin's authored node.
1918
+ *
1919
+ * Format-neutral: the host supplies the evaluator (its format, theme and
1920
+ * context) and validates the finished tree.
1921
+ */
1922
+ declare function composeBlocksWithPlugins(evaluator: JsonBlockEvaluator, document: unknown, options: BlockCompositionOptions): Promise<BlockComposition>;
1923
+
1924
+ type Schema = Record<string, any>;
1925
+ /** A block invocation as authored: the component the editor inserts. */
1926
+ interface BlockInvocationExample {
1927
+ name: 'block';
1928
+ props: {
1929
+ ref: string;
1930
+ slots?: Record<string, unknown>;
1931
+ };
1932
+ }
1933
+ /**
1934
+ * A slot's contract as short facts, in one order, for every place that shows
1935
+ * it: the editor hover, the AI prompt, a catalog summary. "Required" means
1936
+ * the caller must supply a value — a slot with a default never is.
1937
+ */
1938
+ declare function blockSlotFacts(slot: BlockSlot): string[];
1939
+ /** The hover text for a slot: its description, then its contract in one line. */
1940
+ declare function blockSlotMarkdown(slot: BlockSlot): string;
1941
+ /**
1942
+ * JSON Schema for one slot as the editor should see it. Unlike the portable
1943
+ * `blockSlotJsonSchema`, a component slot references the real component
1944
+ * definition — so a chart placed in it completes like any other chart — with
1945
+ * the placement props the runtime rejects flagged at the key they appear on.
1946
+ */
1947
+ declare function blockSlotEditorSchema(slot: BlockSlot, componentRef?: Schema): Schema;
1948
+ /** The `slots` object of an invocation of this definition. */
1949
+ declare function blockSlotsEditorSchema(definition: JsonBlockDefinition, componentRef?: Schema): Schema;
1950
+ /**
1951
+ * The `props` of a `block` component given this document's definitions:
1952
+ * `ref` enumerates the names with their descriptions, and each name
1953
+ * dispatches `slots` to its own schema. With no definitions the reference
1954
+ * stays a free string — the runtime says which name is missing.
1955
+ */
1956
+ declare function blockInvocationPropsSchema(definitions: Record<string, JsonBlockDefinition>, componentRef?: Schema): Schema;
1957
+ /** Where the document-aware invocation props go in an exported schema. */
1958
+ interface DocumentBlockTarget {
1959
+ /** A component definition under `definitions`, typically one per renderer. */
1960
+ name: string;
1961
+ /**
1962
+ * What a component slot accepts — the content a slide or a section holds,
1963
+ * as a reference into the same schema. Omitted, a component slot only asks
1964
+ * for a `name`.
1965
+ */
1966
+ componentRef?: Schema;
1967
+ }
1968
+ /**
1969
+ * Install the document-aware invocation props on every `block` branch inside
1970
+ * the targeted component definitions — the definition's own branch and the
1971
+ * copies a container inlines for its children — so an invocation completes
1972
+ * the same wherever a slide or section places it. References out of the
1973
+ * definition are not followed: block bodies live in their own derived
1974
+ * definitions and keep their binding-aware props. Mutates in place; call on
1975
+ * a copy of the shared schema.
1976
+ */
1977
+ declare function applyDocumentBlocksToSchema(schema: Schema, definitions: Record<string, JsonBlockDefinition>, targets: readonly DocumentBlockTarget[]): void;
1978
+ /**
1979
+ * The definitions a block needs beside itself, dependencies first, so a
1980
+ * copied definition never leaves an unresolved reference behind. Unknown
1981
+ * references and cycles are skipped: the runtime reports those.
1982
+ */
1983
+ declare function blockDependencies(definitions: Record<string, JsonBlockDefinition>, name: string): string[];
1984
+ /**
1985
+ * A valid invocation to insert: the first one the source document makes, if
1986
+ * it makes one — real content, at the cardinality its author chose — else
1987
+ * one synthesized from the slots at typical cardinality.
1988
+ */
1989
+ declare function blockInvocationExample(name: string, definition: JsonBlockDefinition, options: {
1990
+ document?: unknown;
1991
+ format: OfficeFormat;
1992
+ }): BlockInvocationExample;
1993
+ /** An authoring reference extracted from a complete document. */
1994
+ interface BlockReference {
1995
+ name: string;
1996
+ format: OfficeFormat;
1997
+ /** The document the definition comes from. */
1998
+ template: string;
1999
+ definitionPointer: string;
2000
+ description: string;
2001
+ definition: JsonBlockDefinition;
2002
+ /** Portable slot schema, as `jto://blocks` publishes it. */
2003
+ slotsSchema: Record<string, unknown>;
2004
+ /** A valid invocation at typical cardinality. */
2005
+ example: BlockInvocationExample;
2006
+ /** Other definitions of the same document this one invokes, dependencies first. */
2007
+ dependencies: string[];
2008
+ }
2009
+ /**
2010
+ * Every block a complete document defines, as a reference an editor or an
2011
+ * agent can copy: definition, dependencies and a working invocation. A
2012
+ * document whose definitions do not validate contributes nothing — a
2013
+ * reference must be copyable as is.
2014
+ */
2015
+ declare function blockReferencesFromDocument(document: unknown, source: {
2016
+ template: string;
2017
+ format: OfficeFormat;
2018
+ }): BlockReference[];
2019
+
1702
2020
  /**
1703
2021
  * Deep Merge Utilities
1704
2022
  * Generic deep-merge helpers used by both docx and pptx
@@ -1712,4 +2030,4 @@ declare function withChartFontFaceCss<T extends {
1712
2030
  */
1713
2031
  declare function mergeWithDefaults<T>(userConfig: T, themeDefaults: Partial<T>): T;
1714
2032
 
1715
- export { CANVASES, type ChartTypography, ChromeSchema, DEFAULT_CHART_THEME_COLORS, type DesignCanvas, DesignSpacingSchema, type DesignSystem, DesignSystemProperties, DesignSystemSchema, FONT_URL_ALLOWLIST, type FontIssueCode, FontRegistry, FontRegistryEntry, type FontRegistryInput, type FontResolutionIssue, FontRuntimeOpts, type FontSubstitution, type FontValidationInput, type FontValidationResult, MotifSchema, POINTS_PER_PIXEL_96DPI, POPULAR_GOOGLE_FONTS, PaletteSchema, type PopularGoogleFont, ROLE_SCALE_STEPS, RasterizeFontFace, ResolvedFont, ResolvedFontSource, type SynthesizedFamily, TYPE_ROLES, TextCaseSchema, type TypeRole, type TypeRoleName, TypeRoleNameSchema, TypeRoleSchema, TypeRolesSchema, TypographySchema, UPSTREAM_OVERRIDES, type UpstreamOverride, type UpstreamVariant, WEIGHT_LABELS, applyExportMode, applyFontSubstitution, buildDefaultSubstitutionMap, capsFormatting, chartFamilyResolver, chartFontFaceCss, chartPointsPerPixel, collectFontNamesFromDocx, collectFontNamesFromPptx, cssFontFamily, defaultSubstituteFor, designCanvas, designColors, detectFontFormat, documentFontRegistry, fetchGoogleFontSources, getUpstreamOverride, isAllowedFontUrl, mergeFontRegistries, mergeWithDefaults, resolveDesignColor, resolveTypeRoles, restructureNameDiscriminatedUnions, rewriteFontFamilyName, synthesizeFamilyName, themeFontRegistry, unionBranches, validateDesignColors, validateFontReferences, withChartFontFaceCss, withChartTypography };
2033
+ export { BLOCK_SLOT_PLACEMENT_PROPS, BLOCK_SLOT_ROLES, type BlockComposition, type BlockCompositionOptions, BlockDefinitionsSchema, type BlockEnvironment, BlockEvaluationError, type BlockEvaluatorOptions, type BlockInvocationExample, BlockInvocationPropsSchema, type BlockIssue, type BlockReference, type BlockSectionEffect, type BlockSlideEffect, type BlockSlot, type BlockSlotBudget, type BlockSlotRole, type BlockSlotRoleValue, BlockSlotSchema, type BlockSourceMap, CANVASES, type ChartTypography, ChromeSchema, DEFAULT_CHART_THEME_COLORS, type DesignCanvas, DesignSpacingSchema, type DesignSystem, DesignSystemProperties, DesignSystemSchema, type DocumentBlockTarget, type ExpandedBlocks, FONT_URL_ALLOWLIST, type FontIssueCode, FontRegistry, FontRegistryEntry, type FontRegistryInput, type FontResolutionIssue, FontRuntimeOpts, type FontSubstitution, type FontValidationInput, type FontValidationResult, type JsonBlockDefinition, JsonBlockDefinitionSchema, JsonBlockEvaluator, MotifSchema, OfficeFormat, POINTS_PER_PIXEL_96DPI, POPULAR_GOOGLE_FONTS, PaletteSchema, type PopularGoogleFont, ROLE_SCALE_STEPS, RasterizeFontFace, ResolvedFont, ResolvedFontSource, type SynthesizedFamily, TYPE_ROLES, TextCaseSchema, type TypeRole, type TypeRoleName, TypeRoleNameSchema, TypeRoleSchema, TypeRolesSchema, TypographySchema, UPSTREAM_OVERRIDES, type UpstreamOverride, type UpstreamVariant, WEIGHT_LABELS, applyDocumentBlocksToSchema, applyExportMode, applyFontSubstitution, blockDependencies, blockInvocationExample, blockInvocationPropsSchema, blockPointerKey, blockReferencesFromDocument, blockSlotBudgets, blockSlotEditorSchema, blockSlotFacts, blockSlotJsonSchema, blockSlotMarkdown, blockSlotRoles, blockSlotsEditorSchema, blockSlotsJsonSchema, blockValueAt, blockWordCount, buildDefaultSubstitutionMap, capsFormatting, chartFamilyResolver, chartFontFaceCss, chartPointsPerPixel, collectFontNamesFromDocx, collectFontNamesFromPptx, composeBlocksWithPlugins, createBlockAuthoringSchema, cssFontFamily, defaultSubstituteFor, designCanvas, designColors, detectFontFormat, documentBlockMetadata, documentFontRegistry, fetchGoogleFontSources, getUpstreamOverride, isAllowedFontUrl, isBlockRecord, mergeFontRegistries, mergeWithDefaults, readBlockDefinitions, resolveBlockSlot, resolveDesignColor, resolveTypeRoles, restructureNameDiscriminatedUnions, rewriteFontFamilyName, synthesizeFamilyName, themeFontRegistry, toAuthoredBlockPointer, unionBranches, validateBlockDefinitions, validateBlockInvocations, validateDesignColors, validateFontReferences, withChartFontFaceCss, withChartTypography };