@hirokisakabe/pom 10.0.0 → 10.2.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 (77) hide show
  1. package/README.md +1 -1
  2. package/dist/autoFit/autoFit.js +55 -15
  3. package/dist/autoFit/autoFit.js.map +1 -1
  4. package/dist/autoFit/strategies/reduceFontSize.js.map +1 -1
  5. package/dist/buildContext.js +4 -4
  6. package/dist/buildContext.js.map +1 -1
  7. package/dist/buildPptx.d.ts +3 -2
  8. package/dist/buildPptx.d.ts.map +1 -1
  9. package/dist/buildPptx.js +1 -1
  10. package/dist/buildPptx.js.map +1 -1
  11. package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
  12. package/dist/calcYogaLayout/fontLoader.d.ts +13 -0
  13. package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -0
  14. package/dist/calcYogaLayout/fontLoader.js +70 -3
  15. package/dist/calcYogaLayout/fontLoader.js.map +1 -1
  16. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  17. package/dist/calcYogaLayout/measureText.js +6 -6
  18. package/dist/calcYogaLayout/measureText.js.map +1 -1
  19. package/dist/diagnostics.d.ts +1 -1
  20. package/dist/diagnostics.d.ts.map +1 -1
  21. package/dist/diagnostics.js.map +1 -1
  22. package/dist/extractSlideMastersAsPptx.d.ts.map +1 -1
  23. package/dist/extractThemeTokensFromPptx.d.ts +0 -1
  24. package/dist/extractThemeTokensFromPptx.d.ts.map +1 -1
  25. package/dist/icons/renderIcon.js +12 -10
  26. package/dist/icons/renderIcon.js.map +1 -1
  27. package/dist/index.d.ts +2 -1
  28. package/dist/parseXml/coercionRules.js.map +1 -1
  29. package/dist/parseXml/parseXml.d.ts +0 -1
  30. package/dist/parseXml/parseXml.d.ts.map +1 -1
  31. package/dist/parseXml/parseXml.js.map +1 -1
  32. package/dist/parseXml/serializeXml.d.ts +0 -1
  33. package/dist/parseXml/serializeXml.d.ts.map +1 -1
  34. package/dist/parseXml/serializeXml.js.map +1 -1
  35. package/dist/registry/definitions/icon.js +1 -1
  36. package/dist/registry/definitions/list.js +1 -1
  37. package/dist/registry/definitions/list.js.map +1 -1
  38. package/dist/registry/definitions/shape.js +1 -1
  39. package/dist/registry/definitions/shape.js.map +1 -1
  40. package/dist/registry/definitions/text.js +1 -1
  41. package/dist/registry/definitions/text.js.map +1 -1
  42. package/dist/renderPptx/authoringContext.js +101 -0
  43. package/dist/renderPptx/authoringContext.js.map +1 -0
  44. package/dist/renderPptx/{pptxAuthoring.js → glimpseAdapter.js} +83 -152
  45. package/dist/renderPptx/glimpseAdapter.js.map +1 -0
  46. package/dist/renderPptx/nodes/arrow.js +49 -7
  47. package/dist/renderPptx/nodes/arrow.js.map +1 -1
  48. package/dist/renderPptx/nodes/chart.js +2 -2
  49. package/dist/renderPptx/nodes/chart.js.map +1 -1
  50. package/dist/renderPptx/nodes/icon.js +1 -1
  51. package/dist/renderPptx/nodes/icon.js.map +1 -1
  52. package/dist/renderPptx/nodes/list.js +11 -19
  53. package/dist/renderPptx/nodes/list.js.map +1 -1
  54. package/dist/renderPptx/nodes/shape.js +18 -19
  55. package/dist/renderPptx/nodes/shape.js.map +1 -1
  56. package/dist/renderPptx/nodes/table.js +12 -21
  57. package/dist/renderPptx/nodes/table.js.map +1 -1
  58. package/dist/renderPptx/nodes/text.js +16 -1
  59. package/dist/renderPptx/nodes/text.js.map +1 -1
  60. package/dist/renderPptx/renderPptx.js +93 -40
  61. package/dist/renderPptx/renderPptx.js.map +1 -1
  62. package/dist/renderPptx/utils/connectorSites.js +58 -0
  63. package/dist/renderPptx/utils/connectorSites.js.map +1 -0
  64. package/dist/renderPptx/utils/glimpsePicture.js +2 -4
  65. package/dist/renderPptx/utils/glimpsePicture.js.map +1 -1
  66. package/dist/renderPptx/utils/glimpseShape.js +3 -3
  67. package/dist/renderPptx/utils/glimpseShape.js.map +1 -1
  68. package/dist/renderPptx/utils/glimpseTextBox.js +3 -30
  69. package/dist/renderPptx/utils/glimpseTextBox.js.map +1 -1
  70. package/dist/renderPptx/utils/straightLine.js.map +1 -1
  71. package/dist/renderPptx/writablePptx.d.ts +1 -1
  72. package/dist/renderPptx/writablePptx.d.ts.map +1 -1
  73. package/dist/types.d.ts +0 -1
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +1 -1
  76. package/package.json +10 -6
  77. package/dist/renderPptx/pptxAuthoring.js.map +0 -1
@@ -1,5 +1,16 @@
1
- import { addStraightLine } from "../utils/straightLine.js";
1
+ import { pxToEmu } from "../units.js";
2
+ import { arrowEndpoint, createShapeBoundsInput, solidShapeFill } from "../utils/glimpseShape.js";
3
+ import { resolveArrowType } from "../utils/straightLine.js";
4
+ import { asEmu } from "@pptx-glimpse/document";
2
5
  //#region src/renderPptx/nodes/arrow.ts
6
+ function connectionSite(sites, other) {
7
+ const otherCenterX = other.x + other.w / 2;
8
+ const otherCenterY = other.y + other.h / 2;
9
+ return sites.reduce((nearest, candidate) => {
10
+ const nearestDistance = Math.hypot(nearest.x - otherCenterX, nearest.y - otherCenterY);
11
+ return Math.hypot(candidate.x - otherCenterX, candidate.y - otherCenterY) < nearestDistance ? candidate : nearest;
12
+ });
13
+ }
3
14
  function renderArrowNode(node, ctx) {
4
15
  const fromBounds = ctx.idPositionMap.get(node.from);
5
16
  const toBounds = ctx.idPositionMap.get(node.to);
@@ -11,12 +22,43 @@ function renderArrowNode(node, ctx) {
11
22
  ctx.buildContext.diagnostics.add("ARROW_REF_NOT_FOUND", `Arrow: "to" ID "${node.to}" not found`);
12
23
  return;
13
24
  }
14
- addStraightLine(ctx, {
15
- x1: fromBounds.x + fromBounds.w / 2,
16
- y1: fromBounds.y + fromBounds.h / 2,
17
- x2: toBounds.x + toBounds.w / 2,
18
- y2: toBounds.y + toBounds.h / 2
19
- }, node);
25
+ const fromTarget = ctx.connectorTargetMap.get(node.from);
26
+ const toTarget = ctx.connectorTargetMap.get(node.to);
27
+ if (!fromTarget || !toTarget) {
28
+ const id = !fromTarget ? node.from : node.to;
29
+ ctx.buildContext.diagnostics.add("ARROW_REF_NOT_CONNECTABLE", `Arrow: ID "${id}" does not reference a connector-compatible Shape geometry or Text node`);
30
+ return;
31
+ }
32
+ const startSite = connectionSite(fromTarget.sites, toTarget.bounds);
33
+ const endSite = connectionSite(toTarget.sites, fromTarget.bounds);
34
+ const minX = Math.min(startSite.x, endSite.x);
35
+ const minY = Math.min(startSite.y, endSite.y);
36
+ ctx.authoring.addConnector({
37
+ preset: "straightConnector1",
38
+ ...createShapeBoundsInput({
39
+ x: minX,
40
+ y: minY,
41
+ w: Math.abs(endSite.x - startSite.x),
42
+ h: Math.abs(endSite.y - startSite.y)
43
+ }),
44
+ flipHorizontal: endSite.x < startSite.x,
45
+ flipVertical: endSite.y < startSite.y,
46
+ start: {
47
+ shapeHandle: fromTarget.handle,
48
+ connectionSiteIndex: startSite.index
49
+ },
50
+ end: {
51
+ shapeHandle: toTarget.handle,
52
+ connectionSiteIndex: endSite.index
53
+ },
54
+ outline: {
55
+ fill: solidShapeFill(node.color ?? "000000"),
56
+ width: node.lineWidth !== void 0 ? asEmu(Math.round(pxToEmu(node.lineWidth))) : asEmu(12700),
57
+ dash: node.dashType,
58
+ headEnd: arrowEndpoint(resolveArrowType(node.beginArrow)),
59
+ tailEnd: arrowEndpoint(resolveArrowType(node.endArrow))
60
+ }
61
+ });
20
62
  }
21
63
  //#endregion
22
64
  export { renderArrowNode };
