@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.
- package/dist/cli.js +1 -1
- package/dist/client/assets/{HomePage-CW9U2ufj.js → HomePage-9ryiIVJl.js} +22 -22
- package/dist/client/assets/HomePage-9ryiIVJl.js.map +1 -0
- package/dist/client/assets/{JsonEditorPage-B7Dvlxwb.js → JsonEditorPage-BO0AtnI3.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-B7Dvlxwb.js.map → JsonEditorPage-BO0AtnI3.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-DML1yjXU.js → MonacoPluginProvider-BE7Xjhup.js} +3 -3
- package/dist/client/assets/{MonacoPluginProvider-DML1yjXU.js.map → MonacoPluginProvider-BE7Xjhup.js.map} +1 -1
- package/dist/client/assets/{button-DIVbkn2f.js → button-DghEEchK.js} +2 -2
- package/dist/client/assets/{button-DIVbkn2f.js.map → button-DghEEchK.js.map} +1 -1
- package/dist/client/assets/{editor-CIPfAaib.js → editor-BxyYhgT1.js} +2 -2
- package/dist/client/assets/{editor-CIPfAaib.js.map → editor-BxyYhgT1.js.map} +1 -1
- package/dist/client/assets/{editor-monaco-json-Bjq1VFZK.js → editor-monaco-json-PlUCgtCX.js} +2 -2
- package/dist/client/assets/{editor-monaco-json-Bjq1VFZK.js.map → editor-monaco-json-PlUCgtCX.js.map} +1 -1
- package/dist/client/assets/{index-YMR5mZvu.js → index-DSzthtfQ.js} +3 -3
- package/dist/client/assets/{index-YMR5mZvu.js.map → index-DSzthtfQ.js.map} +1 -1
- package/dist/client/assets/{preview-BrYFbmhA.js → preview-BBQhSmsm.js} +2 -2
- package/dist/client/assets/{preview-BrYFbmhA.js.map → preview-BBQhSmsm.js.map} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/prompts/instructions-docx.md +46 -0
- package/dist/prompts/instructions-edit-document-docx.md +54 -0
- package/dist/prompts/instructions-edit-document-pptx-slides.md +40 -0
- package/dist/prompts/instructions-edit-document-pptx-templates.md +48 -0
- package/dist/prompts/instructions-edit-document-pptx.md +49 -0
- package/dist/prompts/instructions-edit-document.md +28 -0
- package/dist/prompts/instructions-edit-pptx.md +31 -0
- package/dist/prompts/instructions-edit.md +24 -0
- package/dist/prompts/instructions-generate-docx.md +10 -0
- package/dist/prompts/instructions-generate-pptx.md +24 -0
- package/dist/prompts/instructions-generate.md +21 -0
- package/dist/prompts/pptx-core.md +180 -0
- package/dist/prompts/pptx-design.md +209 -0
- package/dist/prompts/system-theme.md +28 -0
- package/dist/prompts/system.md +30 -0
- package/package.json +2 -2
- 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.
|