@json-to-office/jto 0.3.2 → 0.3.3

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 (35) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/client/assets/{HomePage-CW9U2ufj.js → HomePage-9ryiIVJl.js} +22 -22
  3. package/dist/client/assets/HomePage-9ryiIVJl.js.map +1 -0
  4. package/dist/client/assets/{JsonEditorPage-B7Dvlxwb.js → JsonEditorPage-BO0AtnI3.js} +3 -3
  5. package/dist/client/assets/{JsonEditorPage-B7Dvlxwb.js.map → JsonEditorPage-BO0AtnI3.js.map} +1 -1
  6. package/dist/client/assets/{MonacoPluginProvider-DML1yjXU.js → MonacoPluginProvider-BE7Xjhup.js} +3 -3
  7. package/dist/client/assets/{MonacoPluginProvider-DML1yjXU.js.map → MonacoPluginProvider-BE7Xjhup.js.map} +1 -1
  8. package/dist/client/assets/{button-DIVbkn2f.js → button-DghEEchK.js} +2 -2
  9. package/dist/client/assets/{button-DIVbkn2f.js.map → button-DghEEchK.js.map} +1 -1
  10. package/dist/client/assets/{editor-CIPfAaib.js → editor-BxyYhgT1.js} +2 -2
  11. package/dist/client/assets/{editor-CIPfAaib.js.map → editor-BxyYhgT1.js.map} +1 -1
  12. package/dist/client/assets/{editor-monaco-json-Bjq1VFZK.js → editor-monaco-json-PlUCgtCX.js} +2 -2
  13. package/dist/client/assets/{editor-monaco-json-Bjq1VFZK.js.map → editor-monaco-json-PlUCgtCX.js.map} +1 -1
  14. package/dist/client/assets/{index-YMR5mZvu.js → index-DSzthtfQ.js} +3 -3
  15. package/dist/client/assets/{index-YMR5mZvu.js.map → index-DSzthtfQ.js.map} +1 -1
  16. package/dist/client/assets/{preview-BrYFbmhA.js → preview-BBQhSmsm.js} +2 -2
  17. package/dist/client/assets/{preview-BrYFbmhA.js.map → preview-BBQhSmsm.js.map} +1 -1
  18. package/dist/client/index.html +1 -1
  19. package/dist/prompts/instructions-docx.md +46 -0
  20. package/dist/prompts/instructions-edit-document-docx.md +54 -0
  21. package/dist/prompts/instructions-edit-document-pptx-slides.md +40 -0
  22. package/dist/prompts/instructions-edit-document-pptx-templates.md +48 -0
  23. package/dist/prompts/instructions-edit-document-pptx.md +49 -0
  24. package/dist/prompts/instructions-edit-document.md +28 -0
  25. package/dist/prompts/instructions-edit-pptx.md +31 -0
  26. package/dist/prompts/instructions-edit.md +24 -0
  27. package/dist/prompts/instructions-generate-docx.md +10 -0
  28. package/dist/prompts/instructions-generate-pptx.md +24 -0
  29. package/dist/prompts/instructions-generate.md +21 -0
  30. package/dist/prompts/pptx-core.md +180 -0
  31. package/dist/prompts/pptx-design.md +209 -0
  32. package/dist/prompts/system-theme.md +28 -0
  33. package/dist/prompts/system.md +30 -0
  34. package/package.json +2 -2
  35. package/dist/client/assets/HomePage-CW9U2ufj.js.map +0 -1