@@ -1 +1 @@
1
- {"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { addStraightLine } from \"../utils/straightLine.ts\";\n\ntype ArrowPositionedNode = Extract<PositionedNode, { type: \"arrow\" }>;\n\nexport function renderArrowNode(\n node: ArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const fromBounds = ctx.idPositionMap.get(node.from);\n const toBounds = ctx.idPositionMap.get(node.to);\n\n if (!fromBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"from\" ID \"${node.from}\" not found`,\n );\n return;\n }\n if (!toBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"to\" ID \"${node.to}\" not found`,\n );\n return;\n }\n\n // 参照ノードの中心同士を結ぶ\n addStraightLine(\n ctx,\n {\n x1: fromBounds.x + fromBounds.w / 2,\n y1: fromBounds.y + fromBounds.h / 2,\n x2: toBounds.x + toBounds.w / 2,\n y2: toBounds.y + toBounds.h / 2,\n },\n node,\n );\n}\n"],"mappings":";;AAMA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,aAAa,IAAI,cAAc,IAAI,KAAK,IAAI;CAClD,MAAM,WAAW,IAAI,cAAc,IAAI,KAAK,EAAE;CAE9C,IAAI,CAAC,YAAY;EACf,IAAI,aAAa,YAAY,IAC3B,uBACA,qBAAqB,KAAK,KAAK,YACjC;EACA;CACF;CACA,IAAI,CAAC,UAAU;EACb,IAAI,aAAa,YAAY,IAC3B,uBACA,mBAAmB,KAAK,GAAG,YAC7B;EACA;CACF;CAGA,gBACE,KACA;EACE,IAAI,WAAW,IAAI,WAAW,IAAI;EAClC,IAAI,WAAW,IAAI,WAAW,IAAI;EAClC,IAAI,SAAS,IAAI,SAAS,IAAI;EAC9B,IAAI,SAAS,IAAI,SAAS,IAAI;CAChC,GACA,IACF;AACF"}
1
+ {"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import { asEmu } from \"@pptx-glimpse/document\";\nimport type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n arrowEndpoint,\n createShapeBoundsInput,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\nimport { resolveArrowType } from \"../utils/straightLine.ts\";\nimport type { ConnectorSite } from \"../utils/connectorSites.ts\";\n\ntype ArrowPositionedNode = Extract<PositionedNode, { type: \"arrow\" }>;\n\nfunction connectionSite(\n sites: readonly ConnectorSite[],\n other: { x: number; y: number; w: number; h: number },\n): ConnectorSite {\n const otherCenterX = other.x + other.w / 2;\n const otherCenterY = other.y + other.h / 2;\n return sites.reduce((nearest, candidate) => {\n const nearestDistance = Math.hypot(\n nearest.x - otherCenterX,\n nearest.y - otherCenterY,\n );\n const candidateDistance = Math.hypot(\n candidate.x - otherCenterX,\n candidate.y - otherCenterY,\n );\n return candidateDistance < nearestDistance ? candidate : nearest;\n });\n}\n\nexport function renderArrowNode(\n node: ArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const fromBounds = ctx.idPositionMap.get(node.from);\n const toBounds = ctx.idPositionMap.get(node.to);\n\n if (!fromBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"from\" ID \"${node.from}\" not found`,\n );\n return;\n }\n if (!toBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"to\" ID \"${node.to}\" not found`,\n );\n return;\n }\n\n const fromTarget = ctx.connectorTargetMap.get(node.from);\n const toTarget = ctx.connectorTargetMap.get(node.to);\n if (!fromTarget || !toTarget) {\n const id = !fromTarget ? node.from : node.to;\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_CONNECTABLE\",\n `Arrow: ID \"${id}\" does not reference a connector-compatible Shape geometry or Text node`,\n );\n return;\n }\n\n const startSite = connectionSite(fromTarget.sites, toTarget.bounds);\n const endSite = connectionSite(toTarget.sites, fromTarget.bounds);\n const minX = Math.min(startSite.x, endSite.x);\n const minY = Math.min(startSite.y, endSite.y);\n\n ctx.authoring.addConnector({\n preset: \"straightConnector1\",\n ...createShapeBoundsInput({\n x: minX,\n y: minY,\n w: Math.abs(endSite.x - startSite.x),\n h: Math.abs(endSite.y - startSite.y),\n }),\n flipHorizontal: endSite.x < startSite.x,\n flipVertical: endSite.y < startSite.y,\n start: {\n shapeHandle: fromTarget.handle,\n connectionSiteIndex: startSite.index,\n },\n end: {\n shapeHandle: toTarget.handle,\n connectionSiteIndex: endSite.index,\n },\n outline: {\n fill: solidShapeFill(node.color ?? \"000000\"),\n width:\n node.lineWidth !== undefined\n ? asEmu(Math.round(pxToEmu(node.lineWidth)))\n : asEmu(12700),\n dash: node.dashType,\n headEnd: arrowEndpoint(resolveArrowType(node.beginArrow)),\n tailEnd: arrowEndpoint(resolveArrowType(node.endArrow)),\n },\n });\n}\n"],"mappings":";;;;;AAcA,SAAS,eACP,OACA,OACe;CACf,MAAM,eAAe,MAAM,IAAI,MAAM,IAAI;CACzC,MAAM,eAAe,MAAM,IAAI,MAAM,IAAI;CACzC,OAAO,MAAM,QAAQ,SAAS,cAAc;EAC1C,MAAM,kBAAkB,KAAK,MAC3B,QAAQ,IAAI,cACZ,QAAQ,IAAI,YACd;EAKA,OAJ0B,KAAK,MAC7B,UAAU,IAAI,cACd,UAAU,IAAI,YAEO,IAAI,kBAAkB,YAAY;CAC3D,CAAC;AACH;AAEA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,aAAa,IAAI,cAAc,IAAI,KAAK,IAAI;CAClD,MAAM,WAAW,IAAI,cAAc,IAAI,KAAK,EAAE;CAE9C,IAAI,CAAC,YAAY;EACf,IAAI,aAAa,YAAY,IAC3B,uBACA,qBAAqB,KAAK,KAAK,YACjC;EACA;CACF;CACA,IAAI,CAAC,UAAU;EACb,IAAI,aAAa,YAAY,IAC3B,uBACA,mBAAmB,KAAK,GAAG,YAC7B;EACA;CACF;CAEA,MAAM,aAAa,IAAI,mBAAmB,IAAI,KAAK,IAAI;CACvD,MAAM,WAAW,IAAI,mBAAmB,IAAI,KAAK,EAAE;CACnD,IAAI,CAAC,cAAc,CAAC,UAAU;EAC5B,MAAM,KAAK,CAAC,aAAa,KAAK,OAAO,KAAK;EAC1C,IAAI,aAAa,YAAY,IAC3B,6BACA,cAAc,GAAG,wEACnB;EACA;CACF;CAEA,MAAM,YAAY,eAAe,WAAW,OAAO,SAAS,MAAM;CAClE,MAAM,UAAU,eAAe,SAAS,OAAO,WAAW,MAAM;CAChE,MAAM,OAAO,KAAK,IAAI,UAAU,GAAG,QAAQ,CAAC;CAC5C,MAAM,OAAO,KAAK,IAAI,UAAU,GAAG,QAAQ,CAAC;CAE5C,IAAI,UAAU,aAAa;EACzB,QAAQ;EACR,GAAG,uBAAuB;GACxB,GAAG;GACH,GAAG;GACH,GAAG,KAAK,IAAI,QAAQ,IAAI,UAAU,CAAC;GACnC,GAAG,KAAK,IAAI,QAAQ,IAAI,UAAU,CAAC;EACrC,CAAC;EACD,gBAAgB,QAAQ,IAAI,UAAU;EACtC,cAAc,QAAQ,IAAI,UAAU;EACpC,OAAO;GACL,aAAa,WAAW;GACxB,qBAAqB,UAAU;EACjC;EACA,KAAK;GACH,aAAa,SAAS;GACtB,qBAAqB,QAAQ;EAC/B;EACA,SAAS;GACP,MAAM,eAAe,KAAK,SAAS,QAAQ;GAC3C,OACE,KAAK,cAAc,KAAA,IACf,MAAM,KAAK,MAAM,QAAQ,KAAK,SAAS,CAAC,CAAC,IACzC,MAAM,KAAK;GACjB,MAAM,KAAK;GACX,SAAS,cAAc,iBAAiB,KAAK,UAAU,CAAC;GACxD,SAAS,cAAc,iBAAiB,KAAK,QAAQ,CAAC;EACxD;CACF,CAAC;AACH"}
@@ -1,6 +1,6 @@
1
1
  import { pxToEmu } from "../units.js";
2
2
  import { getContentArea } from "../utils/contentArea.js";
3
- import { toColorInput } from "../pptxAuthoring.js";
3
+ import { toColorInput } from "../glimpseAdapter.js";
4
4
  import { asEmu, asOoxmlPercent, asPt } from "@pptx-glimpse/document";
5
5
  //#region src/renderPptx/nodes/chart.ts
