@ohos-ports/slides-grab 1.5.0-beta.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README-ko.md +292 -0
  3. package/README.md +301 -0
  4. package/bin/ohos-postinstall.cjs +118 -0
  5. package/bin/ppt-agent.js +620 -0
  6. package/convert.cjs +20 -0
  7. package/native/@img/sharp-libvips-openharmony-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
  8. package/native/@img/sharp-libvips-openharmony-arm64/lib/index.js +1 -0
  9. package/native/@img/sharp-libvips-openharmony-arm64/lib/libexpat.so +0 -0
  10. package/native/@img/sharp-libvips-openharmony-arm64/lib/libffi.so +0 -0
  11. package/native/@img/sharp-libvips-openharmony-arm64/lib/libjpeg.so +0 -0
  12. package/native/@img/sharp-libvips-openharmony-arm64/lib/libpcre2-8.so.0 +0 -0
  13. package/native/@img/sharp-libvips-openharmony-arm64/lib/libvips-cpp.so.42.20.3 +0 -0
  14. package/native/@img/sharp-libvips-openharmony-arm64/lib/libvips.so.42.20.3 +0 -0
  15. package/native/@img/sharp-libvips-openharmony-arm64/package.json +13 -0
  16. package/native/@img/sharp-openharmony-arm64/lib/sharp-openharmony-arm64.node +0 -0
  17. package/native/@img/sharp-openharmony-arm64/package.json +16 -0
  18. package/package.json +95 -0
  19. package/runtimes/claude-code/agents/design-critic-agent.md +23 -0
  20. package/runtimes/codex/agents/slides-grab-design-critic.md +22 -0
  21. package/scripts/build-viewer.js +444 -0
  22. package/scripts/design-gate.js +258 -0
  23. package/scripts/download-video.js +213 -0
  24. package/scripts/editor-server.js +1167 -0
  25. package/scripts/figma-export.js +169 -0
  26. package/scripts/generate-image.js +116 -0
  27. package/scripts/generate-images.js +164 -0
  28. package/scripts/html2pdf.js +822 -0
  29. package/scripts/html2png.js +246 -0
  30. package/scripts/html2pptx.js +162 -0
  31. package/scripts/import-template.js +86 -0
  32. package/scripts/install-runtime.js +216 -0
  33. package/scripts/render-tldraw.js +44 -0
  34. package/scripts/validate-slides.js +221 -0
  35. package/skills/slides-grab/SKILL.md +65 -0
  36. package/skills/slides-grab/references/presentation-workflow-reference.md +61 -0
  37. package/skills/slides-grab-card-news/SKILL.md +35 -0
  38. package/skills/slides-grab-design/SKILL.md +88 -0
  39. package/skills/slides-grab-design/references/beautiful-slide-defaults.md +88 -0
  40. package/skills/slides-grab-design/references/design-gate.md +349 -0
  41. package/skills/slides-grab-design/references/design-rules.md +76 -0
  42. package/skills/slides-grab-design/references/design-system-full.md +568 -0
  43. package/skills/slides-grab-design/references/detailed-design-rules.md +70 -0
  44. package/skills/slides-grab-export/SKILL.md +55 -0
  45. package/skills/slides-grab-export/references/export-rules.md +27 -0
  46. package/skills/slides-grab-export/references/html2pptx.md +627 -0
  47. package/skills/slides-grab-export/references/ooxml.md +427 -0
  48. package/skills/slides-grab-export/references/pptx-skill-reference.md +189 -0
  49. package/skills/slides-grab-html/SKILL.md +67 -0
  50. package/skills/slides-grab-image/SKILL.md +82 -0
  51. package/skills/slides-grab-plan/SKILL.md +68 -0
  52. package/skills/slides-grab-plan/references/design-md-to-slides-conversion.md +135 -0
  53. package/skills/slides-grab-plan/references/outline-format.md +47 -0
  54. package/skills/slides-grab-plan/references/plan-workflow-reference.md +140 -0
  55. package/src/codex-imagen.js +182 -0
  56. package/src/design-diversity-data.js +6932 -0
  57. package/src/design-gate-report.js +244 -0
  58. package/src/design-gate-state.js +329 -0
  59. package/src/design-import.js +164 -0
  60. package/src/design-md-parser.js +415 -0
  61. package/src/design-styles-data.js +1928 -0
  62. package/src/design-styles.js +209 -0
  63. package/src/editor/codex-edit.js +584 -0
  64. package/src/editor/edit-subprocess.js +170 -0
  65. package/src/editor/editor-codex-prompt.md +50 -0
  66. package/src/editor/editor.html +1785 -0
  67. package/src/editor/js/editor-bbox.js +332 -0
  68. package/src/editor/js/editor-chat.js +56 -0
  69. package/src/editor/js/editor-direct-edit.js +238 -0
  70. package/src/editor/js/editor-dom.js +59 -0
  71. package/src/editor/js/editor-init.js +405 -0
  72. package/src/editor/js/editor-navigation.js +54 -0
  73. package/src/editor/js/editor-select.js +558 -0
  74. package/src/editor/js/editor-send.js +175 -0
  75. package/src/editor/js/editor-sse.js +163 -0
  76. package/src/editor/js/editor-state.js +41 -0
  77. package/src/editor/js/editor-type.js +71 -0
  78. package/src/editor/js/editor-utils.js +167 -0
  79. package/src/editor/js/model-registry.js +37 -0
  80. package/src/editor/screenshot.js +82 -0
  81. package/src/export-resolution.cjs +68 -0
  82. package/src/figma.js +71 -0
  83. package/src/html2pptx-scale.cjs +120 -0
  84. package/src/html2pptx.cjs +1262 -0
  85. package/src/image-contract.js +329 -0
  86. package/src/image-native.js +468 -0
  87. package/src/nano-banana.js +841 -0
  88. package/src/ohos-browser-bridge.cjs +272 -0
  89. package/src/pptx-raster-export.cjs +299 -0
  90. package/src/resolve.js +110 -0
  91. package/src/slide-mode.cjs +72 -0
  92. package/src/template-fidelity.js +267 -0
  93. package/src/template-import.js +505 -0
  94. package/src/template-layout.js +261 -0
  95. package/src/template-pack.js +255 -0
  96. package/src/tldraw/render.js +473 -0
  97. package/src/validation/cli.js +120 -0
  98. package/src/validation/core.js +1023 -0
  99. package/templates/chart.html +121 -0
  100. package/templates/closing.html +54 -0
  101. package/templates/content.html +50 -0
  102. package/templates/contents.html +60 -0
  103. package/templates/cover.html +64 -0
  104. package/templates/custom/.gitkeep +0 -0
  105. package/templates/custom/README.md +7 -0
  106. package/templates/design-styles/README.md +20 -0
  107. package/templates/design-styles/preview.html +4438 -0
  108. package/templates/diagram-tldraw.html +56 -0
  109. package/templates/diagram.html +98 -0
  110. package/templates/quote.html +31 -0
  111. package/templates/section-divider.html +43 -0
  112. package/templates/split-layout.html +43 -0
  113. package/templates/statistics.html +55 -0
  114. package/templates/team.html +49 -0
  115. package/templates/timeline.html +59 -0