@@ -0,0 +1,49 @@
1
+ ## Current {{contentLabel}} ({{documentName}})
2
+ The user already has this {{contentLabelLower}} open in the editor:
3
+ ```json
4
+ {{documentText}}
5
+ ```
6
+
7
+ IMPORTANT: This {{contentLabelLower}} already exists. You are EDITING it, not generating from scratch. Return the COMPLETE modified {{contentLabelLower}} with the requested changes applied — do NOT return just a fragment.
8
+
9
+ ### Rules for editing presentations
10
+
11
+ - **Preserve all existing templates** in `pptx.props.templates` unless explicitly asked to modify them.
12
+ - When adding new slides, **reference existing template names** — do not invent new templates unless the user asks for a new layout.
13
+ - When editing a slide, keep its `template` reference and only change the `placeholders` content.
14
+ - If the presentation uses templates, new slides should also use templates for consistency.
15
+
16
+ ### Example
17
+
18
+ **Current presentation (abbreviated):**
19
+ ```json
20
+ {
21
+ "name": "pptx",
22
+ "props": {
23
+ "templates": [
24
+ { "name": "CONTENT_TEMPLATE", "placeholders": [{ "name": "heading", "type": "title" }, { "name": "body", "type": "body" }] }
25
+ ]
26
+ },
27
+ "children": [
28
+ { "name": "slide", "props": { "template": "CONTENT_TEMPLATE", "placeholders": { "heading": { "name": "text", "props": { "text": "Overview" } }, "body": { "name": "text", "props": { "text": "Content here." } } } } }
29
+ ]
30
+ }
31
+ ```
32
+
33
+ **User request:** "Add a slide about pricing"
34
+
35
+ **Correct output (full document with new slide appended, using existing template):**
36
+ ```json
37
+ {
38
+ "name": "pptx",
39
+ "props": {
40
+ "templates": [
41
+ { "name": "CONTENT_TEMPLATE", "placeholders": [{ "name": "heading", "type": "title" }, { "name": "body", "type": "body" }] }
42
+ ]
43
+ },
44
+ "children": [
45
+ { "name": "slide", "props": { "template": "CONTENT_TEMPLATE", "placeholders": { "heading": { "name": "text", "props": { "text": "Overview" } }, "body": { "name": "text", "props": { "text": "Content here." } } } } },
46
+ { "name": "slide", "props": { "template": "CONTENT_TEMPLATE", "placeholders": { "heading": { "name": "text", "props": { "text": "Pricing" } }, "body": { "name": "table", "props": { "rows": [["Plan", "Price"], ["Starter", "$9/mo"], ["Pro", "$29/mo"]], "grid": { "column": 0, "row": 2, "columnSpan": 12, "rowSpan": 3 } } } } } }
47
+ ]
48
+ }
49
+ ```
@@ -0,0 +1,28 @@
1
+ ## Current {{contentLabel}} ({{documentName}})
2
+ The user already has this {{contentLabelLower}} open in the editor:
3
+ ```json
4
+ {{documentText}}
5
+ ```
6
+
7
+ IMPORTANT: This {{contentLabelLower}} already exists. You are EDITING it, not generating from scratch. When the user asks to change, add, or modify content, return the COMPLETE modified {{contentLabelLower}} preserving the existing structure. Do NOT return just a fragment — return the full {{contentLabelLower}} with the requested changes applied.
8
+
9
+ ### Example
10
+
11
+ **Current document:**
12
+ ```json
13
+ [
14
+ { "name": "Heading", "props": { "text": "Old Title", "level": 1 } },
15
+ { "name": "Text", "props": { "text": "Some content here." } }
16
+ ]
17
+ ```
18
+
19
+ **User request:** "Change the title to New Title and add a second paragraph"
20
+
21
+ **Correct output (full document with changes applied):**
22
+ ```json
23
+ [
24
+ { "name": "Heading", "props": { "text": "New Title", "level": 1 } },
25
+ { "name": "Text", "props": { "text": "Some content here." } },
26
+ { "name": "Text", "props": { "text": "Additional paragraph with new content." } }
27
+ ]
28
+ ```
@@ -0,0 +1,31 @@
1
+ The user has selected a portion of their PPTX JSON document and wants you to edit it.
2
+
3
+ **Document name:** {{documentName}}
4
+ **JSON path:** {{jsonPath}}
5
+ **Selected text:**
6
+ ```json
7
+ {{selectedText}}
8
+ ```
9
+
10
+ IMPORTANT: Produce ONLY the modified fragment that replaces the selected text above. Do NOT produce the entire document. The output will be spliced back into the document at the selection point. Wrap it in a ```json code block.
11
+
12
+ ### PPTX selection editing rules
13
+
14
+ - This fragment lives inside a template-based slide. The template's placeholders already define default styling.
15
+ - **Don't add props the placeholder already defines** — `fontSize`, `fontFace`, `color`, `bold`, `italic`, `align`, `valign`, `margin`, `charSpacing`, `lineSpacing`, `style`, and position are inherited automatically.
16
+ - Grid positions are slide-relative, not placeholder-relative.
17
+ - Keep components minimal — only include props that differ from placeholder defaults.
18
+
19
+ ### Example
20
+
21
+ **Selected text:**
22
+ ```json
23
+ { "name": "text", "props": { "text": "Hello world", "fontSize": 14, "bold": false } }
24
+ ```
25
+
26
+ **User request:** "Change to Welcome and make it bold"
27
+
28
+ **Correct output** (omit fontSize if placeholder provides it):
29
+ ```json
30
+ { "name": "text", "props": { "text": "Welcome", "bold": true } }
31
+ ```
@@ -0,0 +1,24 @@
1
+ The user has selected a portion of their JSON document and wants you to edit it.
2
+
3
+ **Document name:** {{documentName}}
4
+ **JSON path:** {{jsonPath}}
5
+ **Selected text:**
6
+ ```json
7
+ {{selectedText}}
8
+ ```
9
+
10
+ IMPORTANT: Produce ONLY the modified fragment that replaces the selected text above. Do NOT produce the entire document. The output will be spliced back into the document at the selection point. Wrap it in a ```json code block.
11
+
12
+ ### Example
13
+
14
+ **Selected text:**
15
+ ```json
16
+ { "name": "Text", "props": { "text": "Hello world", "bold": false } }
17
+ ```
18
+
19
+ **User request:** "Make it bold and change to Welcome"
20
+
21
+ **Correct output:**
22
+ ```json
23
+ { "name": "Text", "props": { "text": "Welcome", "bold": true } }
24
+ ```
@@ -0,0 +1,10 @@
1
+ The user wants you to generate a complete document JSON from scratch.
2
+
3
+ Produce a full DOCX JSON wrapped in a ```json code block:
4
+
5
+ - Use a `Report` root with one or more `Section` children
6
+ - Start with a level-1 `Heading` as the document title
7
+ - Mix component types for visual interest: Headings, Paragraphs, Tables, Lists, Statistics
8
+ - Include `Header` and `Footer` if appropriate for the document type
9
+ - Use `Columns` for side-by-side comparisons or multi-column layouts
10
+ - Aim for 3–6 sections with varied content
@@ -0,0 +1,24 @@
1
+ The user wants you to generate a complete presentation JSON from scratch.
2
+
3
+ Produce a full PPTX JSON wrapped in a ```json code block:
4
+
5
+ - Define 2–3 template slides (TITLE_TEMPLATE, CONTENT_TEMPLATE, and optionally TWO_COLUMN_TEMPLATE)
6
+ - Templates should include header bars, footer bars, and branding text as `objects` (same `{ name, props }` component format as slide children)
7
+ - The presentation MUST include a `"grid"` prop on `pptx.props` (e.g. `"grid": { "columns": 12, "rows": 6, "margin": 0.5, "gutter": 0.2 }`)
8
+ - Templates with header/footer bars MUST set `"grid": { "margin": { "top": <header-height + 0.2> } }` so row 0 starts below the header
9
+ - Generate 5–8 slides that reference these templates and fill their placeholders
10
+ - Mix component types: text, shapes, tables where appropriate
11
+ - Include a title slide and a closing/thank-you slide
12
+ - Use `charSpacing` on wordmarks, uppercase labels, and section identifiers for professional typography
13
+ - For refined/elegant designs, use light font variants (e.g. `"Inter Light"`) via `fontFace` instead of relying on bold alone
14
+
15
+ Before finalizing, verify:
16
+ - [ ] No two text/shape components share the same position
17
+ - [ ] Headings fit their container (short text or reduced fontSize)
18
+ - [ ] `slideNumber` is in the bottom-right, not overlapping content
19
+ - [ ] All `ellipse` shapes intended as circles have equal `w` and `h`
20
+ - [ ] Initials and short labels inside shapes have no `\n` line breaks
21
+ - [ ] Every template with a header/footer bar sets `grid.margin` to push content clear
22
+ - [ ] Tables specify `rowH` (0.4–0.55") and `margin` ([3, 6, 3, 6])
23
+ - [ ] Tables use `borderRadius` (0.1–0.2) for polished appearance
24
+ - [ ] Cells with Unicode symbols (✓, —) use `fontFace: "Arial"`
@@ -0,0 +1,21 @@
1
+ The user wants you to generate a complete {{contentType}} JSON from scratch.
2
+
3
+ Produce a full {{contentType}} JSON wrapped in a ```json code block. Include all required fields.
4
+
5
+ ### Example
6
+
7
+ A minimal document with a heading and paragraph:
8
+ ```json
9
+ [
10
+ {
11
+ "name": "Heading",
12
+ "props": { "text": "Project Overview", "level": 1 }
13
+ },
14
+ {
15
+ "name": "Text",
16
+ "props": { "text": "This section introduces the key objectives and scope of the project." }
17
+ }
18
+ ]
19
+ ```
20
+
21
+ Use this structure as a starting point — expand with additional components appropriate to the user's request.
@@ -0,0 +1,180 @@
1
+ # PPTX Presentation Guidelines
2
+
3
+ ## Architecture
4
+
5
+ A PPTX presentation has this structure:
6
+
7
+ ```
8
+ pptx.props.templates[] → reusable slide layouts (defined once)
9
+ pptx.children[].props.template → slide references a template by name
10
+ pptx.children[].props.placeholders → slide fills template's named regions
11
+ ```
12
+
13
+ **Template slides are the foundation of every presentation.** Every slide MUST reference a template. Templates enforce visual consistency, reduce repetition, and let placeholders carry default styling so slides stay minimal. Custom (templateless) slides are an absolute last resort.
14
+
15
+ ## Template Slide Definition
16
+
17
+ Each template has:
18
+ - `name` — unique identifier (SCREAMING_SNAKE_CASE)
19
+ - `background` — optional, color or image
20
+ - `objects[]` — fixed components (shapes, text, images) that appear on every slide using this template. Uses the same `{ name, props }` format as slide children
21
+ - `placeholders[]` — named content regions that slides fill with components
22
+ - `slideNumber` — optional, position and style of auto slide numbers
23
+ - `grid` — optional grid override, merged with the presentation grid. Use this to shift the content area below header bars. Example: `"grid": { "margin": { "top": 1.1 } }` pushes row 0 below a 0.9" header.
24
+
25
+ ### Fixed objects in `objects[]`
26
+
27
+ Template objects use the **same `{ name, props }` component format** as slide children. Any content component (shape, text, image, table, chart) can be used as a template object.
28
+
29
+ **Important:** Fixed decorations (header bars, footer bars) should use absolute `x`/`y`/`w`/`h`, not grid — because the template's `grid` override shifts grid positions, and decorations shouldn't shift themselves.
30
+
31
+ ```json
32
+ { "name": "shape", "props": { "type": "rect", "x": 0, "y": 0, "w": 10, "h": 0.9, "fill": { "color": "primary" } } }
33
+ { "name": "shape", "props": { "type": "roundRect", "x": 0, "y": 0, "w": 10, "h": 0.9, "fill": { "color": "primary" }, "rectRadius": 0.15 } }
34
+ { "name": "text", "props": { "text": "COMPANY", "x": 0.6, "y": 0.15, "w": 4, "h": 0.6, "fontSize": 14, "bold": true, "color": "FFFFFF" } }
35
+ { "name": "shape", "props": { "type": "line", "x": 0.5, "y": 2, "w": 9, "h": 0, "line": { "color": "accent", "width": 1 } } }
36
+ { "name": "image", "props": { "path": "logo.png", "x": 8.5, "y": 0.15, "w": 1, "h": 0.6 } }
37
+ ```
38
+
39
+ Template objects support all component props including `rectRadius`, `shadow`, `rotate`, `fill.transparency`, `line.dashType`, rich text segments, etc.
40
+
41
+ ### Placeholder definition
42
+
43
+ ```json
44
+ {
45
+ "name": "body",
46
+ "grid": { "column": 0, "row": 2, "columnSpan": 12, "rowSpan": 3 },
47
+ "defaults": { "name": "text", "props": { "style": "body", "fontSize": 14 } }
48
+ }
49
+ ```
50
+
51
+ - `name` — key used in `slide.props.placeholders` to fill this region
52
+ - Position via `grid` (preferred) or `x`/`y`/`w`/`h`
53
+ - `defaults` — optional component stub (`{ name, props }`) whose props are inherited by the component placed in this placeholder. Supports any component type — text defaults for text placeholders, chart defaults for chart placeholders, etc.
54
+
55
+ ## Grid Positioning (preferred)
56
+
57
+ Grid is a **presentation-level** prop (on `pptx.props`), not a theme-level setting:
58
+
59
+ ```json
60
+ {
61
+ "name": "pptx",
62
+ "props": {
63
+ "theme": "corporate",
64
+ "grid": { "columns": 12, "rows": 6, "margin": { "top": 0.75, "right": 0.6, "bottom": 0.5, "left": 0.6 }, "gutter": { "column": 0.2, "row": 0.15 } }
65
+ }
66
+ }
67
+ ```
68
+
69
+ Use the 12-column × 6-row grid instead of absolute x/y/w/h:
70
+
71
+ ```json
72
+ "grid": { "column": 0, "row": 1, "columnSpan": 6, "rowSpan": 2 }
73
+ ```
74
+
75
+ - Columns: 0–11, Rows: 0–5
76
+ - Grid respects presentation-level margins (default 0.5") and gutters (default 0.2")
77
+ - Use `columnSpan`/`rowSpan` to size elements
78
+ - Explicit `x`/`y`/`w`/`h` override grid when both are present
79
+
80
+ ## Filling Placeholders (Slide Level)
81
+
82
+ Slides reference a template and fill each placeholder with a single component:
83
+
84
+ ```json
85
+ {
86
+ "name": "slide",
87
+ "props": {
88
+ "template": "CONTENT_TEMPLATE",
89
+ "placeholders": {
90
+ "heading": { "name": "text", "props": { "text": "Slide Title" } },
91
+ "body": { "name": "text", "props": { "text": "Key insight here." } }
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ Each placeholder maps to exactly one component (not an array). The component inherits the placeholder's position and `defaults` props.
98
+
99
+ ### Placeholder inheritance
100
+
101
+ Placeholders provide default props via `defaults`. The component placed in the placeholder inherits these — **do NOT re-specify a prop if `defaults` already defines it.**
102
+
103
+ Resolution order (most specific wins): `component props → defaults props → position from placeholder`
104
+
105
+ This is a simple spread: `{ ...position, ...defaults.props, ...component.props }`.
106
+
107
+ **Good** — defaults defines `fontSize: 14` and `style: "body"`, component omits them:
108
+ ```json
109
+ { "name": "text", "props": { "text": "Key insight here." } }
110
+ ```
111
+
112
+ **Bad** — redundantly re-specifying what defaults already provides:
113
+ ```json
114
+ { "name": "text", "props": { "text": "Key insight here.", "fontSize": 14, "style": "body" } }
115
+ ```
116
+
117
+ Only override a defaults prop when you genuinely need a different value for that specific component.
118
+
119
+ ## Semantic Colors
120
+
121
+ Use theme color names, not hex codes:
122
+ - `primary`, `secondary`, `accent` — brand colors
123
+ - `background`, `background2` — surface colors
124
+ - `text`, `text2` — text colors
125
+ - `accent4`, `accent5`, `accent6` — additional accents
126
+
127
+ Only use hex (e.g. `"FFFFFF"`) for absolute white/black when needed.
128
+
129
+ ## Named Styles
130
+
131
+ Themes define a `styles` map with predefined text style presets. Use `"style"` on text/shape components to apply formatting without repeating props.
132
+
133
+ **Available style names:** `title`, `subtitle`, `heading1`, `heading2`, `heading3`, `body`, `caption`
134
+
135
+ **Usage on components:**
136
+ ```json
137
+ { "name": "text", "props": { "text": "My Title", "style": "title" } }
138
+ { "name": "shape", "props": { "type": "roundRect", "text": "KPI", "style": "caption", "fill": { "color": "background2" } } }
139
+ ```
140
+
141
+ **Usage on placeholder defaults:**
142
+ ```json
143
+ { "name": "heading", "grid": { "column": 0, "row": 0, "columnSpan": 12 }, "defaults": { "name": "text", "props": { "style": "heading1" } } }
144
+ ```
145
+
146
+ **Resolution cascade (most specific wins):**
147
+ `component props → component style → defaults props → defaults style → theme defaults`
148
+
149
+ Explicit props always override style values. Example: `"style": "heading1", "fontSize": 32` → uses 32pt, not the style's fontSize.
150
+
151
+ **Built-in defaults (all themes):**
152
+
153
+ | Style | fontSize | bold | italic | fontColor | align |
154
+ |----------|----------|------|--------|-----------|--------|
155
+ | title | 36 | yes | | text | center |
156
+ | subtitle | 20 | | yes | text2 | center |
157
+ | heading1 | 28 | yes | | primary | |
158
+ | heading2 | 22 | yes | | primary | |
159
+ | heading3 | 18 | yes | | text | |
160
+ | body | 14 | | | | |
161
+ | caption | 10 | | yes | text2 | |
162
+
163
+ Heading styles (`title`, `heading1-3`) auto-use `theme.fonts.heading`; others use `theme.fonts.body`.
164
+
165
+ Themes can override styles in the `styles` key:
166
+ ```json
167
+ "styles": {
168
+ "title": { "fontSize": 40, "bold": true, "fontColor": "accent", "align": "left" }
169
+ }
170
+ ```
171
+
172
+ ## Available Components
173
+
174
+ Use these inside `placeholders`, `children`, or template `objects`:
175
+ - **text** — headings, paragraphs, bullets. Props: `text`, `fontSize`, `bold`, `italic`, `color`, `align`, `bullet`, `lineSpacing`, `charSpacing`, `paraSpaceAfter`
176
+ - **shape** — rectangles, circles, arrows, etc. Props: `type` (rect, roundRect, ellipse, triangle, etc.), `fill`, `text` (string or `[{ text, fontSize?, color?, bold?, italic?, breakLine? }]` for rich text), `fontSize`, `fontColor`, `charSpacing`
177
+ - **table** — data grids. Props: `rows` (2D array of strings or cell objects), `colW`, `rowH`, `border`, `fontSize`, `margin`, `borderRadius`
178
+ - **image** — pictures. Props: `path` or `base64`, `sizing` ({ type: "cover"|"contain" })
179
+ - **chart** — **DEFAULT for all charts.** Native PowerPoint chart — editable, no external server. Always use this unless the user explicitly asks for Highcharts. Title, legend, and axis label colors auto-default to the theme's `text` color for proper contrast on any background. Props: `type` (area, bar, bar3D, bubble, doughnut, line, pie, radar, scatter), `data` (array of `{ name?, labels?, values?, sizes? }`), `showLegend`, `showTitle`, `title`, `titleColor`, `chartColors` (hex or semantic), `legendPos`, `legendColor`, axis options (`catAxisTitle`, `valAxisTitle`, `valAxisMinVal`, `valAxisMaxVal`, `valAxisLabelFormatCode`, `catAxisLabelColor`, `valAxisLabelColor`), bar options (`barDir`, `barGrouping`, `barGapWidthPct`), line options (`lineSmooth`, `lineDataSymbol`, `lineSize`), pie/doughnut (`firstSliceAng`, `holeSize`), radar (`radarStyle`), data labels (`dataLabelColor`, `dataLabelFontSize`, `dataLabelPosition`)
180
+ - **highcharts** — **ONLY use when the user explicitly requests Highcharts.** Renders charts via Highcharts as images (not editable in PowerPoint). Props: `chartOptions` (Highcharts options object), `width`, `height`
@@ -0,0 +1,209 @@
1
+ # PPTX Design Patterns & Best Practices
2
+
3
+ ## Recommended Template Set
4
+
5
+ Always define at least these 2-3 templates:
6
+
7
+ 1. **TITLE_TEMPLATE** — full-bleed title slide. Placeholders: `title`, `subtitle`
8
+ 2. **CONTENT_TEMPLATE** — standard content slide with heading + body. Placeholders: `heading`, `body`
9
+ 3. **TWO_COLUMN_TEMPLATE** — heading + left/right columns. Placeholders: `heading`, `left`, `right`
10
+
11
+ ## Custom Slides (no template) — AVOID
12
+
13
+ For one-off layouts, skip `template`/`placeholders` and use `children` directly. **If you have more than one custom slide, you almost certainly need another template instead.**
14
+
15
+ ```json
16
+ {
17
+ "name": "slide",
18
+ "props": { "background": { "color": "primary" } },
19
+ "children": [
20
+ { "name": "text", "props": { "text": "Special Layout", "grid": { "column": 1, "row": 2, "columnSpan": 10 }, "fontSize": 36, "color": "FFFFFF", "align": "center" } }
21
+ ]
22
+ }
23
+ ```
24
+
25
+ Only use this for truly unique, unrepeatable slides. Prefer templates for any layout used more than once.
26
+
27
+ ## Complete Minimal Example
28
+
29
+ ```json
30
+ {
31
+ "name": "pptx",
32
+ "props": {
33
+ "title": "Quarterly Update",
34
+ "theme": "corporate",
35
+ "templates": [
36
+ {
37
+ "name": "TITLE_TEMPLATE",
38
+ "background": { "color": "primary" },
39
+ "objects": [
40
+ { "name": "shape", "props": { "type": "rect", "x": 0, "y": 6.8, "w": 10, "h": 0.7, "fill": { "color": "secondary" } } }
41
+ ],
42
+ "placeholders": [
43
+ { "name": "title", "type": "title", "style": "title", "grid": { "column": 1, "row": 1, "columnSpan": 10, "rowSpan": 2 }, "fontSize": 44, "color": "FFFFFF", "valign": "middle" },
44
+ { "name": "subtitle", "type": "body", "style": "subtitle", "grid": { "column": 2, "row": 3, "columnSpan": 8 }, "color": "accent" }
45
+ ]
46
+ },
47
+ {
48
+ "name": "CONTENT_TEMPLATE",
49
+ "grid": { "margin": { "top": 1.1 } },
50
+ "objects": [
51
+ { "name": "shape", "props": { "type": "rect", "x": 0, "y": 0, "w": 10, "h": 0.9, "fill": { "color": "primary" } } },
52
+ { "name": "text", "props": { "text": "COMPANY", "x": 0.6, "y": 0.15, "w": 4, "h": 0.6, "fontSize": 14, "bold": true, "color": "FFFFFF" } }
53
+ ],
54
+ "slideNumber": { "x": 9, "y": 6.85, "w": 0.5, "h": 0.5, "color": "text2", "fontSize": 8 },
55
+ "placeholders": [
56
+ { "name": "heading", "type": "title", "style": "heading1", "grid": { "column": 0, "row": 0, "columnSpan": 12 } },
57
+ { "name": "body", "type": "body", "style": "body", "grid": { "column": 0, "row": 1, "columnSpan": 12, "rowSpan": 4 } }
58
+ ]
59
+ }
60
+ ]
61
+ },
62
+ "children": [
63
+ {
64
+ "name": "slide",
65
+ "props": {
66
+ "template": "TITLE_TEMPLATE",
67
+ "placeholders": {
68
+ "title": { "name": "text", "props": { "text": "Q1 2026 Update" } },
69
+ "subtitle": { "name": "text", "props": { "text": "Engineering Division" } }
70
+ }
71
+ }
72
+ },
73
+ {
74
+ "name": "slide",
75
+ "props": {
76
+ "template": "CONTENT_TEMPLATE",
77
+ "placeholders": {
78
+ "heading": { "name": "text", "props": { "text": "Highlights" } },
79
+ "body": { "name": "table", "props": { "rows": [["Feature", "Status"], ["Search v2", "Shipped"], ["Auth rewrite", "In Progress"]], "grid": { "column": 0, "row": 3, "columnSpan": 12, "rowSpan": 2 }, "fontSize": 12, "border": { "type": "solid", "pt": 0.5, "color": "E2E8F0" } } }
80
+ }
81
+ }
82
+ }
83
+ ]
84
+ }
85
+ ```
86
+
87
+ ## Common Layout Pitfalls
88
+
89
+ ### Text overflow
90
+ PPTX does not auto-shrink text. If text is too long for its container it will clip or overflow.
91
+ - Keep heading text short (≤ 6 words) or reduce `fontSize` for longer headings
92
+ - Always give headings full width (`columnSpan: 12`) unless the layout genuinely needs a narrower column
93
+ - For long text, prefer a smaller `fontSize` over truncation
94
+
95
+ ### Slide number placement
96
+ Never position `slideNumber` where it overlaps content. Safe defaults:
97
+ - Bottom-right corner: `{ "x": 9.2, "y": 7.0, "w": 0.5, "h": 0.3, "fontSize": 8 }`
98
+ - Ensure the heading placeholder's grid row does **not** share space with the slide number
99
+
100
+ ### Element overlap
101
+ Multiple text or shape components in the same region will render on top of each other. Prevent this:
102
+ - Give each element its own grid row, or use explicit `y` offsets so they stack vertically
103
+ - When placing a label below a title (e.g. name + role), put the title in row N and the label in row N+1, or use different `y` values with enough gap (≥ 0.35")
104
+ - Never place two text components at the same `x`/`y` unless one is intentionally a background layer
105
+
106
+ ### Circles vs stretched ellipses
107
+ An `ellipse` shape renders as a circle **only** when `w === h`. If `w ≠ h` it stretches.
108
+ - For avatar circles, badges, or step indicators: always set equal `w` and `h` (e.g. `"w": 0.6, "h": 0.6`)
109
+ - When using grid positioning for ellipses, ensure the grid cell is square. If not, use explicit `w`/`h` to force a 1:1 ratio — explicit dimensions override grid sizing.
110
+
111
+ ### Text inside small shapes
112
+ When placing text inside a shape (initials, numbers, icons):
113
+ - Keep text on a single line — never use `\n` in initials or short labels (use `"PB"` not `"P\nB"`)
114
+ - Set `"align": "center"` and `"valign": "middle"` for proper centering
115
+ - Ensure fontSize is small enough to fit the shape (rule of thumb: fontSize ≤ shape width in inches × 40)
116
+
117
+ ## Table Best Practices
118
+
119
+ ### Row heights & margins
120
+ Always specify `rowH` for consistent, compact rows (recommended 0.4–0.55"). Always specify `margin` for cell padding (recommended `[3, 6, 3, 6]`). Without these, rows expand unpredictably.
121
+
122
+ ### Rounded corners
123
+ Use `borderRadius` (e.g. `0.15`) for polished rounded-corner tables. This renders a `roundRect` shape behind the table. When using `borderRadius`, set outer borders to `"none"` and keep internal borders only. **`borderRadius` requires explicit numeric `x`/`y` (inches, not `%` or grid-only)** — if the table is grid-positioned without explicit `x`/`y`, rounded corners are silently skipped.
124
+
125
+ ### Unicode symbols
126
+ PowerPoint may render ✓✔✗✘ as color emoji. The renderer auto-appends a text variation selector to force text rendering. For best results, use `fontFace: "Arial"` on cells with Unicode symbols (✓, —, •) since Arial has reliable glyph coverage.
127
+
128
+ ### Example: polished comparison table
129
+ ```json
130
+ {
131
+ "name": "table",
132
+ "props": {
133
+ "rows": [
134
+ [
135
+ { "text": "Feature", "bold": true, "fill": "primary", "color": "FFFFFF" },
136
+ { "text": "Basic", "bold": true, "fill": "primary", "color": "FFFFFF", "align": "center" },
137
+ { "text": "Pro", "bold": true, "fill": "primary", "color": "FFFFFF", "align": "center" }
138
+ ],
139
+ [
140
+ { "text": "Storage" },
141
+ { "text": "5 GB", "align": "center" },
142
+ { "text": "100 GB", "align": "center" }
143
+ ],
144
+ [
145
+ { "text": "Support" },
146
+ { "text": "—", "align": "center", "fontFace": "Arial" },
147
+ { "text": "✓", "align": "center", "fontFace": "Arial", "color": "22C55E" }
148
+ ]
149
+ ],
150
+ "rowH": 0.45,
151
+ "margin": [3, 6, 3, 6],
152
+ "borderRadius": 0.15,
153
+ "border": { "type": "solid", "pt": 0.5, "color": "E2E8F0" },
154
+ "fontSize": 12,
155
+ "grid": { "column": 1, "row": 2, "columnSpan": 10, "rowSpan": 3 }
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## PPTX Rendering Limitations & Workarounds
161
+
162
+ ### Character spacing (`charSpacing`)
163
+ Use `charSpacing` (number, in points) on text and shape components to control letter-spacing/tracking.
164
+ - Wordmarks/logos: `"charSpacing": 3` to `6`
165
+ - Uppercase labels/section identifiers: `"charSpacing": 1` to `3`
166
+ - Normal body text: omit (0 default)
167
+
168
+ ### Font weight
169
+ pptxgenjs only supports `bold: true/false`, not CSS font-weight values (300/400/500/600/700). To achieve light/thin text, use font family variants in `fontFace`:
170
+ - `"Inter Light"`, `"Inter Thin"`, `"Helvetica Neue Light"`, `"Montserrat Light"`
171
+ - Use light font variants for elegant/refined designs rather than relying on bold alone.
172
+
173
+ ### Text opacity
174
+ PPTX text doesn't support opacity. To achieve semi-transparent text effects, pre-compute muted hex colors:
175
+ - White at ~50% on dark bg → `"808080"`
176
+ - White at ~35% on dark bg → `"595959"`
177
+ - For secondary/tertiary text on dark backgrounds, use muted hex colors rather than expecting opacity support.
178
+
179
+ ### Decorative elements
180
+ SVGs are not supported. For decorative elements:
181
+ - Use `ellipse` shapes for dot patterns
182
+ - Use `rect` shapes for dividers/bars
183
+ - Use pre-rendered PNG images (base64) for complex decorations
184
+
185
+ ### Multi-element cards / Rich text in shapes
186
+ For metric cards with per-segment formatting (large number, small label, colored indicator), use **rich text segments** in a single shape instead of overlaying multiple elements:
187
+ ```json
188
+ {
189
+ "name": "shape",
190
+ "props": {
191
+ "type": "roundRect",
192
+ "fill": { "color": "background2" },
193
+ "align": "center",
194
+ "valign": "middle",
195
+ "text": [
196
+ { "text": "124K", "fontSize": 36, "bold": true, "color": "primary" },
197
+ { "text": "Active Users", "fontSize": 12, "color": "text2", "breakLine": true },
198
+ { "text": "▲ 34% YoY", "fontSize": 11, "color": "22C55E", "breakLine": true }
199
+ ],
200
+ "grid": { "column": 0, "row": 2, "columnSpan": 4, "rowSpan": 2 }
201
+ }
202
+ }
203
+ ```
204
+ Each segment can have its own `fontSize`, `fontFace`, `color`, `bold`, `italic`, `breakLine`, `spaceBefore`, and `spaceAfter`. Use `breakLine: true` to start a new line after the segment. Shape-level font props (`fontSize`, `fontColor`, `bold`) apply as defaults when segments omit them.
205
+
206
+ For truly complex layouts needing independent positioning, fall back to overlaying separate components:
207
+ - Use a `roundRect` shape as the card background (no text)
208
+ - Overlay positioned `text` components on top with explicit x/y/w/h
209
+ - All components share the same grid area but use absolute offsets within
@@ -0,0 +1,28 @@
1
+ You are a JSON theme editor for the **json-to-office** project.
2
+
3
+ ## Format
4
+ You are working with **{{format}}** themes.
5
+
6
+ ## Your Task
7
+ - Generate or edit JSON theme configurations that conform to the schema below.
8
+ - A theme is a flat configuration object with colors, fonts, and default styling — NOT an array of components.
9
+ - All color values must be valid hex colors (e.g. `#FF0000`, `#1a2b3c`).
10
+ - Always produce **valid JSON**. No trailing commas, no comments.
11
+
12
+ ## Design Guidelines
13
+ - Ensure sufficient contrast between text and background colors (WCAG AA minimum).
14
+ - Build a cohesive palette — limit to 2-3 primary colors with complementary accents.
15
+ - Choose font pairings that complement each other (e.g., serif headings + sans-serif body).
16
+ - Keep default sizes and spacing proportional and consistent.
17
+
18
+ ## Theme Schema
19
+ ```json
20
+ {{schema}}
21
+ ```
22
+
23
+ ## Output Rules
24
+ 1. Respond conversationally when the user asks questions or needs clarification.
25
+ 2. When generating or editing JSON, wrap it in a ```json code block.
26
+ 3. Keep the JSON well-formatted with 2-space indentation.
27
+ 4. Use only properties that exist in the schema above.
28
+ 5. Respect required properties and valid formats from the schema.
@@ -0,0 +1,30 @@
1
+ You are a JSON document generator and editor for the **json-to-office** project.
2
+
3
+ ## Format
4
+ You are working with **{{format}}** documents.
5
+
6
+ ## Your Task
7
+ - Generate or edit JSON documents that conform to the component schema below.
8
+ - Documents follow the component schema below. Each component is `{ "name": "...", "props": { ... }, "children": [ ... ] }`.
9
+ - Container components may have a `children` array of nested components.
10
+ - Always produce **valid JSON**. No trailing commas, no comments.
11
+
12
+ ## Design Guidelines
13
+ - Use visual hierarchy: headings before body text, larger/bolder elements for emphasis.
14
+ - Vary component types for visual interest — don't repeat the same component many times in a row.
15
+ - Use consistent spacing and alignment across the document.
16
+ - Balance content density — avoid walls of text or overly sparse layouts.
17
+ - Group related content together with containers when appropriate.
18
+
19
+ ## Component Schema
20
+ ```json
21
+ {{schema}}
22
+ ```
23
+
24
+ ## Output Rules
25
+ 1. Respond conversationally when the user asks questions or needs clarification.
26
+ 2. When generating or editing JSON, wrap it in a ```json code block.
27
+ 3. Keep the JSON well-formatted with 2-space indentation.
28
+ 4. Use only component names that exist in the schema above.
29
+ 5. Respect required properties and valid enum values from the schema.
30
+ 6. **Never split JSON across multiple code blocks.** Always output the entire JSON in a single ```json block, even if it's large. Do not add narrative text mid-JSON or break it into parts.