@json-to-office/shared 0.29.0 → 0.33.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-5J43F4XD.js → chunk-KLWNDWC4.js} +106 -2
- package/dist/chunk-KLWNDWC4.js.map +1 -0
- package/dist/index.d.ts +67 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas/schema-utils.js +1 -1
- package/dist/schemas/slide-content.js +1 -1
- package/dist/schemas/slide-content.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5J43F4XD.js.map +0 -1
|
@@ -1,5 +1,104 @@
|
|
|
1
1
|
// src/schemas/schema-utils.ts
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
|
+
|
|
4
|
+
// src/schemas/discriminated-unions.ts
|
|
5
|
+
function branchNameConst(branch) {
|
|
6
|
+
if (typeof branch !== "object" || branch === null || Array.isArray(branch))
|
|
7
|
+
return void 0;
|
|
8
|
+
const name = branch.properties?.name;
|
|
9
|
+
return typeof name?.const === "string" ? name.const : void 0;
|
|
10
|
+
}
|
|
11
|
+
function isVersionedBranch(branch) {
|
|
12
|
+
const version = branch.properties?.version;
|
|
13
|
+
return typeof version?.const === "string";
|
|
14
|
+
}
|
|
15
|
+
function branchRequiresName(branch) {
|
|
16
|
+
return Array.isArray(branch.required) && branch.required.includes("name");
|
|
17
|
+
}
|
|
18
|
+
function groupByName(branches) {
|
|
19
|
+
const groups = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const branch of branches) {
|
|
21
|
+
const name = branchNameConst(branch);
|
|
22
|
+
const group = groups.get(name);
|
|
23
|
+
if (group) group.push(branch);
|
|
24
|
+
else groups.set(name, [branch]);
|
|
25
|
+
}
|
|
26
|
+
return groups;
|
|
27
|
+
}
|
|
28
|
+
function nameEntry(name, group) {
|
|
29
|
+
const source = group.find(
|
|
30
|
+
(b) => !isVersionedBranch(b) && typeof b.description === "string"
|
|
31
|
+
) ?? group.find((b) => typeof b.description === "string");
|
|
32
|
+
return {
|
|
33
|
+
const: name,
|
|
34
|
+
type: "string",
|
|
35
|
+
...source ? { description: source.description } : {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function restructureNameDiscriminatedUnions(schema) {
|
|
39
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
40
|
+
function walk(node) {
|
|
41
|
+
if (typeof node !== "object" || node === null) return;
|
|
42
|
+
if (visited.has(node)) return;
|
|
43
|
+
visited.add(node);
|
|
44
|
+
if (Array.isArray(node)) {
|
|
45
|
+
node.forEach(walk);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const obj = node;
|
|
49
|
+
const anyOf = obj.anyOf;
|
|
50
|
+
const isCandidate = Array.isArray(anyOf) && anyOf.length >= 2 && anyOf.every(
|
|
51
|
+
(b) => branchNameConst(b) !== void 0 && branchRequiresName(b)
|
|
52
|
+
) && obj.properties === void 0 && obj.allOf === void 0 && obj.if === void 0 && obj.required === void 0 && // A sibling `additionalProperties` evaluates against the node's own
|
|
53
|
+
// (absent) `properties`; declaring `name` here would change what it
|
|
54
|
+
// rejects, so such unions are left alone.
|
|
55
|
+
obj.additionalProperties === void 0 && (obj.type === void 0 || obj.type === "object");
|
|
56
|
+
const groups = isCandidate ? groupByName(anyOf) : void 0;
|
|
57
|
+
if (groups && groups.size >= 2) {
|
|
58
|
+
obj.type = "object";
|
|
59
|
+
obj.required = ["name"];
|
|
60
|
+
obj.properties = {
|
|
61
|
+
name: {
|
|
62
|
+
anyOf: [...groups.entries()].map(
|
|
63
|
+
([name, group]) => nameEntry(name, group)
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
obj.allOf = [...groups.entries()].map(([name, group]) => ({
|
|
68
|
+
if: {
|
|
69
|
+
properties: { name: { const: name } },
|
|
70
|
+
required: ["name"]
|
|
71
|
+
},
|
|
72
|
+
then: group.length === 1 ? group[0] : { anyOf: group }
|
|
73
|
+
}));
|
|
74
|
+
delete obj.anyOf;
|
|
75
|
+
}
|
|
76
|
+
for (const value of Object.values(obj)) walk(value);
|
|
77
|
+
}
|
|
78
|
+
walk(schema);
|
|
79
|
+
}
|
|
80
|
+
function unionBranches(schema) {
|
|
81
|
+
if (typeof schema !== "object" || schema === null) return [];
|
|
82
|
+
const obj = schema;
|
|
83
|
+
if (Array.isArray(obj.anyOf)) {
|
|
84
|
+
return obj.anyOf.filter(
|
|
85
|
+
(b) => typeof b === "object" && b !== null
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (Array.isArray(obj.allOf)) {
|
|
89
|
+
return obj.allOf.flatMap((entry) => {
|
|
90
|
+
const then = entry?.then;
|
|
91
|
+
if (typeof then !== "object" || then === null) return [];
|
|
92
|
+
const inner = then.anyOf;
|
|
93
|
+
return Array.isArray(inner) ? inner.filter(
|
|
94
|
+
(b) => typeof b === "object" && b !== null
|
|
95
|
+
) : [then];
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/schemas/schema-utils.ts
|
|
3
102
|
function replaceRefs(obj, target, replacement) {
|
|
4
103
|
if (typeof obj !== "object" || obj === null) return;
|
|
5
104
|
if (Array.isArray(obj)) {
|
|
@@ -31,7 +130,9 @@ function fixSchemaReferences(schema, rootDefinitionName = "ComponentDefinition")
|
|
|
31
130
|
$ref: `#/definitions/${rootDefinitionName}`
|
|
32
131
|
};
|
|
33
132
|
}
|
|
34
|
-
if (schemaValue.type === "array" && schemaValue.items && typeof schemaValue.items === "object" && "$ref" in schemaValue.items && typeof schemaValue.items.$ref === "string" && /^T\d+$/.test(
|
|
133
|
+
if (schemaValue.type === "array" && schemaValue.items && typeof schemaValue.items === "object" && "$ref" in schemaValue.items && typeof schemaValue.items.$ref === "string" && /^T\d+$/.test(
|
|
134
|
+
schemaValue.items.$ref
|
|
135
|
+
)) {
|
|
35
136
|
schemaValue.items = {
|
|
36
137
|
$ref: `#/definitions/${rootDefinitionName}`
|
|
37
138
|
};
|
|
@@ -101,6 +202,7 @@ function convertToJsonSchema(schema, options = {}) {
|
|
|
101
202
|
jsonSchema.definitions = extractedDefinitions;
|
|
102
203
|
}
|
|
103
204
|
fixSchemaReferences(jsonSchema);
|
|
205
|
+
restructureNameDiscriminatedUnions(jsonSchema);
|
|
104
206
|
return jsonSchema;
|
|
105
207
|
}
|
|
106
208
|
function createComponentSchema(name, config, containerNames, componentDefinitionSchema) {
|
|
@@ -172,10 +274,12 @@ function createComponentSchemaObject(component, recursiveRef) {
|
|
|
172
274
|
}
|
|
173
275
|
|
|
174
276
|
export {
|
|
277
|
+
restructureNameDiscriminatedUnions,
|
|
278
|
+
unionBranches,
|
|
175
279
|
fixSchemaReferences,
|
|
176
280
|
convertToJsonSchema,
|
|
177
281
|
createComponentSchema,
|
|
178
282
|
exportSchemaToFile,
|
|
179
283
|
createComponentSchemaObject
|
|
180
284
|
};
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
285
|
+
//# sourceMappingURL=chunk-KLWNDWC4.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\nexport function fixSchemaReferences(\n schema: Record<string, unknown>,\n rootDefinitionName = 'ComponentDefinition'\n): void {\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 if (\n schemaValue.type === 'array' &&\n schemaValue.items &&\n Object.keys(schemaValue.items).length === 0\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 typeof (schemaValue.items as Record<string, unknown>).$ref ===\n 'string' &&\n /^T\\d+$/.test(\n (schemaValue.items as Record<string, unknown>).$ref as string\n )\n ) {\n schemaValue.items = {\n $ref: `#/definitions/${rootDefinitionName}`,\n };\n }\n\n if (\n typeof schemaValue.$ref === 'string' &&\n (/^T\\d+$/.test(schemaValue.$ref as string) ||\n schemaValue.$ref === rootDefinitionName)\n ) {\n schemaValue.$ref = `#/definitions/${rootDefinitionName}`;\n }\n\n if (\n key === '$id' &&\n typeof value === 'string' &&\n (/^T\\d+$/.test(value) || value === rootDefinitionName) &&\n currentPath !== `definitions.${rootDefinitionName}.$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): Record<string, unknown> {\n const {\n $schema = 'https://json-schema.org/draft-07/schema#',\n $id,\n title,\n description,\n definitions = {},\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 restructureNameDiscriminatedUnions(jsonSchema);\n\n return jsonSchema;\n}\n\nexport function createComponentSchema(\n name: string,\n config: ComponentSchemaConfig,\n containerNames: string[],\n componentDefinitionSchema?: TSchema\n): Record<string, unknown> {\n const componentStructure: Record<string, unknown> = {\n $schema: 'https://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/ComponentDefinition',\n },\n };\n\n if (componentDefinitionSchema) {\n componentStructure.definitions = {\n ComponentDefinition: JSON.parse(\n JSON.stringify(componentDefinitionSchema)\n ),\n };\n }\n }\n\n fixSchemaReferences(componentStructure);\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 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
|
@@ -143,6 +143,72 @@ interface ServicesConfig {
|
|
|
143
143
|
pptx?: PptxServiceConfig;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Canonical `if/then` restructuring for name-discriminated component unions.
|
|
148
|
+
*
|
|
149
|
+
* The generators export component unions as a flat `anyOf`. Schema-driven
|
|
150
|
+
* editors (Monaco, VS Code — vscode-json-languageservice) resolve a partially
|
|
151
|
+
* typed node against an `anyOf` by picking the single best-matching branch:
|
|
152
|
+
* while typing `{ "name": | }`, every branch requiring `props` fails
|
|
153
|
+
* validation, so its name const never reached autocomplete, and diagnostics
|
|
154
|
+
* reported one arbitrary branch's complaints ("Value must be \"heading\"",
|
|
155
|
+
* "Missing property \"props\"") instead of the real problem.
|
|
156
|
+
*
|
|
157
|
+
* This transform rewrites each such union — at JSON-Schema export time only,
|
|
158
|
+
* the runtime TypeBox validators are untouched — into the standard
|
|
159
|
+
* discriminated-union dispatch:
|
|
160
|
+
*
|
|
161
|
+
* {
|
|
162
|
+
* type: "object",
|
|
163
|
+
* required: ["name"],
|
|
164
|
+
* properties: { name: { anyOf: [{ const, description }, …] } },
|
|
165
|
+
* allOf: [
|
|
166
|
+
* { if: { properties: { name: { const } }, required: ["name"] },
|
|
167
|
+
* then: <branch> },
|
|
168
|
+
* …
|
|
169
|
+
* ]
|
|
170
|
+
* }
|
|
171
|
+
*
|
|
172
|
+
* The accepted set of documents is exactly the same — `properties.name` is
|
|
173
|
+
* the enum the branches already imply, and each `then` is the original
|
|
174
|
+
* branch — but editors now behave deterministically:
|
|
175
|
+
* - completing `name` offers every component, with its description
|
|
176
|
+
* - an empty object reports only `Missing property "name"`
|
|
177
|
+
* - a wrong name reports only `Value is not accepted. Valid values: …`
|
|
178
|
+
* - a valid name activates exactly its branch for keys, props and errors
|
|
179
|
+
*
|
|
180
|
+
* Standard draft-07 keywords only, so ajv and every schema-aware editor
|
|
181
|
+
* agree. Versioned plugin branches share a name; they stay grouped in a
|
|
182
|
+
* small `anyOf` inside their `then`, containing best-match ambiguity to the
|
|
183
|
+
* component's own versions.
|
|
184
|
+
*/
|
|
185
|
+
interface SchemaNode {
|
|
186
|
+
[key: string]: unknown;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Walk a JSON Schema and restructure every `anyOf` union whose branches are
|
|
190
|
+
* all name-discriminated objects into the `if/then` dispatch shape above.
|
|
191
|
+
*
|
|
192
|
+
* Mutates in place. Conservative by design — a union is only restructured
|
|
193
|
+
* when the rewrite is provably equivalent:
|
|
194
|
+
* - every branch is an object with a `name` const that lists `name` as
|
|
195
|
+
* required (unions containing `$ref` or free-form branches are left alone;
|
|
196
|
+
* a `$ref`'s target union is restructured where it is defined)
|
|
197
|
+
* - the node declares no `properties`, `allOf`, `if`, `required`,
|
|
198
|
+
* `additionalProperties` or `type` of its own that the rewrite would have
|
|
199
|
+
* to merge with
|
|
200
|
+
* - at least two distinct names; single-name unions (a versioned plugin's
|
|
201
|
+
* variants) validate and complete fine as a plain anyOf
|
|
202
|
+
*/
|
|
203
|
+
declare function restructureNameDiscriminatedUnions(schema: unknown): void;
|
|
204
|
+
/**
|
|
205
|
+
* Iterate the component branches of an exported union, whichever shape it is
|
|
206
|
+
* in — the flat `anyOf` the generators emit, or the `if/then` dispatch this
|
|
207
|
+
* module rewrites it into. For consumers that post-process branch objects
|
|
208
|
+
* (description enhancement, theme-name injection, …).
|
|
209
|
+
*/
|
|
210
|
+
declare function unionBranches(schema: unknown): SchemaNode[];
|
|
211
|
+
|
|
146
212
|
/** Scan an arbitrary doc tree (DOCX or PPTX) for every font family referenced. */
|
|
147
213
|
declare function collectFontNames(doc: unknown): Set<string>;
|
|
148
214
|
/** Scan a DOCX document tree for every font family name referenced. */
|
|
@@ -628,4 +694,4 @@ declare const DEFAULT_CHART_THEME_COLORS: string[];
|
|
|
628
694
|
*/
|
|
629
695
|
declare function mergeWithDefaults<T>(userConfig: T, themeDefaults: Partial<T>): T;
|
|
630
696
|
|
|
631
|
-
export { DEFAULT_CHART_THEME_COLORS, DEFAULT_VISUAL_DPI, type FontIssueCode, FontRegistry, FontRegistryEntry, type FontRegistryInput, type FontResolutionIssue, FontRuntimeOpts, type FontSubstitution, type FontValidationInput, type FontValidationResult, type HighchartsHeaders, type HighchartsHeadersResolver, type HighchartsServiceConfig, MAX_RASTERIZE_BATCH_SLIDES, MAX_VISUAL_DPI, MIN_VISUAL_DPI, POPULAR_GOOGLE_FONTS, type PopularGoogleFont, type PptxBatchRasterizer, type PptxRasterizeBatchRequest, type PptxRasterizeBatchResult, type PptxRasterizeBatchSlide, type PptxRasterizeBatchSlideResult, type PptxRasterizeFailureStage, type PptxRasterizeRequest, type PptxRasterizeResult, type PptxRasterizer, type PptxServiceConfig, type PptxServiceHeaders, type PptxServiceHeadersResolver, ResolvedFont, ResolvedFontSource, type ServicesConfig, type SynthesizedFamily, UPSTREAM_OVERRIDES, type UpstreamOverride, type UpstreamVariant, WEIGHT_LABELS, applyExportMode, applyFontSubstitution, buildDefaultSubstitutionMap, clampVisualDpi, collectFontNamesFromDocx, collectFontNamesFromPptx, defaultSubstituteFor, detectFontFormat, fetchGoogleFontSources, getUpstreamOverride, mergeWithDefaults, rewriteFontFamilyName, scopedThemeName, synthesizeFamilyName, validateFontReferences };
|
|
697
|
+
export { DEFAULT_CHART_THEME_COLORS, DEFAULT_VISUAL_DPI, type FontIssueCode, FontRegistry, FontRegistryEntry, type FontRegistryInput, type FontResolutionIssue, FontRuntimeOpts, type FontSubstitution, type FontValidationInput, type FontValidationResult, type HighchartsHeaders, type HighchartsHeadersResolver, type HighchartsServiceConfig, MAX_RASTERIZE_BATCH_SLIDES, MAX_VISUAL_DPI, MIN_VISUAL_DPI, POPULAR_GOOGLE_FONTS, type PopularGoogleFont, type PptxBatchRasterizer, type PptxRasterizeBatchRequest, type PptxRasterizeBatchResult, type PptxRasterizeBatchSlide, type PptxRasterizeBatchSlideResult, type PptxRasterizeFailureStage, type PptxRasterizeRequest, type PptxRasterizeResult, type PptxRasterizer, type PptxServiceConfig, type PptxServiceHeaders, type PptxServiceHeadersResolver, ResolvedFont, ResolvedFontSource, type ServicesConfig, type SynthesizedFamily, UPSTREAM_OVERRIDES, type UpstreamOverride, type UpstreamVariant, WEIGHT_LABELS, applyExportMode, applyFontSubstitution, buildDefaultSubstitutionMap, clampVisualDpi, collectFontNamesFromDocx, collectFontNamesFromPptx, defaultSubstituteFor, detectFontFormat, fetchGoogleFontSources, getUpstreamOverride, mergeWithDefaults, restructureNameDiscriminatedUnions, rewriteFontFamilyName, scopedThemeName, synthesizeFamilyName, unionBranches, validateFontReferences };
|
package/dist/index.js
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
createComponentSchema,
|
|
8
8
|
createComponentSchemaObject,
|
|
9
9
|
exportSchemaToFile,
|
|
10
|
-
fixSchemaReferences
|
|
11
|
-
|
|
10
|
+
fixSchemaReferences,
|
|
11
|
+
restructureNameDiscriminatedUnions,
|
|
12
|
+
unionBranches
|
|
13
|
+
} from "./chunk-KLWNDWC4.js";
|
|
12
14
|
import {
|
|
13
15
|
FontFamilyNameSchema,
|
|
14
16
|
FontRegistryEntrySchema,
|
|
@@ -1451,11 +1453,13 @@ export {
|
|
|
1451
1453
|
mergeWithDefaults,
|
|
1452
1454
|
parseSemver,
|
|
1453
1455
|
resolveComponentVersion,
|
|
1456
|
+
restructureNameDiscriminatedUnions,
|
|
1454
1457
|
rewriteFontFamilyName,
|
|
1455
1458
|
scopedThemeName,
|
|
1456
1459
|
synthesizeFamilyName,
|
|
1457
1460
|
transformValueError,
|
|
1458
1461
|
transformValueErrors,
|
|
1462
|
+
unionBranches,
|
|
1459
1463
|
validateCustomComponentProps,
|
|
1460
1464
|
validateFontReferences
|
|
1461
1465
|
};
|