@@ -0,0 +1,170 @@
1
+ import { spawn } from 'node:child_process';
2
+
3
+ export const DEFAULT_EDIT_TIMEOUT_MS = 10 * 60 * 1000;
4
+ export const EDIT_TIMEOUT_EXIT_CODE = 124;
5
+ export const EDIT_TIMEOUT_ENV_VAR = 'PPT_AGENT_EDIT_TIMEOUT_MS';
6
+ export const EDIT_TIMEOUT_KILL_SIGNAL = 'SIGTERM';
7
+ export const EDIT_TIMEOUT_FORCE_KILL_AFTER_MS = 5_000;
8
+
9
+ export function parseEditTimeoutMs(rawValue = process.env[EDIT_TIMEOUT_ENV_VAR]) {
10
+ if (rawValue == null || rawValue === '') {
11
+ return DEFAULT_EDIT_TIMEOUT_MS;
12
+ }
13
+
14
+ const timeoutMs = Number(rawValue);
15
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
16
+ return DEFAULT_EDIT_TIMEOUT_MS;
17
+ }
18
+
19
+ return Math.floor(timeoutMs);
20
+ }
21
+
22
+ export function buildEditTimeoutMessage({ engineLabel = 'Editor process', timeoutMs }) {
23
+ return `${engineLabel} edit timed out after ${timeoutMs}ms and was terminated.`;
24
+ }
25
+
26
+ export const EDIT_ABORT_EXIT_CODE = 130;
27
+ export const EDIT_ABORT_KILL_SIGNAL = 'SIGTERM';
28
+ export const EDIT_ABORT_FORCE_KILL_AFTER_MS = 5_000;
29
+
30
+ export function buildEditAbortMessage({ engineLabel = 'Editor process' } = {}) {
31
+ return `${engineLabel} edit was aborted and the child process was terminated.`;
32
+ }
33
+
34
+ export function runEditSubprocess({
35
+ bin,
36
+ args,
37
+ cwd,
38
+ env,
39
+ stdio = ['ignore', 'pipe', 'pipe'],
40
+ timeoutMs = DEFAULT_EDIT_TIMEOUT_MS,
41
+ engineLabel,
42
+ onLog = () => {},
43
+ onChild = () => {},
44
+ signal,
45
+ spawnImpl = spawn,
46
+ }) {
47
+ return new Promise((resolvePromise, rejectPromise) => {
48
+ const child = spawnImpl(bin, args, { cwd, env, stdio });
49
+
50
+ try {
51
+ onChild(child);
52
+ } catch {
53
+ // Never let a faulty observer crash the spawn lifecycle.
54
+ }
55
+
56
+ let stdout = '';
57
+ let stderr = '';
58
+ let timedOut = false;
59
+ let aborted = false;
60
+ let settled = false;
61
+ let forceKillTimer = null;
62
+ let abortForceKillTimer = null;
63
+
64
+ const timeoutMessage = buildEditTimeoutMessage({ engineLabel, timeoutMs });
65
+ const abortMessage = buildEditAbortMessage({ engineLabel });
66
+
67
+ const timeoutTimer = setTimeout(() => {
68
+ if (settled || aborted) return;
69
+ timedOut = true;
70
+ const messageLine = `${timeoutMessage}\n`;
71
+ stderr += messageLine;
72
+ onLog('stderr', messageLine);
73
+ try {
74
+ child.kill(EDIT_TIMEOUT_KILL_SIGNAL);
75
+ } catch {}
76
+ forceKillTimer = setTimeout(() => {
77
+ try {
78
+ child.kill('SIGKILL');
79
+ } catch {}
80
+ }, EDIT_TIMEOUT_FORCE_KILL_AFTER_MS);
81
+ forceKillTimer.unref?.();
82
+ }, timeoutMs);
83
+ timeoutTimer.unref?.();
84
+
85
+ function abortChild() {
86
+ if (settled || aborted) return;
87
+ aborted = true;
88
+ const messageLine = `${abortMessage}\n`;
89
+ stderr += messageLine;
90
+ try {
91
+ onLog('stderr', messageLine);
92
+ } catch {}
93
+ try {
94
+ child.kill(EDIT_ABORT_KILL_SIGNAL);
95
+ } catch {}
96
+ abortForceKillTimer = setTimeout(() => {
97
+ try {
98
+ child.kill('SIGKILL');
99
+ } catch {}
100
+ }, EDIT_ABORT_FORCE_KILL_AFTER_MS);
101
+ abortForceKillTimer.unref?.();
102
+ }
103
+
104
+ if (signal) {
105
+ if (signal.aborted) {
106
+ setImmediate(abortChild);
107
+ } else {
108
+ const onAbort = () => abortChild();
109
+ signal.addEventListener?.('abort', onAbort, { once: true });
110
+ child.once('close', () => {
111
+ signal.removeEventListener?.('abort', onAbort);
112
+ });
113
+ }
114
+ }
115
+
116
+ child.stdout?.on('data', (chunk) => {
117
+ const text = chunk.toString();
118
+ stdout += text;
119
+ onLog('stdout', text);
120
+ });
121
+
122
+ child.stderr?.on('data', (chunk) => {
123
+ const text = chunk.toString();
124
+ stderr += text;
125
+ onLog('stderr', text);
126
+ });
127
+
128
+ child.on('close', (code, exitSignal) => {
129
+ if (settled) return;
130
+ settled = true;
131
+ clearTimeout(timeoutTimer);
132
+ clearTimeout(forceKillTimer);
133
+ clearTimeout(abortForceKillTimer);
134
+
135
+ let resolvedCode;
136
+ if (timedOut) {
137
+ resolvedCode = EDIT_TIMEOUT_EXIT_CODE;
138
+ } else if (aborted) {
139
+ resolvedCode = EDIT_ABORT_EXIT_CODE;
140
+ } else {
141
+ resolvedCode = code ?? 1;
142
+ }
143
+
144
+ let resolvedSignal = exitSignal;
145
+ if (timedOut && !exitSignal) resolvedSignal = EDIT_TIMEOUT_KILL_SIGNAL;
146
+ else if (aborted && !exitSignal) resolvedSignal = EDIT_ABORT_KILL_SIGNAL;
147
+
148
+ resolvePromise({
149
+ code: resolvedCode,
150
+ stdout,
151
+ stderr,
152
+ signal: resolvedSignal,
153
+ timedOut,
154
+ aborted,
155
+ timeoutMs: timedOut ? timeoutMs : null,
156
+ timeoutMessage: timedOut ? timeoutMessage : null,
157
+ abortMessage: aborted ? abortMessage : null,
158
+ });
159
+ });
160
+
161
+ child.on('error', (error) => {
162
+ if (settled) return;
163
+ settled = true;
164
+ clearTimeout(timeoutTimer);
165
+ clearTimeout(forceKillTimer);
166
+ clearTimeout(abortForceKillTimer);
167
+ rejectPromise(error);
168
+ });
169
+ });
170
+ }
@@ -0,0 +1,50 @@
1
+ # Editor Codex Prompt — Slide Edit Rules
2
+
3
+ This prompt is sent to Codex when the editor requests a single-slide edit.
4
+ It is intentionally separate from the full design skill (SKILL.md) because
5
+ the editor context assumes the deck design is already established.
6
+
7
+ ## Primary Objective
8
+ The user's edit request is the primary objective. All rules below exist to support it, not override it. When a rule conflicts with the user's intent, follow the user.
9
+
10
+ ## Edit Workflow
11
+ 1. Read the target slide HTML file.
12
+ 2. Apply the user's edit request to the selected region.
13
+ 3. Run `slides-grab validate --slides-dir <path>` after editing.
14
+ 4. If validation fails, fix the HTML/CSS and re-run until it passes.
15
+ 5. Return after applying the change.
16
+
17
+ ## Slide Rules
18
+ - Keep slide size appropriate for the current mode (`720pt x 405pt` for presentation, `720pt x 720pt` for card-news).
19
+ - Keep semantic text tags (`p`, `h1-h6`, `ul`, `ol`, `li`).
20
+ - Never place text directly in `<div>` or `<span>`.
21
+ - Always include `#` prefix in CSS colors.
22
+ - Always include the Pretendard webfont CDN link.
23
+
24
+ ## Asset Rules
25
+ - Put local images and videos under `<slides-dir>/assets/` and reference as `./assets/<file>`.
26
+ - Always include `alt` on `<img>` tags.
27
+ - Allow `data:` URLs only when the slide must be fully self-contained.
28
+ - Do not leave remote `http(s)://` image URLs in saved slide HTML; download into `./assets/`.
29
+ - Do not use absolute filesystem paths in slide HTML.
30
+ - Do not use non-body `background-image` for content imagery; use `<img>` instead.
31
+ - Use `data-image-placeholder` to reserve space when no image is available yet.
32
+ - When the request needs bespoke imagery, prefer `slides-grab image --prompt "<prompt>" --slides-dir <path>` so the default codex-imagen provider saves the asset under `<slides-dir>/assets/` via your local Codex ChatGPT login (run `codex login` once if needed).
33
+ - Default provider codex-imagen reuses `~/.codex/auth.json` — no OpenAI/Google API key required; requires a Codex/ChatGPT account entitled to image generation. ⚠️ codex calls an unsupported private Codex backend that may break without notice. Optional fallbacks: `--provider openai` (OpenAI gpt-image-2 via `OPENAI_API_KEY`; maps `--aspect-ratio` to the nearest supported OpenAI image size; `--image-size 2K|4K` is Nano Banana-only) or `--provider nano-banana` (Google `gemini-3-pro-image-preview` via `GOOGLE_API_KEY` / `GEMINI_API_KEY`; supports `--image-size 2K|4K`). If credentials are unavailable, fall back to web search + download into `./assets/`.
34
+ - For local videos, use `<video src="./assets/<file>">` with `poster="./assets/<file>"`.
35
+ - If a video starts on YouTube or a supported page, use `slides-grab fetch-video --url <url> --slides-dir <path>` to download first.
36
+
37
+ ## Art Direction Defaults
38
+ - Give each slide one job, one dominant visual anchor, one primary takeaway.
39
+ - Keep copy short enough to scan in seconds.
40
+ - Use whitespace, alignment, scale, cropping, and contrast before adding decorative chrome.
41
+ - Prefer Lucide as the default icon library for slide UI elements, callouts, and supporting visuals.
42
+ - Do not default to emoji for iconography unless the brief explicitly asks for a playful or native-emoji tone.
43
+ - Default to cardless layouts unless a card improves structure.
44
+ - Limit to two typefaces max and one accent color.
45
+
46
+ ## Do NOT
47
+ - Re-open style selection or run `slides-grab preview-styles`.
48
+ - Modify other slide HTML files unless explicitly requested.
49
+ - Persist runtime-only editor/viewer injections (`<base>`, debug scripts, viewer wrappers).
50
+ - Start PPTX/PDF conversion.