@hirokisakabe/pom 5.2.0 → 5.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.
Files changed (106) hide show
  1. package/README.md +10 -11
  2. package/dist/autoFit/autoFit.d.ts +2 -1
  3. package/dist/autoFit/autoFit.d.ts.map +1 -1
  4. package/dist/autoFit/autoFit.js +7 -7
  5. package/dist/autoFit/strategies/reduceFontSize.js +1 -1
  6. package/dist/autoFit/strategies/reduceGapAndPadding.js +1 -1
  7. package/dist/autoFit/strategies/reduceTableRowHeight.js +1 -1
  8. package/dist/autoFit/strategies/uniformScale.js +1 -1
  9. package/dist/buildContext.d.ts +12 -0
  10. package/dist/buildContext.d.ts.map +1 -0
  11. package/dist/buildContext.js +8 -0
  12. package/dist/buildPptx.d.ts +1 -1
  13. package/dist/buildPptx.d.ts.map +1 -1
  14. package/dist/buildPptx.js +15 -15
  15. package/dist/calcYogaLayout/calcYogaLayout.d.ts +3 -1
  16. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  17. package/dist/calcYogaLayout/calcYogaLayout.js +43 -371
  18. package/dist/calcYogaLayout/measureText.d.ts +1 -5
  19. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  20. package/dist/calcYogaLayout/measureText.js +2 -10
  21. package/dist/icons/renderIcon.d.ts +1 -1
  22. package/dist/icons/renderIcon.d.ts.map +1 -1
  23. package/dist/icons/renderIcon.js +3 -4
  24. package/dist/parseXml/coercionRules.d.ts +35 -0
  25. package/dist/parseXml/coercionRules.d.ts.map +1 -0
  26. package/dist/parseXml/coercionRules.js +479 -0
  27. package/dist/parseXml/inputSchema.d.ts +22 -105
  28. package/dist/parseXml/inputSchema.d.ts.map +1 -1
  29. package/dist/parseXml/inputSchema.js +5 -3
  30. package/dist/parseXml/parseXml.d.ts.map +1 -1
  31. package/dist/parseXml/parseXml.js +48 -277
  32. package/dist/registry/definitions/box.d.ts +3 -0
  33. package/dist/registry/definitions/box.d.ts.map +1 -0
  34. package/dist/registry/definitions/box.js +6 -0
  35. package/dist/registry/definitions/chart.d.ts +3 -0
  36. package/dist/registry/definitions/chart.d.ts.map +1 -0
  37. package/dist/registry/definitions/chart.js +8 -0
  38. package/dist/registry/definitions/compositeNodes.d.ts +8 -0
  39. package/dist/registry/definitions/compositeNodes.d.ts.map +1 -0
  40. package/dist/registry/definitions/compositeNodes.js +81 -0
  41. package/dist/registry/definitions/icon.d.ts +3 -0
  42. package/dist/registry/definitions/icon.d.ts.map +1 -0
  43. package/dist/registry/definitions/icon.js +50 -0
  44. package/dist/registry/definitions/image.d.ts +3 -0
  45. package/dist/registry/definitions/image.d.ts.map +1 -0
  46. package/dist/registry/definitions/image.js +34 -0
  47. package/dist/registry/definitions/layer.d.ts +3 -0
  48. package/dist/registry/definitions/layer.d.ts.map +1 -0
  49. package/dist/registry/definitions/layer.js +49 -0
  50. package/dist/registry/definitions/line.d.ts +3 -0
  51. package/dist/registry/definitions/line.d.ts.map +1 -0
  52. package/dist/registry/definitions/line.js +26 -0
  53. package/dist/registry/definitions/list.d.ts +4 -0
  54. package/dist/registry/definitions/list.d.ts.map +1 -0
  55. package/dist/registry/definitions/list.js +53 -0
  56. package/dist/registry/definitions/shape.d.ts +3 -0
  57. package/dist/registry/definitions/shape.d.ts.map +1 -0
  58. package/dist/registry/definitions/shape.js +37 -0
  59. package/dist/registry/definitions/stack.d.ts +4 -0
  60. package/dist/registry/definitions/stack.d.ts.map +1 -0
  61. package/dist/registry/definitions/stack.js +78 -0
  62. package/dist/registry/definitions/table.d.ts +3 -0
  63. package/dist/registry/definitions/table.d.ts.map +1 -0
  64. package/dist/registry/definitions/table.js +16 -0
  65. package/dist/registry/definitions/text.d.ts +3 -0
  66. package/dist/registry/definitions/text.d.ts.map +1 -0
  67. package/dist/registry/definitions/text.js +35 -0
  68. package/dist/registry/index.d.ts +2 -0
  69. package/dist/registry/index.d.ts.map +1 -0
  70. package/dist/registry/index.js +34 -0
  71. package/dist/registry/nodeRegistry.d.ts +7 -0
  72. package/dist/registry/nodeRegistry.d.ts.map +1 -0
  73. package/dist/registry/nodeRegistry.js +13 -0
  74. package/dist/registry/types.d.ts +26 -0
  75. package/dist/registry/types.d.ts.map +1 -0
  76. package/dist/registry/types.js +1 -0
  77. package/dist/renderPptx/nodes/icon.d.ts.map +1 -1
  78. package/dist/renderPptx/nodes/icon.js +22 -4
  79. package/dist/renderPptx/renderPptx.d.ts +2 -1
  80. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  81. package/dist/renderPptx/renderPptx.js +19 -60
  82. package/dist/renderPptx/types.d.ts +2 -0
  83. package/dist/renderPptx/types.d.ts.map +1 -1
  84. package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -1
  85. package/dist/renderPptx/utils/backgroundBorder.js +1 -1
  86. package/dist/shared/freeYogaTree.d.ts.map +1 -0
  87. package/dist/shared/measureImage.d.ts +13 -3
  88. package/dist/shared/measureImage.d.ts.map +1 -1
  89. package/dist/shared/measureImage.js +14 -19
  90. package/dist/shared/walkTree.d.ts.map +1 -0
  91. package/dist/toPositioned/toPositioned.d.ts +8 -1
  92. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  93. package/dist/toPositioned/toPositioned.js +32 -189
  94. package/dist/types.d.ts +38 -54
  95. package/dist/types.d.ts.map +1 -1
  96. package/dist/types.js +11 -1
  97. package/package.json +3 -3
  98. package/dist/autoFit/freeYogaTree.d.ts.map +0 -1
  99. package/dist/autoFit/walkTree.d.ts.map +0 -1
  100. package/dist/renderPptx/nodes/index.d.ts +0 -15
  101. package/dist/renderPptx/nodes/index.d.ts.map +0 -1
  102. package/dist/renderPptx/nodes/index.js +0 -14
  103. /package/dist/{autoFit → shared}/freeYogaTree.d.ts +0 -0
  104. /package/dist/{autoFit → shared}/freeYogaTree.js +0 -0
  105. /package/dist/{autoFit → shared}/walkTree.d.ts +0 -0
  106. /package/dist/{autoFit → shared}/walkTree.js +0 -0