6
6
  const DEFAULT_BAR_CHART_COLORS = [
@@ -47,7 +47,7 @@ function renderChartNode(node, ctx) {
47
47
  const series = normalizeChartSeries(node.data);
48
48
  const chartColors = node.chartColors ?? (node.chartType === "pie" || node.chartType === "doughnut" ? DEFAULT_PIE_CHART_COLORS : DEFAULT_BAR_CHART_COLORS);
49
49
  const pointColors = chartColors.length > 0 && (node.chartType === "pie" || node.chartType === "doughnut" || node.chartType === "bar" && node.data.length === 1 && node.chartColors !== void 0 && node.chartColors.length > 1) ? node.data[0]?.values.map((_value, index) => chartColors[index % chartColors.length]) : void 0;
50
- ctx.buildContext.pptxAuthoring.registerChart({
50
+ ctx.authoring.addChart({
51
51
  chartType: node.chartType,
52
52
  series: series.map((item, index) => ({
53
53
  name: item.name,
@@ -1 +1 @@
1
- {"version":3,"file":"chart.js","names":[],"sources":["../../../src/renderPptx/nodes/chart.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { asEmu, asOoxmlPercent, asPt } from \"@pptx-glimpse/document\";\nimport { pxToEmu } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { toColorInput } from \"../pptxAuthoring.ts\";\n\ntype ChartPositionedNode = Extract<PositionedNode, { type: \"chart\" }>;\n\nconst DEFAULT_BAR_CHART_COLORS = [\n \"C0504D\",\n \"4F81BD\",\n \"9BBB59\",\n \"8064A2\",\n \"4BACC6\",\n \"F79646\",\n \"628FC6\",\n \"C86360\",\n \"C0504D\",\n \"4F81BD\",\n \"9BBB59\",\n \"8064A2\",\n \"4BACC6\",\n \"F79646\",\n \"628FC6\",\n \"C86360\",\n];\nconst DEFAULT_PIE_CHART_COLORS = [\n \"5DA5DA\",\n \"FAA43A\",\n \"60BD68\",\n \"F17CB0\",\n \"B2912F\",\n \"B276B2\",\n \"DECF3F\",\n \"F15854\",\n \"A7A7A7\",\n \"5DA5DA\",\n \"FAA43A\",\n \"60BD68\",\n \"F17CB0\",\n \"B2912F\",\n \"B276B2\",\n \"DECF3F\",\n \"F15854\",\n \"A7A7A7\",\n];\n\nexport function renderChartNode(\n node: ChartPositionedNode,\n ctx: RenderContext,\n): void {\n // sparkline モードは bar / line / area のみ対応。pie / doughnut / radar は\n // 元々凡例 / 軸の概念が異なるため sparkline=true でも通常描画にフォールバックする。\n const isSparkline =\n node.sparkline === true &&\n (node.chartType === \"bar\" ||\n node.chartType === \"line\" ||\n node.chartType === \"area\");\n\n const content = getContentArea(node);\n const series = normalizeChartSeries(node.data);\n const chartColors =\n node.chartColors ??\n (node.chartType === \"pie\" || node.chartType === \"doughnut\"\n ? DEFAULT_PIE_CHART_COLORS\n : DEFAULT_BAR_CHART_COLORS);\n const pointColors =\n chartColors.length > 0 &&\n (node.chartType === \"pie\" ||\n node.chartType === \"doughnut\" ||\n (node.chartType === \"bar\" &&\n node.data.length === 1 &&\n node.chartColors !== undefined &&\n node.chartColors.length > 1))\n ? node.data[0]?.values.map(\n (_value, index) => chartColors[index % chartColors.length],\n )\n : undefined;\n ctx.buildContext.pptxAuthoring.registerChart({\n chartType: node.chartType,\n series: series.map((item, index) => ({\n name: item.name,\n categories: item.labels,\n values: item.values,\n color: chartColors[index % chartColors.length],\n dataPoints:\n index === 0\n ? pointColors?.map((color, pointIndex) => ({\n index: pointIndex,\n fill: { kind: \"solid\", color: toColorInput(color)! },\n }))\n : undefined,\n marker:\n node.chartType === \"line\" || node.chartType === \"radar\"\n ? {\n symbol: \"circle\",\n size: 6,\n fill: {\n kind: \"solid\",\n color: toColorInput(chartColors[index % chartColors.length])!,\n },\n }\n : undefined,\n })),\n offsetX: asEmu(Math.round(pxToEmu(content.x))),\n offsetY: asEmu(Math.round(pxToEmu(content.y))),\n width: asEmu(Math.round(pxToEmu(Math.max(content.w, 1)))),\n height: asEmu(Math.round(pxToEmu(Math.max(content.h, 1)))),\n title:\n !isSparkline && node.showTitle ? node.title || \"Chart Title\" : undefined,\n titleStyle:\n !isSparkline && node.showTitle\n ? {\n fontFace: \"Arial\",\n fontSize: asPt(18),\n color: toColorInput(\"000000\"),\n bold: false,\n italic: false,\n }\n : undefined,\n displayBlanksAs: \"span\",\n roundedCorners: !isSparkline,\n chartArea: isSparkline\n ? {\n fill: {\n kind: \"solid\",\n color: {\n ...toColorInput(\"FFFFFF\")!,\n transforms: [{ kind: \"alpha\", value: asOoxmlPercent(0) }],\n },\n },\n }\n : { fill: { kind: \"none\" }, outline: { fill: { kind: \"none\" } } },\n plotArea: isSparkline\n ? {\n fill: {\n kind: \"solid\",\n color: {\n ...toColorInput(\"FFFFFF\")!,\n transforms: [{ kind: \"alpha\", value: asOoxmlPercent(0) }],\n },\n },\n }\n : { fill: { kind: \"none\" }, outline: { fill: { kind: \"none\" } } },\n showLegend: isSparkline ? false : (node.showLegend ?? false),\n radarStyle: node.chartType === \"radar\" ? node.radarStyle : undefined,\n categoryAxis: isSparkline\n ? { hidden: true, lineVisible: false, gridLinesVisible: false }\n : {\n majorTickMark: \"outside\",\n labelPosition: \"low\",\n numberFormat: { formatCode: \"General\", sourceLinked: true },\n showMultiLevelLabels: false,\n textStyle: {\n fontFace: \"Arial\",\n fontSize: asPt(12),\n color: toColorInput(\"000000\"),\n },\n },\n valueAxis: isSparkline\n ? { hidden: true, lineVisible: false, gridLinesVisible: false }\n : {\n majorTickMark: \"outside\",\n labelPosition: \"nextTo\",\n numberFormat: { formatCode: \"General\", sourceLinked: false },\n majorGridline: {\n width: asEmu(12700),\n fill: { kind: \"solid\", color: toColorInput(\"888888\")! },\n },\n textStyle: {\n fontFace: \"Arial\",\n fontSize: asPt(12),\n color: toColorInput(\"000000\"),\n },\n },\n plotLayout: isSparkline\n ? { coordinateMode: \"edge\", x: 0, y: 0, width: 1, height: 1 }\n : undefined,\n });\n}\n\n/**\n * glimpse の native writer は全系列で同じ category 軸と同じ点数を要求する。\n * 従来受理していた不揃いな入力も生成を継続できるよう、位置ベースで\n * category を共有し、欠けた値を 0 で補う。\n */\nfunction normalizeChartSeries(data: ChartPositionedNode[\"data\"]) {\n const sourceData = data.length > 0 ? data : [{ labels: [], values: [] }];\n const pointCount = Math.max(\n 1,\n ...sourceData.flatMap((series) => [\n series.labels.length,\n series.values.length,\n ]),\n );\n const categories = Array.from(\n { length: pointCount },\n (_, index) =>\n sourceData.find((series) => series.labels[index] !== undefined)?.labels[\n index\n ] ?? \"\",\n );\n return sourceData.map((series) => ({\n name: series.name,\n labels: categories,\n values: Array.from(\n { length: pointCount },\n (_, index) => series.values[index] ?? 0,\n ),\n }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart.js","names":[],"sources":["../../../src/renderPptx/nodes/chart.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { asEmu, asOoxmlPercent, asPt } from \"@pptx-glimpse/document\";\nimport { pxToEmu } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { toColorInput } from \"../glimpseAdapter.ts\";\n\ntype ChartPositionedNode = Extract<PositionedNode, { type: \"chart\" }>;\n\nconst DEFAULT_BAR_CHART_COLORS = [\n \"C0504D\",\n \"4F81BD\",\n \"9BBB59\",\n \"8064A2\",\n \"4BACC6\",\n \"F79646\",\n \"628FC6\",\n \"C86360\",\n \"C0504D\",\n \"4F81BD\",\n \"9BBB59\",\n \"8064A2\",\n \"4BACC6\",\n \"F79646\",\n \"628FC6\",\n \"C86360\",\n];\nconst DEFAULT_PIE_CHART_COLORS = [\n \"5DA5DA\",\n \"FAA43A\",\n \"60BD68\",\n \"F17CB0\",\n \"B2912F\",\n \"B276B2\",\n \"DECF3F\",\n \"F15854\",\n \"A7A7A7\",\n \"5DA5DA\",\n \"FAA43A\",\n \"60BD68\",\n \"F17CB0\",\n \"B2912F\",\n \"B276B2\",\n \"DECF3F\",\n \"F15854\",\n \"A7A7A7\",\n];\n\nexport function renderChartNode(\n node: ChartPositionedNode,\n ctx: RenderContext,\n): void {\n // sparkline モードは bar / line / area のみ対応。pie / doughnut / radar は\n // 元々凡例 / 軸の概念が異なるため sparkline=true でも通常描画にフォールバックする。\n const isSparkline =\n node.sparkline === true &&\n (node.chartType === \"bar\" ||\n node.chartType === \"line\" ||\n node.chartType === \"area\");\n\n const content = getContentArea(node);\n const series = normalizeChartSeries(node.data);\n const chartColors =\n node.chartColors ??\n (node.chartType === \"pie\" || node.chartType === \"doughnut\"\n ? DEFAULT_PIE_CHART_COLORS\n : DEFAULT_BAR_CHART_COLORS);\n const pointColors =\n chartColors.length > 0 &&\n (node.chartType === \"pie\" ||\n node.chartType === \"doughnut\" ||\n (node.chartType === \"bar\" &&\n node.data.length === 1 &&\n node.chartColors !== undefined &&\n node.chartColors.length > 1))\n ? node.data[0]?.values.map(\n (_value, index) => chartColors[index % chartColors.length],\n )\n : undefined;\n ctx.authoring.addChart({\n chartType: node.chartType,\n series: series.map((item, index) => ({\n name: item.name,\n categories: item.labels,\n values: item.values,\n color: chartColors[index % chartColors.length],\n dataPoints:\n index === 0\n ? pointColors?.map((color, pointIndex) => ({\n index: pointIndex,\n fill: { kind: \"solid\", color: toColorInput(color)! },\n }))\n : undefined,\n marker:\n node.chartType === \"line\" || node.chartType === \"radar\"\n ? {\n symbol: \"circle\",\n size: 6,\n fill: {\n kind: \"solid\",\n color: toColorInput(chartColors[index % chartColors.length])!,\n },\n }\n : undefined,\n })),\n offsetX: asEmu(Math.round(pxToEmu(content.x))),\n offsetY: asEmu(Math.round(pxToEmu(content.y))),\n width: asEmu(Math.round(pxToEmu(Math.max(content.w, 1)))),\n height: asEmu(Math.round(pxToEmu(Math.max(content.h, 1)))),\n title:\n !isSparkline && node.showTitle ? node.title || \"Chart Title\" : undefined,\n titleStyle:\n !isSparkline && node.showTitle\n ? {\n fontFace: \"Arial\",\n fontSize: asPt(18),\n color: toColorInput(\"000000\"),\n bold: false,\n italic: false,\n }\n : undefined,\n displayBlanksAs: \"span\",\n roundedCorners: !isSparkline,\n chartArea: isSparkline\n ? {\n fill: {\n kind: \"solid\",\n color: {\n ...toColorInput(\"FFFFFF\")!,\n transforms: [{ kind: \"alpha\", value: asOoxmlPercent(0) }],\n },\n },\n }\n : { fill: { kind: \"none\" }, outline: { fill: { kind: \"none\" } } },\n plotArea: isSparkline\n ? {\n fill: {\n kind: \"solid\",\n color: {\n ...toColorInput(\"FFFFFF\")!,\n transforms: [{ kind: \"alpha\", value: asOoxmlPercent(0) }],\n },\n },\n }\n : { fill: { kind: \"none\" }, outline: { fill: { kind: \"none\" } } },\n showLegend: isSparkline ? false : (node.showLegend ?? false),\n radarStyle: node.chartType === \"radar\" ? node.radarStyle : undefined,\n categoryAxis: isSparkline\n ? { hidden: true, lineVisible: false, gridLinesVisible: false }\n : {\n majorTickMark: \"outside\",\n labelPosition: \"low\",\n numberFormat: { formatCode: \"General\", sourceLinked: true },\n showMultiLevelLabels: false,\n textStyle: {\n fontFace: \"Arial\",\n fontSize: asPt(12),\n color: toColorInput(\"000000\"),\n },\n },\n valueAxis: isSparkline\n ? { hidden: true, lineVisible: false, gridLinesVisible: false }\n : {\n majorTickMark: \"outside\",\n labelPosition: \"nextTo\",\n numberFormat: { formatCode: \"General\", sourceLinked: false },\n majorGridline: {\n width: asEmu(12700),\n fill: { kind: \"solid\", color: toColorInput(\"888888\")! },\n },\n textStyle: {\n fontFace: \"Arial\",\n fontSize: asPt(12),\n color: toColorInput(\"000000\"),\n },\n },\n plotLayout: isSparkline\n ? { coordinateMode: \"edge\", x: 0, y: 0, width: 1, height: 1 }\n : undefined,\n });\n}\n\n/**\n * glimpse の native writer は全系列で同じ category 軸と同じ点数を要求する。\n * 従来受理していた不揃いな入力も生成を継続できるよう、位置ベースで\n * category を共有し、欠けた値を 0 で補う。\n */\nfunction normalizeChartSeries(data: ChartPositionedNode[\"data\"]) {\n const sourceData = data.length > 0 ? data : [{ labels: [], values: [] }];\n const pointCount = Math.max(\n 1,\n ...sourceData.flatMap((series) => [\n series.labels.length,\n series.values.length,\n ]),\n );\n const categories = Array.from(\n { length: pointCount },\n (_, index) =>\n sourceData.find((series) => series.labels[index] !== undefined)?.labels[\n index\n ] ?? \"\",\n );\n return sourceData.map((series) => ({\n name: series.name,\n labels: categories,\n values: Array.from(\n { length: pointCount },\n (_, index) => series.values[index] ?? 0,\n ),\n }));\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { pxToEmu } from "../units.js";
2
- import { toColorInput } from "../pptxAuthoring.js";
2
+ import { toColorInput } from "../glimpseAdapter.js";
3
3
  import { addGlimpsePicture, imageBytesFromSource } from "../utils/glimpsePicture.js";
4
4
  import { addGlimpseShape, createShapeBoundsInput, createShapeRotationInput, noShapeOutline, noneShapeFill, shapeOutline, solidShapeFill } from "../utils/glimpseShape.js";
5
5
  import { asEmu } from "@pptx-glimpse/document";
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import { asEmu } from \"@pptx-glimpse/document\";\nimport type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { toColorInput } from \"../pptxAuthoring.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n addGlimpsePicture,\n imageBytesFromSource,\n} from \"../utils/glimpsePicture.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n createShapeRotationInput,\n noShapeOutline,\n noneShapeFill,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\n\ntype IconPositionedNode = Extract<PositionedNode, { type: \"icon\" }>;\n\nexport function renderIconNode(\n node: IconPositionedNode,\n ctx: RenderContext,\n): void {\n // variant 指定時は背景図形を描画\n if (node.variant) {\n const isCircle = node.variant.startsWith(\"circle\");\n const isFilled = node.variant.endsWith(\"-filled\");\n const bgColor = node.bgColor ?? \"#E0E0E0\";\n const colorValue = bgColor.replace(/^#/, \"\");\n\n // 背景図形の line のデフォルト: outlined variant は colorValue / 1.5pt 相当 (2px)、\n // filled variant は undefined (枠線なし)。\n const variantDefaultLine = isFilled\n ? undefined\n : { color: colorValue, width: 2 };\n // outline 指定時は variant のデフォルト line とフィールド単位でマージする。\n // outline 側で省略された属性は variant default の値を引き継ぐので、例えば\n // outlined variant に `outline.color` だけ指定すると、太さは 1.5pt のまま\n // 色だけ outline で上書きされる。\n const outlineLine = node.outline\n ? {\n color: node.outline.color ?? variantDefaultLine?.color ?? \"FFFFFF\",\n width:\n node.outline.size !== undefined\n ? node.outline.size\n : (variantDefaultLine?.width ?? 1),\n }\n : variantDefaultLine;\n\n const bounds = {\n x: node.bgX ?? node.x,\n y: node.bgY ?? node.y,\n w: node.bgW ?? node.w,\n h: node.bgH ?? node.h,\n };\n const shapeType = isCircle ? \"ellipse\" : \"roundRect\";\n\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: shapeType },\n ...createShapeBoundsInput(bounds),\n rotation: createShapeRotationInput(node.rotate),\n fill: isFilled ? solidShapeFill(colorValue) : noneShapeFill(),\n outline: outlineLine ? shapeOutline(outlineLine) : noShapeOutline(),\n effects: node.glow\n ? {\n glow: {\n radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),\n color: toColorInput(node.glow.color ?? \"FFFFFF\")!,\n },\n }\n : undefined,\n },\n bounds,\n {\n fillColor: isFilled ? colorValue : undefined,\n glow: node.glow,\n rectRadius: isCircle ? undefined : 0.1,\n },\n );\n }\n\n addGlimpsePicture(\n ctx,\n {\n x: node.iconX ?? node.x,\n y: node.iconY ?? node.y,\n w: node.iconW ?? node.w,\n h: node.iconH ?? node.h,\n },\n imageBytesFromSource(\"\", node.iconImageData),\n { rotate: node.rotate },\n );\n}\n"],"mappings":";;;;;;AAqBA,SAAgB,eACd,MACA,KACM;CAEN,IAAI,KAAK,SAAS;EAChB,MAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;EACjD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS;EAEhD,MAAM,cADU,KAAK,WAAW,UAAA,CACL,QAAQ,MAAM,EAAE;EAI3C,MAAM,qBAAqB,WACvB,KAAA,IACA;GAAE,OAAO;GAAY,OAAO;EAAE;EAKlC,MAAM,cAAc,KAAK,UACrB;GACE,OAAO,KAAK,QAAQ,SAAS,oBAAoB,SAAS;GAC1D,OACE,KAAK,QAAQ,SAAS,KAAA,IAClB,KAAK,QAAQ,OACZ,oBAAoB,SAAS;EACtC,IACA;EAEJ,MAAM,SAAS;GACb,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;EACtB;EAGA,gBACE,KACA;GACE,UAAU;IAAE,MAAM;IAAU,QALd,WAAW,YAAY;GAKS;GAC9C,GAAG,uBAAuB,MAAM;GAChC,UAAU,yBAAyB,KAAK,MAAM;GAC9C,MAAM,WAAW,eAAe,UAAU,IAAI,cAAc;GAC5D,SAAS,cAAc,aAAa,WAAW,IAAI,eAAe;GAClE,SAAS,KAAK,OACV,EACE,MAAM;IACJ,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,aAAa,KAAK,KAAK,SAAS,QAAQ;GACjD,EACF,IACA,KAAA;EACN,GACA,QACA;GACE,WAAW,WAAW,aAAa,KAAA;GACnC,MAAM,KAAK;GACX,YAAY,WAAW,KAAA,IAAY;EACrC,CACF;CACF;CAEA,kBACE,KACA;EACE,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;CACxB,GACA,qBAAqB,IAAI,KAAK,aAAa,GAC3C,EAAE,QAAQ,KAAK,OAAO,CACxB;AACF"}
1
+ {"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import { asEmu } from \"@pptx-glimpse/document\";\nimport type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { toColorInput } from \"../glimpseAdapter.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n addGlimpsePicture,\n imageBytesFromSource,\n} from \"../utils/glimpsePicture.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n createShapeRotationInput,\n noShapeOutline,\n noneShapeFill,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\n\ntype IconPositionedNode = Extract<PositionedNode, { type: \"icon\" }>;\n\nexport function renderIconNode(\n node: IconPositionedNode,\n ctx: RenderContext,\n): void {\n // variant 指定時は背景図形を描画\n if (node.variant) {\n const isCircle = node.variant.startsWith(\"circle\");\n const isFilled = node.variant.endsWith(\"-filled\");\n const bgColor = node.bgColor ?? \"#E0E0E0\";\n const colorValue = bgColor.replace(/^#/, \"\");\n\n // 背景図形の line のデフォルト: outlined variant は colorValue / 1.5pt 相当 (2px)、\n // filled variant は undefined (枠線なし)。\n const variantDefaultLine = isFilled\n ? undefined\n : { color: colorValue, width: 2 };\n // outline 指定時は variant のデフォルト line とフィールド単位でマージする。\n // outline 側で省略された属性は variant default の値を引き継ぐので、例えば\n // outlined variant に `outline.color` だけ指定すると、太さは 1.5pt のまま\n // 色だけ outline で上書きされる。\n const outlineLine = node.outline\n ? {\n color: node.outline.color ?? variantDefaultLine?.color ?? \"FFFFFF\",\n width:\n node.outline.size !== undefined\n ? node.outline.size\n : (variantDefaultLine?.width ?? 1),\n }\n : variantDefaultLine;\n\n const bounds = {\n x: node.bgX ?? node.x,\n y: node.bgY ?? node.y,\n w: node.bgW ?? node.w,\n h: node.bgH ?? node.h,\n };\n const shapeType = isCircle ? \"ellipse\" : \"roundRect\";\n\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: shapeType },\n ...createShapeBoundsInput(bounds),\n rotation: createShapeRotationInput(node.rotate),\n fill: isFilled ? solidShapeFill(colorValue) : noneShapeFill(),\n outline: outlineLine ? shapeOutline(outlineLine) : noShapeOutline(),\n effects: node.glow\n ? {\n glow: {\n radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),\n color: toColorInput(node.glow.color ?? \"FFFFFF\")!,\n },\n }\n : undefined,\n },\n bounds,\n {\n fillColor: isFilled ? colorValue : undefined,\n glow: node.glow,\n rectRadius: isCircle ? undefined : 0.1,\n },\n );\n }\n\n addGlimpsePicture(\n ctx,\n {\n x: node.iconX ?? node.x,\n y: node.iconY ?? node.y,\n w: node.iconW ?? node.w,\n h: node.iconH ?? node.h,\n },\n imageBytesFromSource(\"\", node.iconImageData),\n { rotate: node.rotate },\n );\n}\n"],"mappings":";;;;;;AAqBA,SAAgB,eACd,MACA,KACM;CAEN,IAAI,KAAK,SAAS;EAChB,MAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;EACjD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS;EAEhD,MAAM,cADU,KAAK,WAAW,UAAA,CACL,QAAQ,MAAM,EAAE;EAI3C,MAAM,qBAAqB,WACvB,KAAA,IACA;GAAE,OAAO;GAAY,OAAO;EAAE;EAKlC,MAAM,cAAc,KAAK,UACrB;GACE,OAAO,KAAK,QAAQ,SAAS,oBAAoB,SAAS;GAC1D,OACE,KAAK,QAAQ,SAAS,KAAA,IAClB,KAAK,QAAQ,OACZ,oBAAoB,SAAS;EACtC,IACA;EAEJ,MAAM,SAAS;GACb,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;EACtB;EAGA,gBACE,KACA;GACE,UAAU;IAAE,MAAM;IAAU,QALd,WAAW,YAAY;GAKS;GAC9C,GAAG,uBAAuB,MAAM;GAChC,UAAU,yBAAyB,KAAK,MAAM;GAC9C,MAAM,WAAW,eAAe,UAAU,IAAI,cAAc;GAC5D,SAAS,cAAc,aAAa,WAAW,IAAI,eAAe;GAClE,SAAS,KAAK,OACV,EACE,MAAM;IACJ,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,aAAa,KAAK,KAAK,SAAS,QAAQ;GACjD,EACF,IACA,KAAA;EACN,GACA,QACA;GACE,WAAW,WAAW,aAAa,KAAA;GACnC,MAAM,KAAK;GACX,YAAY,WAAW,KAAA,IAAY;EACrC,CACF;CACF;CAEA,kBACE,KACA;EACE,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;CACxB,GACA,qBAAqB,IAAI,KAAK,aAAa,GAC3C,EAAE,QAAQ,KAAK,OAAO,CACxB;AACF"}
@@ -1,6 +1,7 @@
1
1
  import { getContentArea } from "../utils/contentArea.js";
2
2
  import { resolveSubSup } from "../textOptions.js";
3
- import { addGlimpseTextBox, createGlimpseRunProperties } from "../utils/glimpseTextBox.js";
3
+ import { createGlimpseRunProperties } from "../glimpseAdapter.js";
4
+ import { addGlimpseTextBox } from "../utils/glimpseTextBox.js";
4
5
  //#region src/renderPptx/nodes/list.ts
5
6
  function resolveStyle(li, parent) {
6
7
  const subSup = resolveSubSup(li, parent);
@@ -36,7 +37,6 @@ function toRunStyle(style) {
36
37
  }
37
38
  function buildListParagraphs(items, parent) {
38
39
  const paragraphs = [];
39
- const hyperlinks = [];
40
40
  for (let i = 0; i < items.length; i++) {
41
41
  const li = items[i];
42
42
  const style = resolveStyle(li, parent);
@@ -56,32 +56,26 @@ function buildListParagraphs(items, parent) {
56
56
  subscript: runSubSup.subscript,
57
57
  superscript: runSubSup.superscript,
58
58
  highlight: run.highlight ?? style.highlight
59
- })
59
+ }),
60
+ hyperlink: run.text ? run.href : void 0
60
61
  });
61
- hyperlinks.push(run.text ? run.href : void 0);
62
- }
63
- else {
64
- runs.push({
65
- text: li.text,
66
- properties: createGlimpseRunProperties(toRunStyle(style))
67
- });
68
- hyperlinks.push(void 0);
69
62
  }
63
+ else runs.push({
64
+ text: li.text,
65
+ properties: createGlimpseRunProperties(toRunStyle(style))
66
+ });
70
67
  paragraphs.push({
71
68
  properties: paragraphProperties(parent),
72
69
  runs
73
70
  });
74
71
  }
75
- return {
76
- paragraphs,
77
- hyperlinks
78
- };
72
+ return paragraphs;
79
73
  }
80
74
  function renderUlNode(node, ctx) {
81
75
  const fontSizePx = node.fontSize ?? 24;
82
76
  const fontFamily = node.fontFamily ?? "Noto Sans JP";
83
77
  const content = getContentArea(node);
84
- const { paragraphs, hyperlinks } = buildListParagraphs(node.items, node);
78
+ const paragraphs = buildListParagraphs(node.items, node);
85
79
  addGlimpseTextBox(ctx, content, {
86
80
  fontSize: fontSizePx,
87
81
  fontFace: fontFamily,
@@ -97,7 +91,6 @@ function renderUlNode(node, ctx) {
97
91
  superscript: node.superscript,
98
92
  highlight: node.highlight,
99
93
  paragraphs,
100
- hyperlinks,
101
94
  lineHeight: node.lineHeight,
102
95
  bullet: { kind: "bullet" }
103
96
  });
@@ -106,7 +99,7 @@ function renderOlNode(node, ctx) {
106
99
  const fontSizePx = node.fontSize ?? 24;
107
100
  const fontFamily = node.fontFamily ?? "Noto Sans JP";
108
101
  const content = getContentArea(node);
109
- const { paragraphs, hyperlinks } = buildListParagraphs(node.items, node);
102
+ const paragraphs = buildListParagraphs(node.items, node);
110
103
  addGlimpseTextBox(ctx, content, {
111
104
  fontSize: fontSizePx,
112
105
  fontFace: fontFamily,
@@ -122,7 +115,6 @@ function renderOlNode(node, ctx) {
122
115
  superscript: node.superscript,
123
116
  highlight: node.highlight,
124
117
  paragraphs,
125
- hyperlinks,
126
118
  lineHeight: node.lineHeight,
127
119
  bullet: {
128
120
  kind: "number",
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","names":[],"sources":["../../../src/renderPptx/nodes/list.ts"],"sourcesContent":["import type { PositionedNode, LiNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { resolveSubSup } from \"../textOptions.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport {\n addGlimpseTextBox,\n createGlimpseRunProperties,\n type GlimpseTextRunStyle,\n} from \"../utils/glimpseTextBox.ts\";\nimport {\n type AddTextBoxParagraphInput,\n type AddTextBoxRunInput,\n} from \"@pptx-glimpse/document\";\n\ntype UlPositionedNode = Extract<PositionedNode, { type: \"ul\" }>;\ntype OlPositionedNode = Extract<PositionedNode, { type: \"ol\" }>;\n\nfunction resolveStyle(li: LiNode, parent: UlPositionedNode | OlPositionedNode) {\n const subSup = resolveSubSup(li, parent);\n return {\n fontSize: li.fontSize ?? parent.fontSize ?? 24,\n color: li.color ?? parent.color,\n bold: li.bold ?? parent.bold,\n italic: li.italic ?? parent.italic,\n underline: li.underline ?? parent.underline,\n strike: li.strike ?? parent.strike,\n subscript: subSup.subscript,\n superscript: subSup.superscript,\n highlight: li.highlight ?? parent.highlight,\n fontFamily: li.fontFamily ?? parent.fontFamily ?? \"Noto Sans JP\",\n };\n}\n\nfunction paragraphProperties(parent: UlPositionedNode | OlPositionedNode) {\n return {\n align: parent.textAlign ?? \"left\",\n };\n}\n\nfunction toRunStyle(\n style: ReturnType<typeof resolveStyle>,\n): GlimpseTextRunStyle {\n return {\n fontSize: style.fontSize,\n fontFace: style.fontFamily,\n color: style.color,\n bold: style.bold,\n italic: style.italic,\n underline: style.underline,\n strike: style.strike,\n subscript: style.subscript,\n superscript: style.superscript,\n highlight: style.highlight,\n };\n}\n\nfunction buildListParagraphs(\n items: LiNode[],\n parent: UlPositionedNode | OlPositionedNode,\n): {\n paragraphs: AddTextBoxParagraphInput[];\n hyperlinks: (string | undefined)[];\n} {\n const paragraphs: AddTextBoxParagraphInput[] = [];\n const hyperlinks: (string | undefined)[] = [];\n for (let i = 0; i < items.length; i++) {\n const li = items[i];\n const style = resolveStyle(li, parent);\n const runs: AddTextBoxRunInput[] = [];\n if (li.runs && li.runs.length > 0) {\n for (const run of li.runs) {\n const runSubSup = resolveSubSup(run, style);\n runs.push({\n text: run.text,\n properties: createGlimpseRunProperties({\n fontSize: run.fontSize ?? style.fontSize,\n fontFace: run.fontFamily ?? style.fontFamily,\n color: run.color ?? style.color,\n bold: run.bold ?? style.bold,\n italic: run.italic ?? style.italic,\n underline: run.underline ?? style.underline,\n strike: run.strike ?? style.strike,\n subscript: runSubSup.subscript,\n superscript: runSubSup.superscript,\n highlight: run.highlight ?? style.highlight,\n }),\n });\n hyperlinks.push(run.text ? run.href : undefined);\n }\n } else {\n runs.push({\n text: li.text,\n properties: createGlimpseRunProperties(toRunStyle(style)),\n });\n hyperlinks.push(undefined);\n }\n paragraphs.push({\n properties: paragraphProperties(parent),\n runs,\n });\n }\n return { paragraphs, hyperlinks };\n}\n\nexport function renderUlNode(node: UlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const content = getContentArea(node);\n\n const { paragraphs, hyperlinks } = buildListParagraphs(node.items, node);\n addGlimpseTextBox(ctx, content, {\n fontSize: fontSizePx,\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\",\n margin: 0,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: node.underline,\n strike: node.strike,\n subscript: node.subscript,\n superscript: node.superscript,\n highlight: node.highlight,\n paragraphs,\n hyperlinks,\n lineHeight: node.lineHeight,\n bullet: {\n kind: \"bullet\",\n },\n });\n}\n\nexport function renderOlNode(node: OlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const content = getContentArea(node);\n\n const { paragraphs, hyperlinks } = buildListParagraphs(node.items, node);\n addGlimpseTextBox(ctx, content, {\n fontSize: fontSizePx,\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\",\n margin: 0,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: node.underline,\n strike: node.strike,\n subscript: node.subscript,\n superscript: node.superscript,\n highlight: node.highlight,\n paragraphs,\n hyperlinks,\n lineHeight: node.lineHeight,\n bullet: {\n kind: \"number\",\n scheme: node.numberType,\n startAt: node.numberStartAt,\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"list.js","names":[],"sources":["../../../src/renderPptx/nodes/list.ts"],"sourcesContent":["import type { PositionedNode, LiNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { resolveSubSup } from \"../textOptions.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport {\n addGlimpseTextBox,\n createGlimpseRunProperties,\n type GlimpseTextRunStyle,\n} from \"../utils/glimpseTextBox.ts\";\nimport {\n type AddTextBoxParagraphInput,\n type AddTextBoxRunInput,\n} from \"@pptx-glimpse/document\";\n\ntype UlPositionedNode = Extract<PositionedNode, { type: \"ul\" }>;\ntype OlPositionedNode = Extract<PositionedNode, { type: \"ol\" }>;\n\nfunction resolveStyle(li: LiNode, parent: UlPositionedNode | OlPositionedNode) {\n const subSup = resolveSubSup(li, parent);\n return {\n fontSize: li.fontSize ?? parent.fontSize ?? 24,\n color: li.color ?? parent.color,\n bold: li.bold ?? parent.bold,\n italic: li.italic ?? parent.italic,\n underline: li.underline ?? parent.underline,\n strike: li.strike ?? parent.strike,\n subscript: subSup.subscript,\n superscript: subSup.superscript,\n highlight: li.highlight ?? parent.highlight,\n fontFamily: li.fontFamily ?? parent.fontFamily ?? \"Noto Sans JP\",\n };\n}\n\nfunction paragraphProperties(parent: UlPositionedNode | OlPositionedNode) {\n return {\n align: parent.textAlign ?? \"left\",\n };\n}\n\nfunction toRunStyle(\n style: ReturnType<typeof resolveStyle>,\n): GlimpseTextRunStyle {\n return {\n fontSize: style.fontSize,\n fontFace: style.fontFamily,\n color: style.color,\n bold: style.bold,\n italic: style.italic,\n underline: style.underline,\n strike: style.strike,\n subscript: style.subscript,\n superscript: style.superscript,\n highlight: style.highlight,\n };\n}\n\nfunction buildListParagraphs(\n items: LiNode[],\n parent: UlPositionedNode | OlPositionedNode,\n): AddTextBoxParagraphInput[] {\n const paragraphs: AddTextBoxParagraphInput[] = [];\n for (let i = 0; i < items.length; i++) {\n const li = items[i];\n const style = resolveStyle(li, parent);\n const runs: AddTextBoxRunInput[] = [];\n if (li.runs && li.runs.length > 0) {\n for (const run of li.runs) {\n const runSubSup = resolveSubSup(run, style);\n runs.push({\n text: run.text,\n properties: createGlimpseRunProperties({\n fontSize: run.fontSize ?? style.fontSize,\n fontFace: run.fontFamily ?? style.fontFamily,\n color: run.color ?? style.color,\n bold: run.bold ?? style.bold,\n italic: run.italic ?? style.italic,\n underline: run.underline ?? style.underline,\n strike: run.strike ?? style.strike,\n subscript: runSubSup.subscript,\n superscript: runSubSup.superscript,\n highlight: run.highlight ?? style.highlight,\n }),\n hyperlink: run.text ? run.href : undefined,\n });\n }\n } else {\n runs.push({\n text: li.text,\n properties: createGlimpseRunProperties(toRunStyle(style)),\n });\n }\n paragraphs.push({\n properties: paragraphProperties(parent),\n runs,\n });\n }\n return paragraphs;\n}\n\nexport function renderUlNode(node: UlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const content = getContentArea(node);\n\n const paragraphs = buildListParagraphs(node.items, node);\n addGlimpseTextBox(ctx, content, {\n fontSize: fontSizePx,\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\",\n margin: 0,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: node.underline,\n strike: node.strike,\n subscript: node.subscript,\n superscript: node.superscript,\n highlight: node.highlight,\n paragraphs,\n lineHeight: node.lineHeight,\n bullet: {\n kind: \"bullet\",\n },\n });\n}\n\nexport function renderOlNode(node: OlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const content = getContentArea(node);\n\n const paragraphs = buildListParagraphs(node.items, node);\n addGlimpseTextBox(ctx, content, {\n fontSize: fontSizePx,\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\",\n margin: 0,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: node.underline,\n strike: node.strike,\n subscript: node.subscript,\n superscript: node.superscript,\n highlight: node.highlight,\n paragraphs,\n lineHeight: node.lineHeight,\n bullet: {\n kind: \"number\",\n scheme: node.numberType,\n startAt: node.numberStartAt,\n },\n });\n}\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { pxToEmu, pxToPt } from "../units.js";
2
2
  import { getContentArea } from "../utils/contentArea.js";
3
- import { toColorInput } from "../pptxAuthoring.js";
3
+ import { createGlimpseShapeRunProperties, toColorInput } from "../glimpseAdapter.js";
4
+ import { cardinalConnectorSites, supportsCardinalConnectorSites } from "../utils/connectorSites.js";
4
5
  import { addGlimpseShape, createShapeBoundsInput, createShapeRotationInput, noneShapeFill, shapeOutline, solidShapeFill } from "../utils/glimpseShape.js";
5
- import { asEmu, asHundredthPt, asPt } from "@pptx-glimpse/document";
6
+ import { asEmu, asHundredthPt } from "@pptx-glimpse/document";
6
7
  //#region src/renderPptx/nodes/shape.ts
7
8
  /**
8
9
  * outline (Text と同じ書式の `outline.size` / `outline.color`) と
@@ -23,26 +24,19 @@ function resolveShapeLine(line, outline) {
23
24
  dashType: line?.dashType
24
25
  };
25
26
  }
26
- function toUnderlineInput(underline) {
27
- if (underline === void 0 || underline === false) return void 0;
28
- if (underline === true) return true;
29
- return {
30
- style: underline.style,
31
- color: toColorInput(underline.color)
32
- };
33
- }
34
27
  function buildShapeTextProperties(node) {
35
- return {
36
- fontFace: node.fontFamily ?? "Noto Sans JP",
37
- fontSize: asPt(pxToPt(node.fontSize ?? 24)),
38
- color: toColorInput(node.color),
28
+ return createGlimpseShapeRunProperties({
29
+ fontFace: node.fontFamily,
30
+ fontSize: node.fontSize,
31
+ color: node.color,
39
32
  bold: node.bold,
40
33
  italic: node.italic,
41
- underline: toUnderlineInput(node.underline),
34
+ underline: node.underline,
42
35
  strike: node.strike,
43
- baseline: node.subscript ? "subscript" : node.superscript ? "superscript" : void 0,
44
- highlight: toColorInput(node.highlight)
45
- };
36
+ subscript: node.subscript,
37
+ superscript: node.superscript,
38
+ highlight: node.highlight
39
+ });
46
40
  }
47
41
  function buildShapeParagraphs(node) {
48
42
  if (!node.text) return void 0;
@@ -64,7 +58,7 @@ function renderShapeNode(node, ctx) {
64
58
  const lineSpec = resolveShapeLine(node.line, node.outline);
65
59
  const boundsPx = getContentArea(node);
66
60
  const fillOpacity = node.fill?.transparency !== void 0 ? 1 - node.fill.transparency / 100 : void 0;
67
- addGlimpseShape(ctx, {
61
+ const handle = addGlimpseShape(ctx, {
68
62
  geometry: {
69
63
  kind: "preset",
70
64
  preset: node.shapeType
@@ -86,6 +80,11 @@ function renderShapeNode(node, ctx) {
86
80
  shadow: node.shadow,
87
81
  dashType: lineSpec?.dashType
88
82
  });
83
+ if (node.id && ctx.idNodeMap.get(node.id) === node && supportsCardinalConnectorSites(node.shapeType)) ctx.connectorTargetMap.set(node.id, {
84
+ handle,
85
+ bounds: boundsPx,
86
+ sites: cardinalConnectorSites(boundsPx, node.rotate)
87
+ });
89
88
  }
90
89
  //#endregion
91
90
  export { renderShapeNode };
@@ -1 +1 @@
1
- {"version":3,"file":"shape.js","names":[],"sources":["../../../src/renderPptx/nodes/shape.ts"],"sourcesContent":["import {\n asEmu,\n asHundredthPt,\n asPt,\n type AddShapeParagraphInput,\n type AddShapeRunPropertiesInput,\n} from \"@pptx-glimpse/document\";\nimport type { BorderStyle, PositionedNode, Underline } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToPt } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport { toColorInput } from \"../pptxAuthoring.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n createShapeRotationInput,\n noneShapeFill,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\n\ntype ShapePositionedNode = Extract<PositionedNode, { type: \"shape\" }>;\n\n/**\n * outline (Text と同じ書式の `outline.size` / `outline.color`) と\n * 既存 `line` 属性 (`line.color` / `line.width` / `line.dashType`) を\n * 1 つの BorderStyle にマージする。\n *\n * フィールド単位のマージで、`outline` の指定があるフィールドは `line` を\n * 上書きするが、`outline` 側で省略されたフィールドは `line` の値を引き継ぎ、\n * `line` にも値が無い場合は Text outline と同じ既定値 (`width: 1pt 相当` /\n * `color: FFFFFF`) を採用する。`dashType` は `outline` に対応フィールドが\n * 無いため `line.dashType` をそのまま使う。\n */\nfunction resolveShapeLine(\n line: BorderStyle | undefined,\n outline: { size?: number; color?: string } | undefined,\n): BorderStyle | undefined {\n if (!outline) return line;\n return {\n color: outline.color ?? line?.color ?? \"FFFFFF\",\n width: outline.size ?? line?.width ?? 1,\n dashType: line?.dashType,\n };\n}\n\nfunction toUnderlineInput(underline: Underline | undefined) {\n if (underline === undefined || underline === false) return undefined;\n if (underline === true) return true;\n return {\n style: underline.style,\n color: toColorInput(underline.color),\n };\n}\n\nfunction buildShapeTextProperties(\n node: ShapePositionedNode,\n): AddShapeRunPropertiesInput {\n return {\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n fontSize: asPt(pxToPt(node.fontSize ?? 24)),\n color: toColorInput(node.color),\n bold: node.bold,\n italic: node.italic,\n underline: toUnderlineInput(node.underline),\n strike: node.strike,\n baseline: node.subscript\n ? \"subscript\"\n : node.superscript\n ? \"superscript\"\n : undefined,\n highlight: toColorInput(node.highlight),\n };\n}\n\nfunction buildShapeParagraphs(\n node: ShapePositionedNode,\n): AddShapeParagraphInput[] | undefined {\n if (!node.text) return undefined;\n const fontSizePx = node.fontSize ?? 24;\n const lineHeight = node.lineHeight ?? 1.3;\n const properties = buildShapeTextProperties(node);\n return node.text\n .replace(/\\r*\\n/g, \"\\n\")\n .split(\"\\n\")\n .map((text) => ({\n properties: {\n align: node.textAlign ?? \"center\",\n lineSpacing: asHundredthPt(\n Math.round(pxToPt(fontSizePx * lineHeight) * 100),\n ),\n },\n runs: [{ text, properties }],\n }));\n}\n\nexport function renderShapeNode(\n node: ShapePositionedNode,\n ctx: RenderContext,\n): void {\n const lineSpec = resolveShapeLine(node.line, node.outline);\n const boundsPx = getContentArea(node);\n const fillOpacity =\n node.fill?.transparency !== undefined\n ? 1 - node.fill.transparency / 100\n : undefined;\n\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: node.shapeType },\n ...createShapeBoundsInput(boundsPx),\n rotation: createShapeRotationInput(node.rotate),\n fill: node.fill?.color\n ? solidShapeFill(node.fill.color)\n : noneShapeFill(),\n outline: shapeOutline(lineSpec),\n effects: node.glow\n ? {\n glow: {\n radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),\n color: toColorInput(node.glow.color ?? \"FFFFFF\")!,\n },\n }\n : undefined,\n body: node.text\n ? {\n anchor: \"middle\",\n }\n : undefined,\n paragraphs: buildShapeParagraphs(node),\n },\n boundsPx,\n {\n fillColor: node.fill?.color,\n fillOpacity,\n glow: node.glow,\n shadow: node.shadow,\n dashType: lineSpec?.dashType,\n },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmCA,SAAS,iBACP,MACA,SACyB;CACzB,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO;EACL,OAAO,QAAQ,SAAS,MAAM,SAAS;EACvC,OAAO,QAAQ,QAAQ,MAAM,SAAS;EACtC,UAAU,MAAM;CAClB;AACF;AAEA,SAAS,iBAAiB,WAAkC;CAC1D,IAAI,cAAc,KAAA,KAAa,cAAc,OAAO,OAAO,KAAA;CAC3D,IAAI,cAAc,MAAM,OAAO;CAC/B,OAAO;EACL,OAAO,UAAU;EACjB,OAAO,aAAa,UAAU,KAAK;CACrC;AACF;AAEA,SAAS,yBACP,MAC4B;CAC5B,OAAO;EACL,UAAU,KAAK,cAAc;EAC7B,UAAU,KAAK,OAAO,KAAK,YAAY,EAAE,CAAC;EAC1C,OAAO,aAAa,KAAK,KAAK;EAC9B,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,iBAAiB,KAAK,SAAS;EAC1C,QAAQ,KAAK;EACb,UAAU,KAAK,YACX,cACA,KAAK,cACH,gBACA,KAAA;EACN,WAAW,aAAa,KAAK,SAAS;CACxC;AACF;AAEA,SAAS,qBACP,MACsC;CACtC,IAAI,CAAC,KAAK,MAAM,OAAO,KAAA;CACvB,MAAM,aAAa,KAAK,YAAY;CACpC,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,aAAa,yBAAyB,IAAI;CAChD,OAAO,KAAK,KACT,QAAQ,UAAU,IAAI,CAAC,CACvB,MAAM,IAAI,CAAC,CACX,KAAK,UAAU;EACd,YAAY;GACV,OAAO,KAAK,aAAa;GACzB,aAAa,cACX,KAAK,MAAM,OAAO,aAAa,UAAU,IAAI,GAAG,CAClD;EACF;EACA,MAAM,CAAC;GAAE;GAAM;EAAW,CAAC;CAC7B,EAAE;AACN;AAEA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,WAAW,iBAAiB,KAAK,MAAM,KAAK,OAAO;CACzD,MAAM,WAAW,eAAe,IAAI;CACpC,MAAM,cACJ,KAAK,MAAM,iBAAiB,KAAA,IACxB,IAAI,KAAK,KAAK,eAAe,MAC7B,KAAA;CAEN,gBACE,KACA;EACE,UAAU;GAAE,MAAM;GAAU,QAAQ,KAAK;EAAU;EACnD,GAAG,uBAAuB,QAAQ;EAClC,UAAU,yBAAyB,KAAK,MAAM;EAC9C,MAAM,KAAK,MAAM,QACb,eAAe,KAAK,KAAK,KAAK,IAC9B,cAAc;EAClB,SAAS,aAAa,QAAQ;EAC9B,SAAS,KAAK,OACV,EACE,MAAM;GACJ,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;GACtD,OAAO,aAAa,KAAK,KAAK,SAAS,QAAQ;EACjD,EACF,IACA,KAAA;EACJ,MAAM,KAAK,OACP,EACE,QAAQ,SACV,IACA,KAAA;EACJ,YAAY,qBAAqB,IAAI;CACvC,GACA,UACA;EACE,WAAW,KAAK,MAAM;EACtB;EACA,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,UAAU,UAAU;CACtB,CACF;AACF"}
1
+ {"version":3,"file":"shape.js","names":[],"sources":["../../../src/renderPptx/nodes/shape.ts"],"sourcesContent":["import {\n asEmu,\n asHundredthPt,\n type AddShapeParagraphInput,\n type AddShapeRunPropertiesInput,\n} from \"@pptx-glimpse/document\";\nimport type { BorderStyle, PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToPt } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n createGlimpseShapeRunProperties,\n toColorInput,\n} from \"../glimpseAdapter.ts\";\nimport {\n cardinalConnectorSites,\n supportsCardinalConnectorSites,\n} from \"../utils/connectorSites.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n createShapeRotationInput,\n noneShapeFill,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\n\ntype ShapePositionedNode = Extract<PositionedNode, { type: \"shape\" }>;\n\n/**\n * outline (Text と同じ書式の `outline.size` / `outline.color`) と\n * 既存 `line` 属性 (`line.color` / `line.width` / `line.dashType`) を\n * 1 つの BorderStyle にマージする。\n *\n * フィールド単位のマージで、`outline` の指定があるフィールドは `line` を\n * 上書きするが、`outline` 側で省略されたフィールドは `line` の値を引き継ぎ、\n * `line` にも値が無い場合は Text outline と同じ既定値 (`width: 1pt 相当` /\n * `color: FFFFFF`) を採用する。`dashType` は `outline` に対応フィールドが\n * 無いため `line.dashType` をそのまま使う。\n */\nfunction resolveShapeLine(\n line: BorderStyle | undefined,\n outline: { size?: number; color?: string } | undefined,\n): BorderStyle | undefined {\n if (!outline) return line;\n return {\n color: outline.color ?? line?.color ?? \"FFFFFF\",\n width: outline.size ?? line?.width ?? 1,\n dashType: line?.dashType,\n };\n}\n\nfunction buildShapeTextProperties(\n node: ShapePositionedNode,\n): AddShapeRunPropertiesInput {\n return createGlimpseShapeRunProperties({\n fontFace: node.fontFamily,\n fontSize: node.fontSize,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: node.underline,\n strike: node.strike,\n subscript: node.subscript,\n superscript: node.superscript,\n highlight: node.highlight,\n });\n}\n\nfunction buildShapeParagraphs(\n node: ShapePositionedNode,\n): AddShapeParagraphInput[] | undefined {\n if (!node.text) return undefined;\n const fontSizePx = node.fontSize ?? 24;\n const lineHeight = node.lineHeight ?? 1.3;\n const properties = buildShapeTextProperties(node);\n return node.text\n .replace(/\\r*\\n/g, \"\\n\")\n .split(\"\\n\")\n .map((text) => ({\n properties: {\n align: node.textAlign ?? \"center\",\n lineSpacing: asHundredthPt(\n Math.round(pxToPt(fontSizePx * lineHeight) * 100),\n ),\n },\n runs: [{ text, properties }],\n }));\n}\n\nexport function renderShapeNode(\n node: ShapePositionedNode,\n ctx: RenderContext,\n): void {\n const lineSpec = resolveShapeLine(node.line, node.outline);\n const boundsPx = getContentArea(node);\n const fillOpacity =\n node.fill?.transparency !== undefined\n ? 1 - node.fill.transparency / 100\n : undefined;\n\n const handle = addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: node.shapeType },\n ...createShapeBoundsInput(boundsPx),\n rotation: createShapeRotationInput(node.rotate),\n fill: node.fill?.color\n ? solidShapeFill(node.fill.color)\n : noneShapeFill(),\n outline: shapeOutline(lineSpec),\n effects: node.glow\n ? {\n glow: {\n radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),\n color: toColorInput(node.glow.color ?? \"FFFFFF\")!,\n },\n }\n : undefined,\n body: node.text\n ? {\n anchor: \"middle\",\n }\n : undefined,\n paragraphs: buildShapeParagraphs(node),\n },\n boundsPx,\n {\n fillColor: node.fill?.color,\n fillOpacity,\n glow: node.glow,\n shadow: node.shadow,\n dashType: lineSpec?.dashType,\n },\n );\n if (\n node.id &&\n ctx.idNodeMap.get(node.id) === node &&\n supportsCardinalConnectorSites(node.shapeType)\n ) {\n ctx.connectorTargetMap.set(node.id, {\n handle,\n bounds: boundsPx,\n sites: cardinalConnectorSites(boundsPx, node.rotate),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAyCA,SAAS,iBACP,MACA,SACyB;CACzB,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO;EACL,OAAO,QAAQ,SAAS,MAAM,SAAS;EACvC,OAAO,QAAQ,QAAQ,MAAM,SAAS;EACtC,UAAU,MAAM;CAClB;AACF;AAEA,SAAS,yBACP,MAC4B;CAC5B,OAAO,gCAAgC;EACrC,UAAU,KAAK;EACf,UAAU,KAAK;EACf,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,aAAa,KAAK;EAClB,WAAW,KAAK;CAClB,CAAC;AACH;AAEA,SAAS,qBACP,MACsC;CACtC,IAAI,CAAC,KAAK,MAAM,OAAO,KAAA;CACvB,MAAM,aAAa,KAAK,YAAY;CACpC,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,aAAa,yBAAyB,IAAI;CAChD,OAAO,KAAK,KACT,QAAQ,UAAU,IAAI,CAAC,CACvB,MAAM,IAAI,CAAC,CACX,KAAK,UAAU;EACd,YAAY;GACV,OAAO,KAAK,aAAa;GACzB,aAAa,cACX,KAAK,MAAM,OAAO,aAAa,UAAU,IAAI,GAAG,CAClD;EACF;EACA,MAAM,CAAC;GAAE;GAAM;EAAW,CAAC;CAC7B,EAAE;AACN;AAEA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,WAAW,iBAAiB,KAAK,MAAM,KAAK,OAAO;CACzD,MAAM,WAAW,eAAe,IAAI;CACpC,MAAM,cACJ,KAAK,MAAM,iBAAiB,KAAA,IACxB,IAAI,KAAK,KAAK,eAAe,MAC7B,KAAA;CAEN,MAAM,SAAS,gBACb,KACA;EACE,UAAU;GAAE,MAAM;GAAU,QAAQ,KAAK;EAAU;EACnD,GAAG,uBAAuB,QAAQ;EAClC,UAAU,yBAAyB,KAAK,MAAM;EAC9C,MAAM,KAAK,MAAM,QACb,eAAe,KAAK,KAAK,KAAK,IAC9B,cAAc;EAClB,SAAS,aAAa,QAAQ;EAC9B,SAAS,KAAK,OACV,EACE,MAAM;GACJ,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;GACtD,OAAO,aAAa,KAAK,KAAK,SAAS,QAAQ;EACjD,EACF,IACA,KAAA;EACJ,MAAM,KAAK,OACP,EACE,QAAQ,SACV,IACA,KAAA;EACJ,YAAY,qBAAqB,IAAI;CACvC,GACA,UACA;EACE,WAAW,KAAK,MAAM;EACtB;EACA,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,UAAU,UAAU;CACtB,CACF;CACA,IACE,KAAK,MACL,IAAI,UAAU,IAAI,KAAK,EAAE,MAAM,QAC/B,+BAA+B,KAAK,SAAS,GAE7C,IAAI,mBAAmB,IAAI,KAAK,IAAI;EAClC;EACA,QAAQ;EACR,OAAO,uBAAuB,UAAU,KAAK,MAAM;CACrD,CAAC;AAEL"}
@@ -1,9 +1,9 @@
1
- import { pxToEmu, pxToPt } from "../units.js";
1
+ import { pxToEmu } from "../units.js";
2
2
  import { getContentArea } from "../utils/contentArea.js";
3
3
  import { resolveSubSup } from "../textOptions.js";
4
- import { cleanHex, toColorInput } from "../pptxAuthoring.js";
4
+ import { cleanHex, createGlimpseTableRunProperties } from "../glimpseAdapter.js";
5
5
  import { resolveColumnWidths, resolveRowHeights } from "../../shared/tableUtils.js";
6
- import { asEmu, asOoxmlPercent, asPt } from "@pptx-glimpse/document";
6
+ import { asEmu } from "@pptx-glimpse/document";
7
7
  //#region src/renderPptx/nodes/table.ts
8
8
  function renderTableNode(node, ctx) {
9
9
  const content = getContentArea(node);
@@ -13,7 +13,7 @@ function renderTableNode(node, ctx) {
13
13
  color: cleanHex(node.cellBorder.color) ?? "000000",
14
14
  dash: toTableDash(node.cellBorder.dashType)
15
15
  } : void 0;
16
- ctx.buildContext.pptxAuthoring.registerTable({
16
+ ctx.authoring.addTable({
17
17
  offsetX: asEmu(Math.round(pxToEmu(content.x))),
18
18
  offsetY: asEmu(Math.round(pxToEmu(content.y))),
19
19
  width: asEmu(Math.round(pxToEmu(Math.max(content.w, 1)))),
@@ -66,28 +66,19 @@ function buildTableRows(node, rowHeights, border) {
66
66
  }
67
67
  function buildTableRuns(cell) {
68
68
  return (cell.runs?.length ? cell.runs : [{ text: cell.text }]).flatMap((run) => {
69
- const underline = run.underline ?? cell.underline;
70
69
  const subSup = resolveSubSup(run, cell);
71
- const properties = {
72
- fontSize: asPt(pxToPt(run.fontSize ?? cell.fontSize ?? 18)),
70
+ const properties = createGlimpseTableRunProperties({
71
+ fontSize: run.fontSize ?? cell.fontSize ?? 18,
73
72
  fontFace: run.fontFamily ?? cell.fontFamily,
74
- color: cleanHex(run.color ?? cell.color),
73
+ color: run.color ?? cell.color,
75
74
  bold: run.bold ?? cell.bold,
76
75
  italic: run.italic ?? cell.italic,
77
- underline: typeof underline === "object" ? {
78
- style: underline.style,
79
- color: toColorInput(underline.color)
80
- } : Boolean(underline),
76
+ underline: run.underline ?? cell.underline,
81
77
  strike: run.strike ?? cell.strike,
82
- baseline: subSup.subscript ? {
83
- type: "percent",
84
- value: asOoxmlPercent(-4e4)
85
- } : subSup.superscript ? {
86
- type: "percent",
87
- value: asOoxmlPercent(3e4)
88
- } : void 0,
89
- highlight: toColorInput(run.highlight ?? cell.highlight)
90
- };
78
+ subscript: subSup.subscript,
79
+ superscript: subSup.superscript,
80
+ highlight: run.highlight ?? cell.highlight
81
+ });
91
82
  return run.text.replace(/\r*\n/g, "\n").split("\n").map((line, index) => ({
92
83
  text: index === 0 ? line : `\n${line}`,
93
84
  properties,
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","names":[],"sources":["../../../src/renderPptx/nodes/table.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n resolveColumnWidths,\n resolveRowHeights,\n} from \"../../shared/tableUtils.ts\";\nimport {\n asEmu,\n asOoxmlPercent,\n asPt,\n type AddTableCellInput,\n type AddTableRowInput,\n type AddTableRunInput,\n type SourceDashStyle,\n} from \"@pptx-glimpse/document\";\nimport { pxToEmu, pxToPt } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { cleanHex, toColorInput } from \"../pptxAuthoring.ts\";\nimport { resolveSubSup } from \"../textOptions.ts\";\n\ntype TablePositionedNode = Extract<PositionedNode, { type: \"table\" }>;\n\nexport function renderTableNode(\n node: TablePositionedNode,\n ctx: RenderContext,\n): void {\n const content = getContentArea(node);\n const rowHeights = resolveRowHeights(node);\n const border = node.cellBorder\n ? {\n width: asEmu(Math.round(pxToEmu(node.cellBorder.width ?? 1 / 0.75))),\n color: cleanHex(node.cellBorder.color) ?? \"000000\",\n dash: toTableDash(node.cellBorder.dashType),\n }\n : undefined;\n ctx.buildContext.pptxAuthoring.registerTable({\n offsetX: asEmu(Math.round(pxToEmu(content.x))),\n offsetY: asEmu(Math.round(pxToEmu(content.y))),\n width: asEmu(Math.round(pxToEmu(Math.max(content.w, 1)))),\n height: asEmu(Math.round(pxToEmu(Math.max(content.h, 1)))),\n columnWidths: resolveColumnWidths(node, content.w).map((width) =>\n asEmu(Math.round(pxToEmu(Math.max(width, 1)))),\n ),\n rows: buildTableRows(node, rowHeights, border),\n });\n}\n\nfunction buildTableRows(\n node: TablePositionedNode,\n rowHeights: number[],\n border:\n | {\n width: ReturnType<typeof asEmu>;\n color: string;\n dash: SourceDashStyle | undefined;\n }\n | undefined,\n): AddTableRowInput[] {\n const columnCount = node.columns.length;\n const continuationCells = new Set<string>();\n return node.rows.map((row, rowIndex) => {\n const cells: AddTableCellInput[] = Array.from({ length: columnCount });\n for (let columnIndex = 0; columnIndex < columnCount; columnIndex += 1) {\n if (continuationCells.has(`${rowIndex}:${columnIndex}`)) {\n cells[columnIndex] = {};\n }\n }\n\n let columnIndex = 0;\n for (const cell of row.cells) {\n while (cells[columnIndex] !== undefined) columnIndex += 1;\n cells[columnIndex] = {\n runs: buildTableRuns(cell),\n fill: cleanHex(cell.backgroundColor),\n align: cell.textAlign ?? \"left\",\n marginLeft: asEmu(0),\n marginRight: asEmu(0),\n marginTop: asEmu(0),\n marginBottom: asEmu(0),\n borders: border\n ? { top: border, right: border, bottom: border, left: border }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n };\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n for (let y = rowIndex; y < rowIndex + rowspan; y += 1) {\n for (let x = columnIndex; x < columnIndex + colspan; x += 1) {\n if (x === columnIndex && y === rowIndex) continue;\n continuationCells.add(`${y}:${x}`);\n if (y === rowIndex) cells[x] = {};\n }\n }\n columnIndex += colspan;\n }\n\n for (let index = 0; index < cells.length; index += 1) {\n if (cells[index] === undefined) cells[index] = {};\n }\n return {\n height: asEmu(\n Math.round(pxToEmu(Math.max(rowHeights[rowIndex] ?? 0, 1))),\n ),\n cells,\n };\n });\n}\n\nfunction buildTableRuns(\n cell: TablePositionedNode[\"rows\"][number][\"cells\"][number],\n): AddTableRunInput[] {\n const runs = cell.runs?.length ? cell.runs : [{ text: cell.text }];\n return runs.flatMap((run) => {\n const underline = run.underline ?? cell.underline;\n const subSup = resolveSubSup(run, cell);\n const properties = {\n fontSize: asPt(pxToPt(run.fontSize ?? cell.fontSize ?? 18)),\n fontFace: run.fontFamily ?? cell.fontFamily,\n color: cleanHex(run.color ?? cell.color),\n bold: run.bold ?? cell.bold,\n italic: run.italic ?? cell.italic,\n underline:\n typeof underline === \"object\"\n ? {\n style: underline.style,\n color: toColorInput(underline.color),\n }\n : Boolean(underline),\n strike: run.strike ?? cell.strike,\n baseline: subSup.subscript\n ? { type: \"percent\" as const, value: asOoxmlPercent(-40000) }\n : subSup.superscript\n ? { type: \"percent\" as const, value: asOoxmlPercent(30000) }\n : undefined,\n highlight: toColorInput(run.highlight ?? cell.highlight),\n };\n const lines = run.text.replace(/\\r*\\n/g, \"\\n\").split(\"\\n\");\n return lines.map((line, index) => ({\n text: index === 0 ? line : `\\n${line}`,\n properties,\n hyperlink: run.href,\n }));\n });\n}\n\nfunction toTableDash(\n dash: NonNullable<TablePositionedNode[\"cellBorder\"]>[\"dashType\"],\n): SourceDashStyle | undefined {\n return dash;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"table.js","names":[],"sources":["../../../src/renderPptx/nodes/table.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n resolveColumnWidths,\n resolveRowHeights,\n} from \"../../shared/tableUtils.ts\";\nimport {\n asEmu,\n type AddTableCellInput,\n type AddTableRowInput,\n type AddTableRunInput,\n type SourceDashStyle,\n} from \"@pptx-glimpse/document\";\nimport { pxToEmu } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport {\n cleanHex,\n createGlimpseTableRunProperties,\n} from \"../glimpseAdapter.ts\";\nimport { resolveSubSup } from \"../textOptions.ts\";\n\ntype TablePositionedNode = Extract<PositionedNode, { type: \"table\" }>;\n\nexport function renderTableNode(\n node: TablePositionedNode,\n ctx: RenderContext,\n): void {\n const content = getContentArea(node);\n const rowHeights = resolveRowHeights(node);\n const border = node.cellBorder\n ? {\n width: asEmu(Math.round(pxToEmu(node.cellBorder.width ?? 1 / 0.75))),\n color: cleanHex(node.cellBorder.color) ?? \"000000\",\n dash: toTableDash(node.cellBorder.dashType),\n }\n : undefined;\n ctx.authoring.addTable({\n offsetX: asEmu(Math.round(pxToEmu(content.x))),\n offsetY: asEmu(Math.round(pxToEmu(content.y))),\n width: asEmu(Math.round(pxToEmu(Math.max(content.w, 1)))),\n height: asEmu(Math.round(pxToEmu(Math.max(content.h, 1)))),\n columnWidths: resolveColumnWidths(node, content.w).map((width) =>\n asEmu(Math.round(pxToEmu(Math.max(width, 1)))),\n ),\n rows: buildTableRows(node, rowHeights, border),\n });\n}\n\nfunction buildTableRows(\n node: TablePositionedNode,\n rowHeights: number[],\n border:\n | {\n width: ReturnType<typeof asEmu>;\n color: string;\n dash: SourceDashStyle | undefined;\n }\n | undefined,\n): AddTableRowInput[] {\n const columnCount = node.columns.length;\n const continuationCells = new Set<string>();\n return node.rows.map((row, rowIndex) => {\n const cells: AddTableCellInput[] = Array.from({ length: columnCount });\n for (let columnIndex = 0; columnIndex < columnCount; columnIndex += 1) {\n if (continuationCells.has(`${rowIndex}:${columnIndex}`)) {\n cells[columnIndex] = {};\n }\n }\n\n let columnIndex = 0;\n for (const cell of row.cells) {\n while (cells[columnIndex] !== undefined) columnIndex += 1;\n cells[columnIndex] = {\n runs: buildTableRuns(cell),\n fill: cleanHex(cell.backgroundColor),\n align: cell.textAlign ?? \"left\",\n marginLeft: asEmu(0),\n marginRight: asEmu(0),\n marginTop: asEmu(0),\n marginBottom: asEmu(0),\n borders: border\n ? { top: border, right: border, bottom: border, left: border }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n };\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n for (let y = rowIndex; y < rowIndex + rowspan; y += 1) {\n for (let x = columnIndex; x < columnIndex + colspan; x += 1) {\n if (x === columnIndex && y === rowIndex) continue;\n continuationCells.add(`${y}:${x}`);\n if (y === rowIndex) cells[x] = {};\n }\n }\n columnIndex += colspan;\n }\n\n for (let index = 0; index < cells.length; index += 1) {\n if (cells[index] === undefined) cells[index] = {};\n }\n return {\n height: asEmu(\n Math.round(pxToEmu(Math.max(rowHeights[rowIndex] ?? 0, 1))),\n ),\n cells,\n };\n });\n}\n\nfunction buildTableRuns(\n cell: TablePositionedNode[\"rows\"][number][\"cells\"][number],\n): AddTableRunInput[] {\n const runs = cell.runs?.length ? cell.runs : [{ text: cell.text }];\n return runs.flatMap((run) => {\n const subSup = resolveSubSup(run, cell);\n const properties = createGlimpseTableRunProperties({\n fontSize: run.fontSize ?? cell.fontSize ?? 18,\n fontFace: run.fontFamily ?? cell.fontFamily,\n color: run.color ?? cell.color,\n bold: run.bold ?? cell.bold,\n italic: run.italic ?? cell.italic,\n underline: run.underline ?? cell.underline,\n strike: run.strike ?? cell.strike,\n subscript: subSup.subscript,\n superscript: subSup.superscript,\n highlight: run.highlight ?? cell.highlight,\n });\n const lines = run.text.replace(/\\r*\\n/g, \"\\n\").split(\"\\n\");\n return lines.map((line, index) => ({\n text: index === 0 ? line : `\\n${line}`,\n properties,\n hyperlink: run.href,\n }));\n });\n}\n\nfunction toTableDash(\n dash: NonNullable<TablePositionedNode[\"cellBorder\"]>[\"dashType\"],\n): SourceDashStyle | undefined {\n return dash;\n}\n"],"mappings":"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"}
@@ -1,6 +1,21 @@
1
+ import { createTextNodeInput } from "../glimpseAdapter.js";
2
+ import { cardinalConnectorSites } from "../utils/connectorSites.js";
1
3
  //#region src/renderPptx/nodes/text.ts
2
4
  function renderTextNode(node, ctx) {
3
- ctx.buildContext.pptxAuthoring.register(node);
5
+ const handle = ctx.authoring.addTextBox(createTextNodeInput(node, ctx.authoring.useLayoutTextMargins));
6
+ if (node.id && ctx.idNodeMap.get(node.id) === node) {
7
+ const bounds = {
8
+ x: node.x,
9
+ y: node.y,
10
+ w: node.w,
11
+ h: node.h
12
+ };
13
+ ctx.connectorTargetMap.set(node.id, {
14
+ handle,
15
+ bounds,
16
+ sites: cardinalConnectorSites(bounds, node.rotate)
17
+ });
18
+ }
4
19
  }
5
20
  //#endregion
6
21
  export { renderTextNode };
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","names":[],"sources":["../../../src/renderPptx/nodes/text.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\n\ntype TextPositionedNode = Extract<PositionedNode, { type: \"text\" }>;\n\nexport function renderTextNode(\n node: TextPositionedNode,\n ctx: RenderContext,\n): void {\n ctx.buildContext.pptxAuthoring.register(node);\n}\n"],"mappings":";AAKA,SAAgB,eACd,MACA,KACM;CACN,IAAI,aAAa,cAAc,SAAS,IAAI;AAC9C"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../../../src/renderPptx/nodes/text.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { createTextNodeInput } from \"../glimpseAdapter.ts\";\nimport { cardinalConnectorSites } from \"../utils/connectorSites.ts\";\n\ntype TextPositionedNode = Extract<PositionedNode, { type: \"text\" }>;\n\nexport function renderTextNode(\n node: TextPositionedNode,\n ctx: RenderContext,\n): void {\n const handle = ctx.authoring.addTextBox(\n createTextNodeInput(node, ctx.authoring.useLayoutTextMargins),\n );\n if (node.id && ctx.idNodeMap.get(node.id) === node) {\n const bounds = { x: node.x, y: node.y, w: node.w, h: node.h };\n ctx.connectorTargetMap.set(node.id, {\n handle,\n bounds,\n sites: cardinalConnectorSites(bounds, node.rotate),\n });\n }\n}\n"],"mappings":";;;AAOA,SAAgB,eACd,MACA,KACM;CACN,MAAM,SAAS,IAAI,UAAU,WAC3B,oBAAoB,MAAM,IAAI,UAAU,oBAAoB,CAC9D;CACA,IAAI,KAAK,MAAM,IAAI,UAAU,IAAI,KAAK,EAAE,MAAM,MAAM;EAClD,MAAM,SAAS;GAAE,GAAG,KAAK;GAAG,GAAG,KAAK;GAAG,GAAG,KAAK;GAAG,GAAG,KAAK;EAAE;EAC5D,IAAI,mBAAmB,IAAI,KAAK,IAAI;GAClC;GACA;GACA,OAAO,uBAAuB,QAAQ,KAAK,MAAM;EACnD,CAAC;CACH;AACF"}