@@ -1,7 +1,6 @@
1
1
  import { XMLParser } from "fast-xml-parser";
2
- import { z } from "zod";
3
- import { inputTextNodeSchema, inputUlNodeSchema, inputOlNodeSchema, inputLiNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputTimelineNodeSchema, inputMatrixNodeSchema, inputTreeNodeSchema, inputFlowNodeSchema, inputProcessArrowNodeSchema, inputPyramidNodeSchema, inputLineNodeSchema, inputIconNodeSchema, inputBaseNodeSchema, } from "./inputSchema.js";
4
- import { alignItemsSchema, justifyContentSchema, shadowStyleSchema, processArrowStepSchema, pyramidLevelSchema, timelineItemSchema, matrixAxisSchema, matrixQuadrantsSchema, matrixItemSchema, flowNodeItemSchema, flowConnectionSchema, chartDataSchema, tableColumnSchema, tableCellSchema, flexWrapSchema, } from "../types.js";
2
+ import { inputTextNodeSchema, inputUlNodeSchema, inputOlNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputTimelineNodeSchema, inputMatrixNodeSchema, inputTreeNodeSchema, inputFlowNodeSchema, inputProcessArrowNodeSchema, inputPyramidNodeSchema, inputLineNodeSchema, inputIconNodeSchema, } from "./inputSchema.js";
3
+ import { NODE_COERCION_MAP, CHILD_ELEMENT_COERCION_MAP, coerceWithRule, coerceFallback, getObjectShapeFromRule, isBooleanObjectUnionRule, } from "./coercionRules.js";
5
4
  // ===== ParseXmlError =====
6
5
  export class ParseXmlError extends Error {
7
6
  errors;
@@ -36,54 +35,16 @@ const TAG_TO_TYPE = {
36
35
  };
37
36
  // Reverse mapping: node type → tag name
38
37
  const TYPE_TO_TAG = Object.fromEntries(Object.entries(TAG_TO_TYPE).map(([tag, type]) => [type, tag]));
39
- function extractShape(schema) {
40
- return schema.shape;
41
- }
42
- const leafNodeShapes = {
43
- text: extractShape(inputTextNodeSchema),
44
- image: extractShape(inputImageNodeSchema),
45
- table: extractShape(inputTableNodeSchema),
46
- shape: extractShape(inputShapeNodeSchema),
47
- chart: extractShape(inputChartNodeSchema),
48
- timeline: extractShape(inputTimelineNodeSchema),
49
- matrix: extractShape(inputMatrixNodeSchema),
50
- tree: extractShape(inputTreeNodeSchema),
51
- flow: extractShape(inputFlowNodeSchema),
52
- processArrow: extractShape(inputProcessArrowNodeSchema),
53
- pyramid: extractShape(inputPyramidNodeSchema),
54
- line: extractShape(inputLineNodeSchema),
55
- ul: extractShape(inputUlNodeSchema),
56
- ol: extractShape(inputOlNodeSchema),
57
- icon: extractShape(inputIconNodeSchema),
58
- };
59
- const containerShapes = {
60
- box: extractShape(inputBaseNodeSchema.extend({ shadow: shadowStyleSchema.optional() })),
61
- vstack: extractShape(inputBaseNodeSchema.extend({
62
- gap: z.number().optional(),
63
- alignItems: alignItemsSchema.optional(),
64
- justifyContent: justifyContentSchema.optional(),
65
- shadow: shadowStyleSchema.optional(),
66
- flexWrap: flexWrapSchema.optional(),
67
- })),
68
- hstack: extractShape(inputBaseNodeSchema.extend({
69
- gap: z.number().optional(),
70
- alignItems: alignItemsSchema.optional(),
71
- justifyContent: justifyContentSchema.optional(),
72
- shadow: shadowStyleSchema.optional(),
73
- flexWrap: flexWrapSchema.optional(),
74
- })),
75
- layer: extractShape(inputBaseNodeSchema),
76
- };
77
38
  const CONTAINER_TYPES = new Set(["box", "vstack", "hstack", "layer"]);
78
39
  const TEXT_CONTENT_NODES = new Set(["text", "shape"]);
79
40
  // Attributes allowed on any node (e.g., x/y for Layer children positioning)
80
41
  const UNIVERSAL_ATTRS = new Set(["x", "y"]);
81
42
  // ===== Validation helpers =====
82
43
  function getKnownAttributes(nodeType) {
83
- const shape = leafNodeShapes[nodeType] ?? containerShapes[nodeType];
84
- if (!shape)
44
+ const rules = NODE_COERCION_MAP[nodeType];
45
+ if (!rules)
85
46
  return [];
86
- return Object.keys(shape).filter((k) => k !== "type");
47
+ return Object.keys(rules);
87
48
  }
88
49
  function levenshteinDistance(a, b) {
89
50
  const m = a.length;
@@ -117,10 +78,10 @@ function findClosestMatch(input, candidates) {
117
78
  return bestMatch;
118
79
  }
119
80
  function getKnownChildAttributes(tagName) {
120
- const shape = childElementShapes[tagName];
121
- if (!shape)
81
+ const rules = CHILD_ELEMENT_COERCION_MAP[tagName];
82
+ if (!rules)
122
83
  return [];
123
- return Object.keys(shape);
84
+ return Object.keys(rules);
124
85
  }
125
86
  // ===== Leaf node Zod validation schemas =====
126
87
  const leafNodeValidationSchemas = {
@@ -231,165 +192,11 @@ function validateLeafNode(nodeType, result, errors) {
231
192
  }
232
193
  }
233
194
  }
234
- function getDef(schema) {
235
- return schema._def;
236
- }
237
- function getPropertySchema(nodeType, propertyName) {
238
- const shape = leafNodeShapes[nodeType] ?? containerShapes[nodeType];
239
- if (!shape)
240
- return undefined;
241
- return shape[propertyName];
242
- }
243
- function getZodType(schema) {
244
- const def = getDef(schema);
245
- return (def.type ?? def.typeName ?? "");
246
- }
247
- function unwrapSchema(schema) {
248
- const typeName = getZodType(schema);
249
- const def = getDef(schema);
250
- switch (typeName) {
251
- case "optional":
252
- case "default":
253
- case "nullable":
254
- return unwrapSchema(def.innerType);
255
- case "lazy":
256
- return unwrapSchema(def.getter());
257
- case "pipe":
258
- return unwrapSchema(def.in);
259
- default:
260
- return schema;
261
- }
262
- }
263
- function resolveZodTypeName(schema) {
264
- return getZodType(unwrapSchema(schema));
265
- }
266
- // ===== Value coercion =====
267
- // Returns { value, error } — if error is non-null, coercion failed.
268
- function coerceValue(value, schema) {
269
- const unwrapped = unwrapSchema(schema);
270
- const typeName = getZodType(unwrapped);
271
- const def = getDef(unwrapped);
272
- switch (typeName) {
273
- case "number": {
274
- const num = Number(value);
275
- if (isNaN(num)) {
276
- return {
277
- value: undefined,
278
- error: `Cannot convert "${value}" to number`,
279
- };
280
- }
281
- return { value: num, error: null };
282
- }
283
- case "boolean":
284
- if (value !== "true" && value !== "false") {
285
- return {
286
- value: undefined,
287
- error: `Cannot convert "${value}" to boolean (expected "true" or "false")`,
288
- };
289
- }
290
- return { value: value === "true", error: null };
291
- case "string":
292
- case "enum":
293
- return { value, error: null };
294
- case "literal": {
295
- const values = def.values;
296
- const singleValue = def.value;
297
- return { value: values?.[0] ?? singleValue, error: null };
298
- }
299
- case "array":
300
- case "object":
301
- case "record":
302
- case "tuple":
303
- try {
304
- return { value: JSON.parse(value), error: null };
305
- }
306
- catch {
307
- return {
308
- value: undefined,
309
- error: `Cannot parse JSON value: "${value}"`,
310
- };
311
- }
312
- case "union": {
313
- const options = def.options;
314
- return { value: coerceUnionValue(value, options), error: null };
315
- }
316
- default:
317
- return { value: coerceFallback(value), error: null };
318
- }
319
- }
320
- function coerceUnionValue(value, options) {
321
- const typeNames = options.map((opt) => resolveZodTypeName(opt));
322
- // Try boolean
323
- if ((value === "true" || value === "false") &&
324
- typeNames.includes("boolean")) {
325
- return value === "true";
326
- }
327
- // Try number
328
- if (typeNames.includes("number")) {
329
- const num = Number(value);
330
- if (!isNaN(num) && value !== "") {
331
- return num;
332
- }
333
- }
334
- // Try literal
335
- for (let i = 0; i < options.length; i++) {
336
- if (typeNames[i] === "literal") {
337
- const unwrapped = unwrapSchema(options[i]);
338
- const def = getDef(unwrapped);
339
- const values = def.values;
340
- const singleValue = def.value;
341
- const litVal = values?.[0] ?? singleValue;
342
- if (litVal != null && `${litVal}` === value)
343
- return litVal;
344
- }
345
- }
346
- // Try JSON parse for objects/arrays
347
- if (typeNames.some((t) => ["array", "object", "record", "tuple"].includes(t))) {
348
- if (value.startsWith("{") || value.startsWith("[")) {
349
- try {
350
- return JSON.parse(value);
351
- }
352
- catch {
353
- /* ignore */
354
- }
355
- }
356
- }
357
- // Fallback to string
358
- return value;
359
- }
360
- function coerceFallback(value) {
361
- if (value === "true")
362
- return true;
363
- if (value === "false")
364
- return false;
365
- const num = Number(value);
366
- if (value !== "" && !isNaN(num))
367
- return num;
368
- if (value.startsWith("{") || value.startsWith("[")) {
369
- try {
370
- return JSON.parse(value);
371
- }
372
- catch {
373
- /* ignore */
374
- }
375
- }
376
- return value;
195
+ // ===== Coercion rule lookup =====
196
+ function getCoercionRule(nodeType, propertyName) {
197
+ return NODE_COERCION_MAP[nodeType]?.[propertyName];
377
198
  }
378
199
  // ===== Dot notation helpers =====
379
- /**
380
- * Checks if a schema is a union containing both boolean and object types.
381
- * Used to allow `endArrow="true" endArrow.type="triangle"` coexistence.
382
- */
383
- function isBooleanObjectUnion(schema) {
384
- const unwrapped = unwrapSchema(schema);
385
- const typeName = getZodType(unwrapped);
386
- if (typeName !== "union")
387
- return false;
388
- const def = getDef(unwrapped);
389
- const options = def.options;
390
- const typeNames = options.map((opt) => getZodType(unwrapSchema(opt)));
391
- return typeNames.includes("boolean") && typeNames.includes("object");
392
- }
393
200
  // ===== Dot notation expansion =====
394
201
  function expandDotNotation(attrs) {
395
202
  const regular = {};
@@ -409,26 +216,13 @@ function expandDotNotation(attrs) {
409
216
  }
410
217
  return { regular, dotGroups };
411
218
  }
412
- function coerceDotGroup(prefix, subAttrs, schema, tagName, errors) {
413
- const unwrapped = unwrapSchema(schema);
414
- const typeName = getZodType(unwrapped);
415
- let objectSchema;
416
- if (typeName === "object") {
417
- objectSchema = unwrapped;
418
- }
419
- else if (typeName === "union") {
420
- const def = getDef(unwrapped);
421
- const options = def.options;
422
- objectSchema = options.find((opt) => getZodType(unwrapSchema(opt)) === "object");
423
- if (objectSchema)
424
- objectSchema = unwrapSchema(objectSchema);
425
- }
219
+ function coerceDotGroup(prefix, subAttrs, rule, tagName, errors) {
220
+ const objectShape = getObjectShapeFromRule(rule);
426
221
  const obj = {};
427
- if (objectSchema) {
428
- const shape = extractShape(objectSchema);
222
+ if (objectShape) {
429
223
  for (const [subKey, subValue] of Object.entries(subAttrs)) {
430
- if (shape[subKey]) {
431
- const coerced = coerceValue(subValue, shape[subKey]);
224
+ if (objectShape[subKey]) {
225
+ const coerced = coerceWithRule(subValue, objectShape[subKey]);
432
226
  if (coerced.error !== null) {
433
227
  errors.push(`<${tagName}>: ${prefix}.${subKey}: ${coerced.error}`);
434
228
  }
@@ -437,7 +231,7 @@ function coerceDotGroup(prefix, subAttrs, schema, tagName, errors) {
437
231
  }
438
232
  }
439
233
  else {
440
- const knownSubKeys = Object.keys(shape);
234
+ const knownSubKeys = Object.keys(objectShape);
441
235
  const suggestion = findClosestMatch(subKey, knownSubKeys);
442
236
  errors.push(`<${tagName}>: Unknown sub-attribute "${prefix}.${subKey}"${suggestion ? `. Did you mean "${prefix}.${suggestion}"?` : ""}`);
443
237
  }
@@ -490,30 +284,16 @@ function getTextContent(node) {
490
284
  }
491
285
  return textParts.length > 0 ? textParts.join("") : undefined;
492
286
  }
493
- // ===== Child element schemas for type coercion =====
494
- const childElementShapes = {
495
- ProcessArrowStep: extractShape(processArrowStepSchema),
496
- PyramidLevel: extractShape(pyramidLevelSchema),
497
- TimelineItem: extractShape(timelineItemSchema),
498
- MatrixAxes: extractShape(matrixAxisSchema),
499
- MatrixQuadrants: extractShape(matrixQuadrantsSchema),
500
- MatrixItem: extractShape(matrixItemSchema),
501
- FlowNode: extractShape(flowNodeItemSchema),
502
- FlowConnection: extractShape(flowConnectionSchema),
503
- TableColumn: extractShape(tableColumnSchema),
504
- TableCell: extractShape(tableCellSchema),
505
- Li: extractShape(inputLiNodeSchema),
506
- };
507
287
  function coerceChildAttrs(parentTagName, tagName, attrs, errors) {
508
- const shape = childElementShapes[tagName];
288
+ const rules = CHILD_ELEMENT_COERCION_MAP[tagName];
509
289
  const result = {};
510
290
  const { regular: regularAttrs, dotGroups } = expandDotNotation(attrs);
511
291
  // Process dot-notation attributes
512
292
  for (const [prefix, subAttrs] of Object.entries(dotGroups)) {
513
- if (shape && shape[prefix]) {
514
- result[prefix] = coerceDotGroup(prefix, subAttrs, shape[prefix], `${parentTagName}.${tagName}`, errors);
293
+ if (rules && rules[prefix]) {
294
+ result[prefix] = coerceDotGroup(prefix, subAttrs, rules[prefix], `${parentTagName}.${tagName}`, errors);
515
295
  }
516
- else if (shape) {
296
+ else if (rules) {
517
297
  const knownAttrs = getKnownChildAttributes(tagName);
518
298
  const suggestion = findClosestMatch(prefix, knownAttrs);
519
299
  errors.push(`<${parentTagName}>.<${tagName}>: Unknown attribute "${prefix}"${suggestion ? `. Did you mean "${suggestion}"?` : ""}`);
@@ -529,11 +309,11 @@ function coerceChildAttrs(parentTagName, tagName, attrs, errors) {
529
309
  // Process regular attributes
530
310
  for (const [key, value] of Object.entries(regularAttrs)) {
531
311
  if (key in dotGroups) {
532
- // When the schema is a union of boolean and object,
312
+ // When the rule is a union of boolean and object,
533
313
  // allow boolean shorthand to coexist with dot-notation by ignoring the boolean value.
534
- if (shape &&
535
- shape[key] &&
536
- isBooleanObjectUnion(shape[key]) &&
314
+ if (rules &&
315
+ rules[key] &&
316
+ isBooleanObjectUnionRule(rules[key]) &&
537
317
  (value === "true" || value === "false")) {
538
318
  // Silently skip the boolean value; dot-notation takes priority
539
319
  continue;
@@ -541,8 +321,8 @@ function coerceChildAttrs(parentTagName, tagName, attrs, errors) {
541
321
  errors.push(`<${parentTagName}>.<${tagName}>: Attribute "${key}" conflicts with dot-notation attributes. Use one or the other, not both`);
542
322
  continue;
543
323
  }
544
- if (shape && shape[key]) {
545
- const coerced = coerceValue(value, shape[key]);
324
+ if (rules && rules[key]) {
325
+ const coerced = coerceWithRule(value, rules[key]);
546
326
  if (coerced.error !== null) {
547
327
  errors.push(`<${parentTagName}>.<${tagName}>: ${coerced.error}`);
548
328
  }
@@ -550,7 +330,7 @@ function coerceChildAttrs(parentTagName, tagName, attrs, errors) {
550
330
  result[key] = coerced.value;
551
331
  }
552
332
  }
553
- else if (shape) {
333
+ else if (rules) {
554
334
  // Unknown attribute on child element
555
335
  const knownAttrs = getKnownChildAttributes(tagName);
556
336
  const suggestion = findClosestMatch(key, knownAttrs);
@@ -644,7 +424,6 @@ function convertFlowChildren(childElements, result, errors) {
644
424
  }
645
425
  }
646
426
  function convertChartChildren(childElements, result, errors) {
647
- const dataShape = extractShape(chartDataSchema);
648
427
  const data = [];
649
428
  for (const child of childElements) {
650
429
  const tag = getTagName(child);
@@ -658,19 +437,8 @@ function convertChartChildren(childElements, result, errors) {
658
437
  values: [],
659
438
  };
660
439
  if (attrs.name !== undefined) {
661
- const nameSchema = dataShape.name;
662
- if (nameSchema) {
663
- const coerced = coerceValue(attrs.name, nameSchema);
664
- if (coerced.error !== null) {
665
- errors.push(`<Chart>.<ChartSeries>: ${coerced.error}`);
666
- }
667
- else {
668
- series.name = coerced.value;
669
- }
670
- }
671
- else {
672
- series.name = attrs.name;
673
- }
440
+ // chartDataSchema.name z.string().optional() なのでそのまま文字列として使用
441
+ series.name = attrs.name;
674
442
  }
675
443
  for (const dp of getChildElements(child)) {
676
444
  const dpTag = getTagName(dp);
@@ -840,9 +608,9 @@ function convertPomNode(nodeType, tagName, attrs, childElements, textContent, er
840
608
  for (const [prefix, subAttrs] of Object.entries(dotGroups)) {
841
609
  if (prefix === "type")
842
610
  continue;
843
- const propSchema = getPropertySchema(nodeType, prefix);
844
- if (propSchema) {
845
- result[prefix] = coerceDotGroup(prefix, subAttrs, propSchema, tagName, errors);
611
+ const rule = getCoercionRule(nodeType, prefix);
612
+ if (rule) {
613
+ result[prefix] = coerceDotGroup(prefix, subAttrs, rule, tagName, errors);
846
614
  }
847
615
  else {
848
616
  const knownAttrs = getKnownAttributes(nodeType);
@@ -860,11 +628,11 @@ function convertPomNode(nodeType, tagName, attrs, childElements, textContent, er
860
628
  continue;
861
629
  // Conflict check: dot-notation and regular attribute for the same key
862
630
  if (key in dotGroups) {
863
- // When the schema is a union of boolean and object (e.g., endArrow),
631
+ // When the rule is a union of boolean and object (e.g., endArrow),
864
632
  // allow boolean shorthand to coexist with dot-notation by ignoring the boolean value.
865
- const propSchemaForConflict = getPropertySchema(nodeType, key);
866
- if (propSchemaForConflict &&
867
- isBooleanObjectUnion(propSchemaForConflict) &&
633
+ const ruleForConflict = getCoercionRule(nodeType, key);
634
+ if (ruleForConflict &&
635
+ isBooleanObjectUnionRule(ruleForConflict) &&
868
636
  (value === "true" || value === "false")) {
869
637
  // Silently skip the boolean value; dot-notation takes priority
870
638
  continue;
@@ -872,9 +640,9 @@ function convertPomNode(nodeType, tagName, attrs, childElements, textContent, er
872
640
  errors.push(`<${tagName}>: Attribute "${key}" conflicts with dot-notation attributes (e.g., "${key}.xxx"). Use one or the other, not both`);
873
641
  continue;
874
642
  }
875
- const propSchema = getPropertySchema(nodeType, key);
876
- if (propSchema) {
877
- const coerced = coerceValue(value, propSchema);
643
+ const rule = getCoercionRule(nodeType, key);
644
+ if (rule) {
645
+ const coerced = coerceWithRule(value, rule);
878
646
  if (coerced.error !== null) {
879
647
  errors.push(`<${tagName}>: ${coerced.error}`);
880
648
  }
@@ -936,11 +704,14 @@ function convertPomNode(nodeType, tagName, attrs, childElements, textContent, er
936
704
  if (!CONTAINER_TYPES.has(nodeType)) {
937
705
  validateLeafNode(nodeType, result, errors);
938
706
  }
939
- // Normalize icon color: add # prefix if missing
940
- if (nodeType === "icon" &&
941
- typeof result.color === "string" &&
942
- !result.color.startsWith("#")) {
943
- result.color = `#${result.color}`;
707
+ // Normalize icon color / bgColor: add # prefix if missing
708
+ if (nodeType === "icon") {
709
+ if (typeof result.color === "string" && !result.color.startsWith("#")) {
710
+ result.color = `#${result.color}`;
711
+ }
712
+ if (typeof result.bgColor === "string" && !result.bgColor.startsWith("#")) {
713
+ result.bgColor = `#${result.bgColor}`;
714
+ }
944
715
  }
945
716
  return result;
946
717
  }
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const boxNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/box.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,eAAO,MAAM,UAAU,EAAE,cAKxB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const boxNodeDef = {
2
+ type: "box",
3
+ category: "single-child",
4
+ // applyYogaStyle: デフォルトで十分(共通スタイルのみ)
5
+ // render: category ベースの子要素再帰で対応
6
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const chartNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=chart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,YAAY,EAAE,cAM1B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { renderChartNode } from "../../renderPptx/nodes/chart.js";
2
+ export const chartNodeDef = {
3
+ type: "chart",
4
+ category: "leaf",
5
+ render(node, ctx) {
6
+ renderChartNode(node, ctx);
7
+ },
8
+ };
@@ -0,0 +1,8 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const timelineNodeDef: NodeDefinition;
3
+ export declare const matrixNodeDef: NodeDefinition;
4
+ export declare const treeNodeDef: NodeDefinition;
5
+ export declare const flowNodeDef: NodeDefinition;
6
+ export declare const processArrowNodeDef: NodeDefinition;
7
+ export declare const pyramidNodeDef: NodeDefinition;
8
+ //# sourceMappingURL=compositeNodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compositeNodes.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/compositeNodes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAqDxD,eAAO,MAAM,eAAe,EAAE,cAS7B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,cAS3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,cASzB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,cASzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAYjC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAS5B,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { measureProcessArrow, measureTimeline, measureMatrix, measureTree, measureFlow, measurePyramid, } from "../../calcYogaLayout/measureCompositeNodes.js";
2
+ import { renderTimelineNode } from "../../renderPptx/nodes/timeline.js";
3
+ import { renderMatrixNode } from "../../renderPptx/nodes/matrix.js";
4
+ import { renderTreeNode } from "../../renderPptx/nodes/tree.js";
5
+ import { renderFlowNode } from "../../renderPptx/nodes/flow.js";
6
+ import { renderProcessArrowNode } from "../../renderPptx/nodes/processArrow.js";
7
+ import { renderPyramidNode } from "../../renderPptx/nodes/pyramid.js";
8
+ /**
9
+ * コンポジットノードの最小スケール閾値。
10
+ * renderPptx/utils/scaleToFit.ts の MIN_SCALE_THRESHOLD と同じ値を維持すること。
11
+ */
12
+ const MIN_SCALE_THRESHOLD = 0.5;
13
+ /** 制約付きサイズを閾値でクランプする */
14
+ function constrainWithMinScale(intrinsicSize, availableSize) {
15
+ const minSize = intrinsicSize * MIN_SCALE_THRESHOLD;
16
+ return Math.max(minSize, Math.min(intrinsicSize, availableSize));
17
+ }
18
+ /** コンポジットノード共通の measureFunc セットアップ */
19
+ function applyCompositeMeasure(measureFn) {
20
+ return (node, yn, yoga) => {
21
+ yn.setMeasureFunc((width, widthMode, height, heightMode) => {
22
+ const intrinsic = measureFn(node);
23
+ return {
24
+ width: widthMode !== yoga.MEASURE_MODE_UNDEFINED
25
+ ? constrainWithMinScale(intrinsic.width, width)
26
+ : intrinsic.width,
27
+ height: heightMode !== yoga.MEASURE_MODE_UNDEFINED
28
+ ? constrainWithMinScale(intrinsic.height, height)
29
+ : intrinsic.height,
30
+ };
31
+ });
32
+ };
33
+ }
34
+ export const timelineNodeDef = {
35
+ type: "timeline",
36
+ category: "leaf",
37
+ applyYogaStyle: applyCompositeMeasure(measureTimeline),
38
+ render(node, ctx) {
39
+ renderTimelineNode(node, ctx);
40
+ },
41
+ };
42
+ export const matrixNodeDef = {
43
+ type: "matrix",
44
+ category: "leaf",
45
+ applyYogaStyle: applyCompositeMeasure(measureMatrix),
46
+ render(node, ctx) {
47
+ renderMatrixNode(node, ctx);
48
+ },
49
+ };
50
+ export const treeNodeDef = {
51
+ type: "tree",
52
+ category: "leaf",
53
+ applyYogaStyle: applyCompositeMeasure(measureTree),
54
+ render(node, ctx) {
55
+ renderTreeNode(node, ctx);
56
+ },
57
+ };
58
+ export const flowNodeDef = {
59
+ type: "flow",
60
+ category: "leaf",
61
+ applyYogaStyle: applyCompositeMeasure(measureFlow),
62
+ render(node, ctx) {
63
+ renderFlowNode(node, ctx);
64
+ },
65
+ };
66
+ export const processArrowNodeDef = {
67
+ type: "processArrow",
68
+ category: "leaf",
69
+ applyYogaStyle: applyCompositeMeasure(measureProcessArrow),
70
+ render(node, ctx) {
71
+ renderProcessArrowNode(node, ctx);
72
+ },
73
+ };
74
+ export const pyramidNodeDef = {
75
+ type: "pyramid",
76
+ category: "leaf",
77
+ applyYogaStyle: applyCompositeMeasure(measurePyramid),
78
+ render(node, ctx) {
79
+ renderPyramidNode(node, ctx);
80
+ },
81
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const iconNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,eAAO,MAAM,WAAW,EAAE,cAwDzB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { rasterizeIcon } from "../../icons/index.js";
2
+ import { omitYogaNode } from "../../toPositioned/toPositioned.js";
3
+ import { renderIconNode } from "../../renderPptx/nodes/icon.js";
4
+ export const iconNodeDef = {
5
+ type: "icon",
6
+ category: "leaf",
7
+ applyYogaStyle(node, yn) {
8
+ const n = node;
9
+ const iconSize = n.size ?? 24;
10
+ // variant 指定時はアイコンサイズ + パディング分を全体サイズとする
11
+ const totalSize = n.variant ? Math.ceil(iconSize * 1.75) : iconSize;
12
+ yn.setMeasureFunc(() => ({ width: totalSize, height: totalSize }));
13
+ },
14
+ toPositioned(pom, absoluteX, absoluteY, layout, ctx) {
15
+ const n = pom;
16
+ const iconSize = n.size ?? 24;
17
+ const rasterSize = Math.max(Math.ceil(n.variant ? iconSize : layout.width), Math.ceil(n.variant ? iconSize : layout.height), iconSize);
18
+ const iconImageData = rasterizeIcon(n.name, rasterSize, n.color ?? "#000000", ctx.iconRasterCache);
19
+ // variant 指定時はアイコンを中央に配置
20
+ const positioned = {
21
+ ...omitYogaNode(n),
22
+ x: absoluteX,
23
+ y: absoluteY,
24
+ w: layout.width,
25
+ h: layout.height,
26
+ iconImageData,
27
+ };
28
+ if (n.variant) {
29
+ const totalSize = Math.ceil(iconSize * 1.75);
30
+ // 背景図形は totalSize の正方形として、layout 領域の中央に配置
31
+ const bgOffsetX = (layout.width - totalSize) / 2;
32
+ const bgOffsetY = (layout.height - totalSize) / 2;
33
+ positioned.bgX = absoluteX + bgOffsetX;
34
+ positioned.bgY = absoluteY + bgOffsetY;
35
+ positioned.bgW = totalSize;
36
+ positioned.bgH = totalSize;
37
+ // アイコンは背景図形の中央に配置
38
+ const iconOffsetX = (layout.width - iconSize) / 2;
39
+ const iconOffsetY = (layout.height - iconSize) / 2;
40
+ positioned.iconX = absoluteX + iconOffsetX;
41
+ positioned.iconY = absoluteY + iconOffsetY;
42
+ positioned.iconW = iconSize;
43
+ positioned.iconH = iconSize;
44
+ }
45
+ return positioned;
46
+ },
47
+ render(node, ctx) {
48
+ renderIconNode(node, ctx);
49
+ },
50
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const imageNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAOxD,eAAO,MAAM,YAAY,EAAE,cA+B1B,CAAC"}