yumiamd 0.1.19 → 0.1.21
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/bin.js +1 -1
- package/dist/{chunk-YEQHWFYS.js → chunk-TJR6MU2I.js} +2393 -137
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -1
- package/package.json +10 -10
|
@@ -143,6 +143,21 @@ function createColumns(columns, ratios, gap) {
|
|
|
143
143
|
...gap !== void 0 ? { gap } : {}
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
|
+
function createSection(title, subtitle, number) {
|
|
147
|
+
return {
|
|
148
|
+
type: "section",
|
|
149
|
+
title,
|
|
150
|
+
...subtitle ? { subtitle } : {},
|
|
151
|
+
...number !== void 0 ? { number } : {}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function createToc(title, items) {
|
|
155
|
+
return {
|
|
156
|
+
type: "toc",
|
|
157
|
+
...title ? { title } : {},
|
|
158
|
+
...items ? { items } : {}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
146
161
|
function createMath(expression, displayMode = true) {
|
|
147
162
|
return {
|
|
148
163
|
type: "math",
|
|
@@ -157,8 +172,75 @@ function createLayoutDirective(mode, attributes) {
|
|
|
157
172
|
...attributes ? { attributes } : {}
|
|
158
173
|
};
|
|
159
174
|
}
|
|
175
|
+
function createIcon(name, provider, size, color) {
|
|
176
|
+
return {
|
|
177
|
+
type: "icon",
|
|
178
|
+
name,
|
|
179
|
+
...provider ? { provider } : {},
|
|
180
|
+
...size !== void 0 ? { size } : {},
|
|
181
|
+
...color ? { color } : {}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function createGrid(elements, columns = 2, gap) {
|
|
185
|
+
return {
|
|
186
|
+
type: "grid",
|
|
187
|
+
columns,
|
|
188
|
+
elements,
|
|
189
|
+
...gap !== void 0 ? { gap } : {}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function createStack(elements, direction = "vertical", gap, align, justify) {
|
|
193
|
+
return {
|
|
194
|
+
type: "stack",
|
|
195
|
+
direction,
|
|
196
|
+
elements,
|
|
197
|
+
...gap !== void 0 ? { gap } : {},
|
|
198
|
+
...align ? { align } : {},
|
|
199
|
+
...justify ? { justify } : {}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function createComponent(name, props, elements) {
|
|
203
|
+
return {
|
|
204
|
+
type: "component",
|
|
205
|
+
name,
|
|
206
|
+
...props ? { props } : {},
|
|
207
|
+
...elements ? { elements } : {}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function createSlot(name, elements) {
|
|
211
|
+
return {
|
|
212
|
+
type: "slot",
|
|
213
|
+
...name ? { name } : {},
|
|
214
|
+
...elements ? { elements } : {}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
160
217
|
|
|
161
218
|
// ../parser/dist/parser.js
|
|
219
|
+
function parseHighlightLines(highlightStr) {
|
|
220
|
+
if (!highlightStr)
|
|
221
|
+
return [];
|
|
222
|
+
const lines = /* @__PURE__ */ new Set();
|
|
223
|
+
const parts = highlightStr.split(",");
|
|
224
|
+
for (const part of parts) {
|
|
225
|
+
const trimmed = part.trim();
|
|
226
|
+
if (!trimmed)
|
|
227
|
+
continue;
|
|
228
|
+
if (trimmed.includes("-")) {
|
|
229
|
+
const [startStr, endStr] = trimmed.split("-");
|
|
230
|
+
const start = parseInt(startStr || "0", 10);
|
|
231
|
+
const end = parseInt(endStr || "0", 10);
|
|
232
|
+
if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
233
|
+
for (let n = start; n <= end; n++)
|
|
234
|
+
lines.add(n);
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
const num = parseInt(trimmed, 10);
|
|
238
|
+
if (!isNaN(num))
|
|
239
|
+
lines.add(num);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return Array.from(lines).sort((a, b) => a - b);
|
|
243
|
+
}
|
|
162
244
|
var DefaultYumiaParser = class {
|
|
163
245
|
diagnostics = [];
|
|
164
246
|
parse(source, options) {
|
|
@@ -166,6 +248,11 @@ var DefaultYumiaParser = class {
|
|
|
166
248
|
if (!source || typeof source !== "string") {
|
|
167
249
|
return createPresentation({}, []);
|
|
168
250
|
}
|
|
251
|
+
const trimmed = source.trimStart();
|
|
252
|
+
if (trimmed.startsWith("document ") || trimmed.startsWith("document\n") || trimmed.startsWith("slide ") || trimmed.startsWith("slide\n")) {
|
|
253
|
+
const nativeParser = new NativeYumiaParser();
|
|
254
|
+
return nativeParser.parse(source);
|
|
255
|
+
}
|
|
169
256
|
const normalized = source.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
170
257
|
const { metadata, content, lineOffset } = this.extractFrontmatter(normalized);
|
|
171
258
|
if (!content.trim()) {
|
|
@@ -234,16 +321,34 @@ var DefaultYumiaParser = class {
|
|
|
234
321
|
parseYamlMetadata(block) {
|
|
235
322
|
const metadata = {};
|
|
236
323
|
const lines = block.split("\n");
|
|
324
|
+
let currentKey = null;
|
|
237
325
|
for (const line of lines) {
|
|
238
326
|
const trimmed = line.trim();
|
|
239
327
|
if (!trimmed || trimmed.startsWith("#"))
|
|
240
328
|
continue;
|
|
329
|
+
if (trimmed.startsWith("- ") && currentKey) {
|
|
330
|
+
const itemVal = trimmed.slice(2).trim().replace(/^['"](.*)['"]$/, "$1");
|
|
331
|
+
if (Array.isArray(metadata[currentKey])) {
|
|
332
|
+
metadata[currentKey].push(itemVal);
|
|
333
|
+
} else {
|
|
334
|
+
metadata[currentKey] = [itemVal];
|
|
335
|
+
}
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
241
338
|
const colonIndex = trimmed.indexOf(":");
|
|
242
339
|
if (colonIndex > 0) {
|
|
243
340
|
const key = trimmed.slice(0, colonIndex).trim();
|
|
244
341
|
const rawVal = trimmed.slice(colonIndex + 1).trim();
|
|
245
|
-
|
|
246
|
-
|
|
342
|
+
currentKey = key;
|
|
343
|
+
if (rawVal.startsWith("[") && rawVal.endsWith("]")) {
|
|
344
|
+
const listItems = rawVal.slice(1, -1).split(",").map((item) => item.trim().replace(/^['"](.*)['"]$/, "$1")).filter(Boolean);
|
|
345
|
+
metadata[key] = listItems;
|
|
346
|
+
} else if (rawVal) {
|
|
347
|
+
const unquoted = rawVal.replace(/^['"](.*)['"]$/, "$1");
|
|
348
|
+
metadata[key] = unquoted;
|
|
349
|
+
} else {
|
|
350
|
+
metadata[key] = [];
|
|
351
|
+
}
|
|
247
352
|
}
|
|
248
353
|
}
|
|
249
354
|
const result = {};
|
|
@@ -268,6 +373,23 @@ var DefaultYumiaParser = class {
|
|
|
268
373
|
} else if (typeof metadata["embedFonts"] === "boolean") {
|
|
269
374
|
result.embedFonts = metadata["embedFonts"];
|
|
270
375
|
}
|
|
376
|
+
if (typeof metadata["watermark"] === "string") {
|
|
377
|
+
if (metadata["watermark"] === "false" || metadata["watermark"] === "none" || metadata["watermark"] === "off") {
|
|
378
|
+
result.watermark = false;
|
|
379
|
+
} else if (metadata["watermark"] === "true" || metadata["watermark"] === "yes" || metadata["watermark"] === "on") {
|
|
380
|
+
result.watermark = true;
|
|
381
|
+
} else {
|
|
382
|
+
result.watermark = metadata["watermark"];
|
|
383
|
+
}
|
|
384
|
+
} else if (typeof metadata["watermark"] === "boolean") {
|
|
385
|
+
result.watermark = metadata["watermark"];
|
|
386
|
+
}
|
|
387
|
+
if (metadata["styles"] || metadata["stylesheets"] || metadata["css"]) {
|
|
388
|
+
result.styles = metadata["styles"] || metadata["stylesheets"] || metadata["css"];
|
|
389
|
+
}
|
|
390
|
+
if (metadata["scripts"] || metadata["js"]) {
|
|
391
|
+
result.scripts = metadata["scripts"] || metadata["js"];
|
|
392
|
+
}
|
|
271
393
|
const colors = {};
|
|
272
394
|
if (typeof metadata["background"] === "string")
|
|
273
395
|
colors.background = metadata["background"];
|
|
@@ -386,7 +508,16 @@ var DefaultYumiaParser = class {
|
|
|
386
508
|
}
|
|
387
509
|
if (line.startsWith("```")) {
|
|
388
510
|
flushAll();
|
|
389
|
-
|
|
511
|
+
let rawLang = line.slice(3).trim() || void 0;
|
|
512
|
+
let highlight;
|
|
513
|
+
if (rawLang) {
|
|
514
|
+
const hlMatch = rawLang.match(/\{([\d,\s-]+)\}/) || rawLang.match(/highlight=['"]([\d,\s-]+)['"]/);
|
|
515
|
+
if (hlMatch) {
|
|
516
|
+
highlight = hlMatch[1]?.trim();
|
|
517
|
+
rawLang = rawLang.replace(hlMatch[0], "").trim() || void 0;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const language = rawLang;
|
|
390
521
|
const codeLines = [];
|
|
391
522
|
const codeStartLine = currentLineNum;
|
|
392
523
|
i++;
|
|
@@ -413,6 +544,10 @@ var DefaultYumiaParser = class {
|
|
|
413
544
|
});
|
|
414
545
|
}
|
|
415
546
|
const el = createCode(codeLines.join("\n"), language);
|
|
547
|
+
if (highlight) {
|
|
548
|
+
el.highlight = highlight;
|
|
549
|
+
el.highlightLines = parseHighlightLines(highlight);
|
|
550
|
+
}
|
|
416
551
|
el.loc = {
|
|
417
552
|
start: { line: codeStartLine, column: 1 },
|
|
418
553
|
end: { line: baseLine + i - 1, column: 1 }
|
|
@@ -462,7 +597,7 @@ var DefaultYumiaParser = class {
|
|
|
462
597
|
const variantMatch = directiveHeader.match(/variant=['"](.*?)['"]/);
|
|
463
598
|
const descMatch = directiveHeader.match(/description=['"](.*?)['"]/);
|
|
464
599
|
const unitMatch = directiveHeader.match(/unit=['"](.*?)['"]/);
|
|
465
|
-
const changeMatch = directiveHeader.match(/change=['"](.*?)['"]/);
|
|
600
|
+
const changeMatch = directiveHeader.match(/(?:change|diff)=['"](.*?)['"]/);
|
|
466
601
|
const value = valueMatch ? valueMatch[1] : "0";
|
|
467
602
|
const label = labelMatch ? labelMatch[1] : "";
|
|
468
603
|
const variant = variantMatch ? variantMatch[1] : void 0;
|
|
@@ -606,6 +741,82 @@ var DefaultYumiaParser = class {
|
|
|
606
741
|
end: { line: baseLine + i - 1, column: 1 }
|
|
607
742
|
};
|
|
608
743
|
elements.push(el);
|
|
744
|
+
} else if (directiveName === "code") {
|
|
745
|
+
const langMatch = directiveArg.match(/lang(?:uage)?=['"](.*?)['"]/);
|
|
746
|
+
const hlMatch = directiveArg.match(/highlight=['"](.*?)['"]/);
|
|
747
|
+
let lang = langMatch ? langMatch[1] : directiveArg.split(" ")[0] || void 0;
|
|
748
|
+
if (lang && (lang.includes("=") || lang.startsWith("{")))
|
|
749
|
+
lang = void 0;
|
|
750
|
+
const hlBraceMatch = directiveArg.match(/\{([\d,\s-]+)\}/);
|
|
751
|
+
const highlight = hlMatch ? hlMatch[1] : hlBraceMatch ? hlBraceMatch[1] : void 0;
|
|
752
|
+
const codeContent = blockLines.join("\n");
|
|
753
|
+
const el = createCode(codeContent, lang);
|
|
754
|
+
if (highlight) {
|
|
755
|
+
el.highlight = highlight;
|
|
756
|
+
el.highlightLines = parseHighlightLines(highlight);
|
|
757
|
+
}
|
|
758
|
+
el.loc = {
|
|
759
|
+
start: { line: directiveStartLine, column: 1 },
|
|
760
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
761
|
+
};
|
|
762
|
+
elements.push(el);
|
|
763
|
+
} else if (directiveName === "section") {
|
|
764
|
+
const allSectionText = [directiveArg, ...blockLines].join(" ");
|
|
765
|
+
const titleMatch = allSectionText.match(/\btitle=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
766
|
+
const subtitleMatch = allSectionText.match(/\bsubtitle=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
767
|
+
const numberMatch = allSectionText.match(/\bnumber=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
768
|
+
let subtitle = subtitleMatch ? subtitleMatch[1] ?? subtitleMatch[2] ?? subtitleMatch[3] : void 0;
|
|
769
|
+
const number = numberMatch ? numberMatch[1] ?? numberMatch[2] ?? numberMatch[3] : void 0;
|
|
770
|
+
let title = titleMatch ? titleMatch[1] ?? titleMatch[2] ?? titleMatch[3] : void 0;
|
|
771
|
+
if (!title) {
|
|
772
|
+
const stripped = directiveArg.replace(/\bsubtitle=(?:"[^"]*"|'[^']*'|\S+)/g, "").replace(/\bnumber=(?:"[^"]*"|'[^']*'|\S+)/g, "").trim();
|
|
773
|
+
title = stripped.replace(/^['"](.*)['"]$/, "$1").trim() || void 0;
|
|
774
|
+
}
|
|
775
|
+
if (!title && blockLines.length > 0) {
|
|
776
|
+
const plainLines = blockLines.filter((l) => !l.includes("subtitle=") && !l.includes("number="));
|
|
777
|
+
if (plainLines.length > 0)
|
|
778
|
+
title = plainLines[0]?.trim();
|
|
779
|
+
if (!subtitle && plainLines.length > 1)
|
|
780
|
+
subtitle = plainLines.slice(1).join("\n").trim();
|
|
781
|
+
}
|
|
782
|
+
const el = createSection(title || "Section", subtitle, number);
|
|
783
|
+
el.loc = {
|
|
784
|
+
start: { line: directiveStartLine, column: 1 },
|
|
785
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
786
|
+
};
|
|
787
|
+
elements.push(el);
|
|
788
|
+
} else if (directiveName === "toc") {
|
|
789
|
+
const titleMatch = directiveArg.match(/\btitle=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
790
|
+
let title = titleMatch ? titleMatch[1] ?? titleMatch[2] ?? titleMatch[3] : void 0;
|
|
791
|
+
if (!title) {
|
|
792
|
+
title = directiveArg.replace(/^['"](.*)['"]$/, "$1").trim() || void 0;
|
|
793
|
+
}
|
|
794
|
+
const items = [];
|
|
795
|
+
for (const bl of blockLines) {
|
|
796
|
+
const trimmed = bl.trim();
|
|
797
|
+
if (!trimmed)
|
|
798
|
+
continue;
|
|
799
|
+
const matchOrdered = trimmed.match(/^(\d+)\.\s+(.*?)(?:\s+[-–—:]\s+(.*))?$/);
|
|
800
|
+
const matchUnordered = trimmed.match(/^[-*]\s+(.*?)(?:\s+[-–—:]\s+(.*))?$/);
|
|
801
|
+
if (matchOrdered && matchOrdered[1] && matchOrdered[2]) {
|
|
802
|
+
items.push({
|
|
803
|
+
number: matchOrdered[1],
|
|
804
|
+
title: matchOrdered[2].trim(),
|
|
805
|
+
description: matchOrdered[3]?.trim() || void 0
|
|
806
|
+
});
|
|
807
|
+
} else if (matchUnordered && matchUnordered[1]) {
|
|
808
|
+
items.push({
|
|
809
|
+
title: matchUnordered[1].trim(),
|
|
810
|
+
description: matchUnordered[2]?.trim() || void 0
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
const el = createToc(title, items.length > 0 ? items : void 0);
|
|
815
|
+
el.loc = {
|
|
816
|
+
start: { line: directiveStartLine, column: 1 },
|
|
817
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
818
|
+
};
|
|
819
|
+
elements.push(el);
|
|
609
820
|
} else if (directiveName === "step") {
|
|
610
821
|
const { elements: stepElements } = this.parseLines(blockLines, blockBaseLine);
|
|
611
822
|
for (const sEl of stepElements) {
|
|
@@ -620,6 +831,39 @@ var DefaultYumiaParser = class {
|
|
|
620
831
|
end: { line: baseLine + i - 1, column: 1 }
|
|
621
832
|
};
|
|
622
833
|
elements.push(el);
|
|
834
|
+
} else if (directiveName === "icon") {
|
|
835
|
+
const nameMatch = directiveArg.match(/^(?:name=)?["']?([^"'\s]+)["']?/);
|
|
836
|
+
const name = nameMatch ? nameMatch[1] : directiveArg.trim();
|
|
837
|
+
const sizeMatch = directiveArg.match(/\bsize=["']?([^"'\s]+)["']?/);
|
|
838
|
+
const colorMatch = directiveArg.match(/\bcolor=["']?([^"'\s]+)["']?/);
|
|
839
|
+
const el = createIcon(name, void 0, sizeMatch ? sizeMatch[1] : void 0, colorMatch ? colorMatch[1] : void 0);
|
|
840
|
+
el.loc = {
|
|
841
|
+
start: { line: directiveStartLine, column: 1 },
|
|
842
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
843
|
+
};
|
|
844
|
+
elements.push(el);
|
|
845
|
+
} else if (directiveName === "grid") {
|
|
846
|
+
const colsMatch = directiveArg.match(/\bcolumns=["']?([^"'\s]+)["']?/);
|
|
847
|
+
const gapMatch = directiveArg.match(/\bgap=["']?([^"'\s]+)["']?/);
|
|
848
|
+
const columns = colsMatch ? parseInt(colsMatch[1], 10) || colsMatch[1] : 2;
|
|
849
|
+
const { elements: gridChildren } = this.parseLines(blockLines, blockBaseLine);
|
|
850
|
+
const el = createGrid(gridChildren, columns, gapMatch ? gapMatch[1] : void 0);
|
|
851
|
+
el.loc = {
|
|
852
|
+
start: { line: directiveStartLine, column: 1 },
|
|
853
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
854
|
+
};
|
|
855
|
+
elements.push(el);
|
|
856
|
+
} else if (directiveName === "stack") {
|
|
857
|
+
const dirMatch = directiveArg.match(/\bdirection=["']?(horizontal|vertical)["']?/);
|
|
858
|
+
const direction = dirMatch ? dirMatch[1] : "vertical";
|
|
859
|
+
const gapMatch = directiveArg.match(/\bgap=["']?([^"'\s]+)["']?/);
|
|
860
|
+
const { elements: stackChildren } = this.parseLines(blockLines, blockBaseLine);
|
|
861
|
+
const el = createStack(stackChildren, direction, gapMatch ? gapMatch[1] : void 0);
|
|
862
|
+
el.loc = {
|
|
863
|
+
start: { line: directiveStartLine, column: 1 },
|
|
864
|
+
end: { line: baseLine + i - 1, column: 1 }
|
|
865
|
+
};
|
|
866
|
+
elements.push(el);
|
|
623
867
|
}
|
|
624
868
|
continue;
|
|
625
869
|
}
|
|
@@ -837,6 +1081,7 @@ var DefaultYumiaParser = class {
|
|
|
837
1081
|
series.push({ name: title || "Data", values });
|
|
838
1082
|
}
|
|
839
1083
|
}
|
|
1084
|
+
const singleSeriesValues = [];
|
|
840
1085
|
for (const line of blockLines) {
|
|
841
1086
|
const trimmed = line.trim();
|
|
842
1087
|
if (!trimmed || trimmed.startsWith("#"))
|
|
@@ -858,13 +1103,28 @@ var DefaultYumiaParser = class {
|
|
|
858
1103
|
if (l && valStr) {
|
|
859
1104
|
labels.push(l);
|
|
860
1105
|
const val = parseFloat(valStr) || 0;
|
|
861
|
-
|
|
862
|
-
series.push({ name: "Data", values: [] });
|
|
863
|
-
series[0]?.values.push(val);
|
|
1106
|
+
singleSeriesValues.push(val);
|
|
864
1107
|
}
|
|
865
1108
|
}
|
|
1109
|
+
} else {
|
|
1110
|
+
const kvMatch = trimmed.match(/^[-*]?\s*(.*?)\s*[:=]\s*([+-]?\d+(?:\.\d+)?%?)$/);
|
|
1111
|
+
if (kvMatch && kvMatch[1] && kvMatch[2]) {
|
|
1112
|
+
labels.push(kvMatch[1].trim());
|
|
1113
|
+
const val = parseFloat(kvMatch[2].replace("%", "")) || 0;
|
|
1114
|
+
singleSeriesValues.push(val);
|
|
1115
|
+
}
|
|
866
1116
|
}
|
|
867
1117
|
}
|
|
1118
|
+
if (singleSeriesValues.length > 0) {
|
|
1119
|
+
if (series.length === 0) {
|
|
1120
|
+
series.push({ name: title || "Data", values: singleSeriesValues });
|
|
1121
|
+
} else if (series[0]) {
|
|
1122
|
+
series[0].values.push(...singleSeriesValues);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
if (series.length === 0) {
|
|
1126
|
+
series.push({ name: title || "Data", values: [] });
|
|
1127
|
+
}
|
|
868
1128
|
if (labels.length === 0) {
|
|
869
1129
|
const maxLen = Math.max(0, ...series.map((s) => s.values.length));
|
|
870
1130
|
labels = Array.from({ length: maxLen }, (_, i) => `Item ${i + 1}`);
|
|
@@ -910,6 +1170,13 @@ var DefaultYumiaParser = class {
|
|
|
910
1170
|
const rightMatch = headerArg.match(/right=['"](.*?)['"]/);
|
|
911
1171
|
const leftTitle = leftMatch ? leftMatch[1] : void 0;
|
|
912
1172
|
const rightTitle = rightMatch ? rightMatch[1] : void 0;
|
|
1173
|
+
const hasColumns = blockLines.some((l) => l.trim().startsWith(":::column"));
|
|
1174
|
+
if (hasColumns) {
|
|
1175
|
+
const cols = this.parseColumnsBlock(blockLines, baseLine);
|
|
1176
|
+
const leftElements2 = cols[0]?.elements || [];
|
|
1177
|
+
const rightElements2 = cols[1]?.elements || [];
|
|
1178
|
+
return createCompare(leftElements2, rightElements2, leftTitle, rightTitle);
|
|
1179
|
+
}
|
|
913
1180
|
let leftLines = [];
|
|
914
1181
|
let rightLines = [];
|
|
915
1182
|
let currentSide = "left";
|
|
@@ -944,6 +1211,449 @@ function parseYumia(source, options) {
|
|
|
944
1211
|
return parser.parse(source, options);
|
|
945
1212
|
}
|
|
946
1213
|
|
|
1214
|
+
// ../parser/dist/native-parser.js
|
|
1215
|
+
var NativeYumiaParser = class {
|
|
1216
|
+
parse(source) {
|
|
1217
|
+
const lines = source.split(/\r?\n/);
|
|
1218
|
+
const tokens = [];
|
|
1219
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1220
|
+
const raw = lines[i];
|
|
1221
|
+
const matchIndent = raw.match(/^(\s*)/);
|
|
1222
|
+
const indent = matchIndent ? matchIndent[1].length : 0;
|
|
1223
|
+
const text = raw.trim();
|
|
1224
|
+
if (!text || text.startsWith("//") || text.startsWith("#"))
|
|
1225
|
+
continue;
|
|
1226
|
+
const spaceIdx = text.indexOf(" ");
|
|
1227
|
+
const command = spaceIdx === -1 ? text : text.slice(0, spaceIdx);
|
|
1228
|
+
const args = spaceIdx === -1 ? "" : text.slice(spaceIdx + 1).trim();
|
|
1229
|
+
tokens.push({
|
|
1230
|
+
indent,
|
|
1231
|
+
lineNum: i + 1,
|
|
1232
|
+
text,
|
|
1233
|
+
command: command.toLowerCase(),
|
|
1234
|
+
args
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
const metadata = {};
|
|
1238
|
+
const slides = [];
|
|
1239
|
+
let currentSlideElements = [];
|
|
1240
|
+
let currentSlide = null;
|
|
1241
|
+
const flushSlide = () => {
|
|
1242
|
+
if (currentSlide) {
|
|
1243
|
+
currentSlide.elements = [...currentSlideElements];
|
|
1244
|
+
slides.push(currentSlide);
|
|
1245
|
+
currentSlideElements = [];
|
|
1246
|
+
currentSlide = null;
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
let idx = 0;
|
|
1250
|
+
while (idx < tokens.length) {
|
|
1251
|
+
const tok = tokens[idx];
|
|
1252
|
+
const cmdLower = tok.command.toLowerCase();
|
|
1253
|
+
if (cmdLower === "document" || cmdLower === "title") {
|
|
1254
|
+
metadata.title = this.stripQuotes(tok.args);
|
|
1255
|
+
idx++;
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
if (cmdLower === "theme") {
|
|
1259
|
+
metadata.theme = this.stripQuotes(tok.args);
|
|
1260
|
+
idx++;
|
|
1261
|
+
continue;
|
|
1262
|
+
}
|
|
1263
|
+
if (cmdLower === "aspectratio" || cmdLower === "ratio") {
|
|
1264
|
+
metadata.aspectRatio = this.stripQuotes(tok.args);
|
|
1265
|
+
idx++;
|
|
1266
|
+
continue;
|
|
1267
|
+
}
|
|
1268
|
+
if (cmdLower === "transition") {
|
|
1269
|
+
metadata.transition = this.stripQuotes(tok.args);
|
|
1270
|
+
idx++;
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
if (cmdLower === "watermark") {
|
|
1274
|
+
metadata.watermark = this.stripQuotes(tok.args);
|
|
1275
|
+
idx++;
|
|
1276
|
+
continue;
|
|
1277
|
+
}
|
|
1278
|
+
if (cmdLower === "author") {
|
|
1279
|
+
metadata.author = this.stripQuotes(tok.args);
|
|
1280
|
+
idx++;
|
|
1281
|
+
continue;
|
|
1282
|
+
}
|
|
1283
|
+
if (tok.command === "slide" || tok.command === "---") {
|
|
1284
|
+
flushSlide();
|
|
1285
|
+
const slideTitle = tok.command === "slide" ? this.stripQuotes(tok.args) : void 0;
|
|
1286
|
+
currentSlide = createSlide([], {
|
|
1287
|
+
loc: {
|
|
1288
|
+
start: { line: tok.lineNum, column: 1 },
|
|
1289
|
+
end: { line: tok.lineNum, column: tok.text.length }
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
if (slideTitle) {
|
|
1293
|
+
currentSlideElements.push(createHeading(slideTitle, 1));
|
|
1294
|
+
}
|
|
1295
|
+
idx++;
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1298
|
+
if (!currentSlide) {
|
|
1299
|
+
currentSlide = createSlide([], {
|
|
1300
|
+
loc: {
|
|
1301
|
+
start: { line: tok.lineNum, column: 1 },
|
|
1302
|
+
end: { line: tok.lineNum, column: tok.text.length }
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
if (tok.command === "notes") {
|
|
1307
|
+
const noteLines = [];
|
|
1308
|
+
idx++;
|
|
1309
|
+
while (idx < tokens.length && tokens[idx].indent > tok.indent) {
|
|
1310
|
+
noteLines.push(tokens[idx].text);
|
|
1311
|
+
idx++;
|
|
1312
|
+
}
|
|
1313
|
+
currentSlide.notes = (currentSlide.notes ? currentSlide.notes + "\n" : "") + noteLines.join("\n");
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
const parsedEl = this.parseElement(tokens, idx);
|
|
1317
|
+
if (parsedEl) {
|
|
1318
|
+
currentSlideElements.push(parsedEl.element);
|
|
1319
|
+
idx = parsedEl.nextIdx;
|
|
1320
|
+
} else {
|
|
1321
|
+
idx++;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
flushSlide();
|
|
1325
|
+
if (slides.length === 0) {
|
|
1326
|
+
slides.push(createSlide([createHeading(metadata.title || "Untitled Presentation", 1)]));
|
|
1327
|
+
}
|
|
1328
|
+
return createPresentation(metadata, slides);
|
|
1329
|
+
}
|
|
1330
|
+
parseElement(tokens, idx) {
|
|
1331
|
+
const tok = tokens[idx];
|
|
1332
|
+
const baseIndent = tok.indent;
|
|
1333
|
+
switch (tok.command) {
|
|
1334
|
+
case "heading":
|
|
1335
|
+
case "h1":
|
|
1336
|
+
case "h2":
|
|
1337
|
+
case "h3": {
|
|
1338
|
+
const level = tok.command === "h1" ? 1 : tok.command === "h2" ? 2 : tok.command === "h3" ? 3 : 1;
|
|
1339
|
+
const text = this.stripQuotes(tok.args);
|
|
1340
|
+
return { element: createHeading(text, level), nextIdx: idx + 1 };
|
|
1341
|
+
}
|
|
1342
|
+
case "paragraph":
|
|
1343
|
+
case "text":
|
|
1344
|
+
case "p": {
|
|
1345
|
+
let text = this.stripQuotes(tok.args);
|
|
1346
|
+
let nextIdx = idx + 1;
|
|
1347
|
+
if (!text) {
|
|
1348
|
+
const pLines = [];
|
|
1349
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1350
|
+
pLines.push(tokens[nextIdx].text);
|
|
1351
|
+
nextIdx++;
|
|
1352
|
+
}
|
|
1353
|
+
text = pLines.join(" ");
|
|
1354
|
+
}
|
|
1355
|
+
return { element: createParagraph(text), nextIdx };
|
|
1356
|
+
}
|
|
1357
|
+
case "icon": {
|
|
1358
|
+
const nameMatch = tok.args.match(/^(?:name=)?["']?([^"'\s]+)["']?/);
|
|
1359
|
+
const name = nameMatch ? nameMatch[1] : tok.args.trim();
|
|
1360
|
+
const sizeMatch = tok.args.match(/\bsize=["']?([^"'\s]+)["']?/);
|
|
1361
|
+
const colorMatch = tok.args.match(/\bcolor=["']?([^"'\s]+)["']?/);
|
|
1362
|
+
return {
|
|
1363
|
+
element: createIcon(name, void 0, sizeMatch ? sizeMatch[1] : void 0, colorMatch ? colorMatch[1] : void 0),
|
|
1364
|
+
nextIdx: idx + 1
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
case "card": {
|
|
1368
|
+
const titleMatch = tok.args.match(/title=["']([^"']+)["']/);
|
|
1369
|
+
const variantMatch = tok.args.match(/variant=["']?([^"'\s]+)["']?/);
|
|
1370
|
+
const title = titleMatch ? titleMatch[1] : this.stripQuotes(tok.args) || void 0;
|
|
1371
|
+
const variant = variantMatch ? variantMatch[1] : "default";
|
|
1372
|
+
const children = [];
|
|
1373
|
+
let nextIdx = idx + 1;
|
|
1374
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1375
|
+
const childRes = this.parseElement(tokens, nextIdx);
|
|
1376
|
+
if (childRes) {
|
|
1377
|
+
children.push(childRes.element);
|
|
1378
|
+
nextIdx = childRes.nextIdx;
|
|
1379
|
+
} else {
|
|
1380
|
+
nextIdx++;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return { element: createCard(children, title, variant), nextIdx };
|
|
1384
|
+
}
|
|
1385
|
+
case "columns": {
|
|
1386
|
+
const ratios = tok.args || "50:50";
|
|
1387
|
+
const cols = [];
|
|
1388
|
+
let nextIdx = idx + 1;
|
|
1389
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1390
|
+
const childRes = this.parseElement(tokens, nextIdx);
|
|
1391
|
+
if (childRes) {
|
|
1392
|
+
cols.push(childRes.element);
|
|
1393
|
+
nextIdx = childRes.nextIdx;
|
|
1394
|
+
} else {
|
|
1395
|
+
nextIdx++;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
const colElements = cols.map((c) => c.type === "column" ? c : createColumn([c]));
|
|
1399
|
+
return { element: createColumns(colElements, ratios), nextIdx };
|
|
1400
|
+
}
|
|
1401
|
+
case "grid": {
|
|
1402
|
+
const colsMatch = tok.args.match(/columns=["']?([^"'\s]+)["']?/);
|
|
1403
|
+
const gapMatch = tok.args.match(/gap=["']?([^"'\s]+)["']?/);
|
|
1404
|
+
const columns = colsMatch ? parseInt(colsMatch[1], 10) || colsMatch[1] : 2;
|
|
1405
|
+
const gap = gapMatch ? gapMatch[1] : void 0;
|
|
1406
|
+
const children = [];
|
|
1407
|
+
let nextIdx = idx + 1;
|
|
1408
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1409
|
+
const childRes = this.parseElement(tokens, nextIdx);
|
|
1410
|
+
if (childRes) {
|
|
1411
|
+
children.push(childRes.element);
|
|
1412
|
+
nextIdx = childRes.nextIdx;
|
|
1413
|
+
} else {
|
|
1414
|
+
nextIdx++;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return { element: createGrid(children, columns, gap), nextIdx };
|
|
1418
|
+
}
|
|
1419
|
+
case "stack": {
|
|
1420
|
+
const dirMatch = tok.args.match(/direction=["']?(horizontal|vertical)["']?/);
|
|
1421
|
+
const direction = dirMatch ? dirMatch[1] : "vertical";
|
|
1422
|
+
const gapMatch = tok.args.match(/gap=["']?([^"'\s]+)["']?/);
|
|
1423
|
+
const children = [];
|
|
1424
|
+
let nextIdx = idx + 1;
|
|
1425
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1426
|
+
const childRes = this.parseElement(tokens, nextIdx);
|
|
1427
|
+
if (childRes) {
|
|
1428
|
+
children.push(childRes.element);
|
|
1429
|
+
nextIdx = childRes.nextIdx;
|
|
1430
|
+
} else {
|
|
1431
|
+
nextIdx++;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
return {
|
|
1435
|
+
element: createStack(children, direction, gapMatch ? gapMatch[1] : void 0),
|
|
1436
|
+
nextIdx
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
case "metric": {
|
|
1440
|
+
const valMatch = tok.args.match(/^(?:value=)?["']([^"']+)["']/);
|
|
1441
|
+
const labelMatch = tok.args.match(/\blabel=["']([^"']+)["']/);
|
|
1442
|
+
const diffMatch = tok.args.match(/\bdiff=["']([^"']+)["']/);
|
|
1443
|
+
const variantMatch = tok.args.match(/\bvariant=["']?([^"'\s]+)["']?/);
|
|
1444
|
+
const value = valMatch ? valMatch[1] : "0";
|
|
1445
|
+
const label = labelMatch ? labelMatch[1] : "Metric";
|
|
1446
|
+
return {
|
|
1447
|
+
element: createMetric(value, label, variantMatch ? variantMatch[1] : "primary", void 0, void 0, diffMatch ? diffMatch[1] : void 0),
|
|
1448
|
+
nextIdx: idx + 1
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
case "code": {
|
|
1452
|
+
const langMatch = tok.args.match(/\blang(?:uage)?=["']?([^"'\s]+)["']?/);
|
|
1453
|
+
const hlMatch = tok.args.match(/\bhighlight=["']([^"']+)["']/);
|
|
1454
|
+
const codeLines = [];
|
|
1455
|
+
let nextIdx = idx + 1;
|
|
1456
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1457
|
+
codeLines.push(tokens[nextIdx].text);
|
|
1458
|
+
nextIdx++;
|
|
1459
|
+
}
|
|
1460
|
+
const el = createCode(codeLines.join("\n"), langMatch ? langMatch[1] : void 0);
|
|
1461
|
+
if (hlMatch && hlMatch[1]) {
|
|
1462
|
+
el.highlight = hlMatch[1];
|
|
1463
|
+
el.highlightLines = parseHighlightLines(hlMatch[1]);
|
|
1464
|
+
}
|
|
1465
|
+
return { element: el, nextIdx };
|
|
1466
|
+
}
|
|
1467
|
+
case "section": {
|
|
1468
|
+
const titleMatch = tok.args.match(/^(?:title=)?["']([^"']+)["']/);
|
|
1469
|
+
const subtitleMatch = tok.args.match(/\bsubtitle=["']([^"']+)["']/);
|
|
1470
|
+
const numMatch = tok.args.match(/\bnumber=["']?([^"'\s]+)["']?/);
|
|
1471
|
+
const title = titleMatch ? titleMatch[1] : this.stripQuotes(tok.args) || "Section";
|
|
1472
|
+
return {
|
|
1473
|
+
element: createSection(title, subtitleMatch ? subtitleMatch[1] : void 0, numMatch ? numMatch[1] : void 0),
|
|
1474
|
+
nextIdx: idx + 1
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
case "toc": {
|
|
1478
|
+
const title = this.stripQuotes(tok.args) || "Table of Contents";
|
|
1479
|
+
return { element: createToc(title), nextIdx: idx + 1 };
|
|
1480
|
+
}
|
|
1481
|
+
case "badge": {
|
|
1482
|
+
const textMatch = tok.args.match(/^(?:text=)?["']([^"']+)["']/);
|
|
1483
|
+
const variantMatch = tok.args.match(/\bvariant=["']?([^"'\s]+)["']?/);
|
|
1484
|
+
const text = textMatch ? textMatch[1] : this.stripQuotes(tok.args);
|
|
1485
|
+
return {
|
|
1486
|
+
element: createBadge(text, variantMatch ? variantMatch[1] : "default"),
|
|
1487
|
+
nextIdx: idx + 1
|
|
1488
|
+
};
|
|
1489
|
+
}
|
|
1490
|
+
case "list": {
|
|
1491
|
+
const items = [];
|
|
1492
|
+
let nextIdx = idx + 1;
|
|
1493
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1494
|
+
const sub = tokens[nextIdx];
|
|
1495
|
+
if (sub.command === "item" || sub.command === "-") {
|
|
1496
|
+
items.push({ text: this.stripQuotes(sub.args) });
|
|
1497
|
+
} else {
|
|
1498
|
+
items.push({ text: sub.text.replace(/^[-*]\s*/, "") });
|
|
1499
|
+
}
|
|
1500
|
+
nextIdx++;
|
|
1501
|
+
}
|
|
1502
|
+
return { element: createList(items, false), nextIdx };
|
|
1503
|
+
}
|
|
1504
|
+
case "quote": {
|
|
1505
|
+
const authorMatch = tok.args.match(/\bauthor=["']([^"']+)["']/);
|
|
1506
|
+
const textLines = [];
|
|
1507
|
+
let nextIdx = idx + 1;
|
|
1508
|
+
while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
|
|
1509
|
+
textLines.push(tokens[nextIdx].text);
|
|
1510
|
+
nextIdx++;
|
|
1511
|
+
}
|
|
1512
|
+
return {
|
|
1513
|
+
element: createQuote(textLines.join(" "), authorMatch ? authorMatch[1] : void 0),
|
|
1514
|
+
nextIdx
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
default:
|
|
1518
|
+
return { element: createParagraph(tok.text), nextIdx: idx + 1 };
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
stripQuotes(str) {
|
|
1522
|
+
if (!str)
|
|
1523
|
+
return "";
|
|
1524
|
+
const trimmed = str.trim();
|
|
1525
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
1526
|
+
return trimmed.slice(1, -1);
|
|
1527
|
+
}
|
|
1528
|
+
return trimmed;
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
function parseNativeYumia(source) {
|
|
1532
|
+
const parser = new NativeYumiaParser();
|
|
1533
|
+
return parser.parse(source);
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// ../parser/dist/migrator.js
|
|
1537
|
+
function migrateMarkdownToNative(source) {
|
|
1538
|
+
const presentation = parseYumia(source);
|
|
1539
|
+
const out = [];
|
|
1540
|
+
if (presentation.metadata.title) {
|
|
1541
|
+
out.push(`document "${presentation.metadata.title}"`);
|
|
1542
|
+
}
|
|
1543
|
+
if (presentation.metadata.theme) {
|
|
1544
|
+
const themeName = typeof presentation.metadata.theme === "string" ? presentation.metadata.theme : presentation.metadata.theme.name;
|
|
1545
|
+
out.push(` theme "${themeName}"`);
|
|
1546
|
+
}
|
|
1547
|
+
if (presentation.metadata.author) {
|
|
1548
|
+
out.push(` author "${presentation.metadata.author}"`);
|
|
1549
|
+
}
|
|
1550
|
+
if (presentation.metadata.aspectRatio) {
|
|
1551
|
+
out.push(` aspectRatio "${presentation.metadata.aspectRatio}"`);
|
|
1552
|
+
}
|
|
1553
|
+
if (presentation.metadata.transition) {
|
|
1554
|
+
const trans = typeof presentation.metadata.transition === "string" ? presentation.metadata.transition : presentation.metadata.transition.type;
|
|
1555
|
+
out.push(` transition "${trans}"`);
|
|
1556
|
+
}
|
|
1557
|
+
if (presentation.metadata.watermark) {
|
|
1558
|
+
out.push(` watermark "${presentation.metadata.watermark}"`);
|
|
1559
|
+
}
|
|
1560
|
+
out.push("");
|
|
1561
|
+
for (const slide of presentation.slides) {
|
|
1562
|
+
const firstHeading = slide.elements.find((el) => el.type === "heading");
|
|
1563
|
+
const slideTitle = firstHeading && firstHeading.level === 1 ? firstHeading.text : "";
|
|
1564
|
+
if (slideTitle) {
|
|
1565
|
+
out.push(`slide "${slideTitle}"`);
|
|
1566
|
+
} else {
|
|
1567
|
+
out.push("slide");
|
|
1568
|
+
}
|
|
1569
|
+
if (slide.transition) {
|
|
1570
|
+
const trans = typeof slide.transition === "string" ? slide.transition : slide.transition.type;
|
|
1571
|
+
out.push(` transition "${trans}"`);
|
|
1572
|
+
}
|
|
1573
|
+
for (const el of slide.elements) {
|
|
1574
|
+
if (el === firstHeading && firstHeading.level === 1)
|
|
1575
|
+
continue;
|
|
1576
|
+
out.push(serializeElement(el, 2));
|
|
1577
|
+
}
|
|
1578
|
+
if (slide.notes) {
|
|
1579
|
+
out.push(" notes");
|
|
1580
|
+
for (const nl of slide.notes.split("\n")) {
|
|
1581
|
+
out.push(` ${nl}`);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
out.push("");
|
|
1585
|
+
}
|
|
1586
|
+
return out.join("\n").trim() + "\n";
|
|
1587
|
+
}
|
|
1588
|
+
function serializeElement(el, indent) {
|
|
1589
|
+
const pad = " ".repeat(indent);
|
|
1590
|
+
switch (el.type) {
|
|
1591
|
+
case "heading":
|
|
1592
|
+
return `${pad}heading "${el.text}"`;
|
|
1593
|
+
case "paragraph":
|
|
1594
|
+
return `${pad}text "${el.text}"`;
|
|
1595
|
+
case "icon":
|
|
1596
|
+
return `${pad}icon "${el.name}"`;
|
|
1597
|
+
case "badge":
|
|
1598
|
+
return `${pad}badge "${el.text}" variant="${el.variant || "default"}"`;
|
|
1599
|
+
case "metric":
|
|
1600
|
+
return `${pad}metric "${el.value}" label="${el.label}"${el.change ? ` diff="${el.change}"` : ""}`;
|
|
1601
|
+
case "code": {
|
|
1602
|
+
const hl = el.highlight ? ` highlight="${el.highlight}"` : "";
|
|
1603
|
+
const lang = el.language ? ` lang="${el.language}"` : "";
|
|
1604
|
+
const codeLines = el.code.split("\n").map((l) => `${pad} ${l}`).join("\n");
|
|
1605
|
+
return `${pad}code${lang}${hl}
|
|
1606
|
+
${codeLines}`;
|
|
1607
|
+
}
|
|
1608
|
+
case "section": {
|
|
1609
|
+
const sub = el.subtitle ? ` subtitle="${el.subtitle}"` : "";
|
|
1610
|
+
const num = el.number !== void 0 ? ` number="${el.number}"` : "";
|
|
1611
|
+
return `${pad}section "${el.title}"${sub}${num}`;
|
|
1612
|
+
}
|
|
1613
|
+
case "toc":
|
|
1614
|
+
return `${pad}toc "${el.title || "Table of Contents"}"`;
|
|
1615
|
+
case "card": {
|
|
1616
|
+
const cleanTitle = (el.title || "").replace(/^[Tt]itle=['"]?/, "").replace(/['"]$/, "");
|
|
1617
|
+
const title = cleanTitle ? ` title="${cleanTitle}"` : "";
|
|
1618
|
+
const v = el.variant ? ` variant="${el.variant}"` : "";
|
|
1619
|
+
const cardChildren = (el.elements || []).map((c) => serializeElement(c, indent + 2)).join("\n");
|
|
1620
|
+
return `${pad}card${title}${v}
|
|
1621
|
+
${cardChildren}`;
|
|
1622
|
+
}
|
|
1623
|
+
case "grid": {
|
|
1624
|
+
const gridChildren = el.elements.map((c) => serializeElement(c, indent + 2)).join("\n");
|
|
1625
|
+
return `${pad}grid columns=${el.columns}
|
|
1626
|
+
${gridChildren}`;
|
|
1627
|
+
}
|
|
1628
|
+
case "stack": {
|
|
1629
|
+
const stackChildren = el.elements.map((c) => serializeElement(c, indent + 2)).join("\n");
|
|
1630
|
+
return `${pad}stack direction="${el.direction}"
|
|
1631
|
+
${stackChildren}`;
|
|
1632
|
+
}
|
|
1633
|
+
case "columns": {
|
|
1634
|
+
const colChildren = el.columns.map((col) => {
|
|
1635
|
+
const inner = col.elements.map((c) => serializeElement(c, indent + 4)).join("\n");
|
|
1636
|
+
return `${pad} column
|
|
1637
|
+
${inner}`;
|
|
1638
|
+
}).join("\n");
|
|
1639
|
+
return `${pad}columns ${el.ratios || "50:50"}
|
|
1640
|
+
${colChildren}`;
|
|
1641
|
+
}
|
|
1642
|
+
case "list": {
|
|
1643
|
+
const listItems = el.items.map((it) => `${pad} item "${it.text}"`).join("\n");
|
|
1644
|
+
return `${pad}list
|
|
1645
|
+
${listItems}`;
|
|
1646
|
+
}
|
|
1647
|
+
case "quote": {
|
|
1648
|
+
const qAuthor = el.author ? ` author="${el.author}"` : "";
|
|
1649
|
+
return `${pad}quote${qAuthor}
|
|
1650
|
+
${pad} ${el.text}`;
|
|
1651
|
+
}
|
|
1652
|
+
default:
|
|
1653
|
+
return `${pad}// [${el.type}]`;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
947
1657
|
// ../layout/dist/engine.js
|
|
948
1658
|
var DEFAULT_VIEWPORT = {
|
|
949
1659
|
width: 1920,
|
|
@@ -1036,6 +1746,14 @@ var DefaultLayoutEngine = class {
|
|
|
1036
1746
|
const height = 90;
|
|
1037
1747
|
return { element, bounds: { x, y, width, height } };
|
|
1038
1748
|
}
|
|
1749
|
+
case "section": {
|
|
1750
|
+
const height = 280;
|
|
1751
|
+
return { element, bounds: { x, y, width, height } };
|
|
1752
|
+
}
|
|
1753
|
+
case "toc": {
|
|
1754
|
+
const height = 320;
|
|
1755
|
+
return { element, bounds: { x, y, width, height } };
|
|
1756
|
+
}
|
|
1039
1757
|
case "card": {
|
|
1040
1758
|
return this.layoutCard(element, x, y, width, gap);
|
|
1041
1759
|
}
|
|
@@ -1753,50 +2471,559 @@ var academicTheme = {
|
|
|
1753
2471
|
}
|
|
1754
2472
|
}
|
|
1755
2473
|
};
|
|
1756
|
-
var
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
},
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2474
|
+
var nordTheme = {
|
|
2475
|
+
name: "nord",
|
|
2476
|
+
description: "Arctic, north-bluish clean dark palette for elegant developer decks",
|
|
2477
|
+
colors: {
|
|
2478
|
+
primary: "#88C0D0",
|
|
2479
|
+
secondary: "#81A1C1",
|
|
2480
|
+
background: "#2E3440",
|
|
2481
|
+
surface: "#3B4252",
|
|
2482
|
+
elevatedSurface: "#434C5E",
|
|
2483
|
+
text: "#ECEFF4",
|
|
2484
|
+
muted: "#D8DEE9",
|
|
2485
|
+
accent: "#5E81AC",
|
|
2486
|
+
border: "#4C566A",
|
|
2487
|
+
divider: "#434C5E",
|
|
2488
|
+
success: "#A3BE8C",
|
|
2489
|
+
warning: "#EBCB8B",
|
|
2490
|
+
danger: "#BF616A",
|
|
2491
|
+
info: "#88C0D0"
|
|
2492
|
+
},
|
|
2493
|
+
typography: {
|
|
2494
|
+
headingFont: "Inter, system-ui, sans-serif",
|
|
2495
|
+
bodyFont: "Inter, system-ui, sans-serif",
|
|
2496
|
+
codeFont: "JetBrains Mono, Fira Code, monospace",
|
|
2497
|
+
sizes: {
|
|
2498
|
+
display: 56,
|
|
2499
|
+
h1: 44,
|
|
2500
|
+
h2: 36,
|
|
2501
|
+
h3: 28,
|
|
2502
|
+
h4: 22,
|
|
2503
|
+
body: 18,
|
|
2504
|
+
small: 14,
|
|
2505
|
+
caption: 12,
|
|
2506
|
+
code: 16,
|
|
2507
|
+
quote: 20,
|
|
2508
|
+
metadata: 12
|
|
2509
|
+
},
|
|
2510
|
+
weights: {
|
|
2511
|
+
normal: 400,
|
|
2512
|
+
medium: 500,
|
|
2513
|
+
bold: 700
|
|
2514
|
+
},
|
|
2515
|
+
lineHeights: {
|
|
2516
|
+
tight: 1.15,
|
|
2517
|
+
snug: 1.3,
|
|
2518
|
+
normal: 1.55,
|
|
2519
|
+
relaxed: 1.7
|
|
2520
|
+
},
|
|
2521
|
+
letterSpacing: {
|
|
2522
|
+
tight: "-0.02em",
|
|
2523
|
+
normal: "0em",
|
|
2524
|
+
wide: "0.03em"
|
|
2525
|
+
}
|
|
2526
|
+
},
|
|
2527
|
+
spacing: {
|
|
2528
|
+
unit: 8,
|
|
2529
|
+
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
2530
|
+
slidePadding: 48,
|
|
2531
|
+
elementGap: 24,
|
|
2532
|
+
safeArea: { top: 48, bottom: 48, left: 48, right: 48 }
|
|
2533
|
+
},
|
|
2534
|
+
radius: {
|
|
2535
|
+
none: 0,
|
|
2536
|
+
sm: 4,
|
|
2537
|
+
md: 8,
|
|
2538
|
+
lg: 14,
|
|
2539
|
+
xl: 20,
|
|
2540
|
+
full: 9999,
|
|
2541
|
+
default: 8
|
|
2542
|
+
},
|
|
2543
|
+
shadows: {
|
|
2544
|
+
none: "none",
|
|
2545
|
+
sm: "0 2px 4px rgba(0, 0, 0, 0.25)",
|
|
2546
|
+
md: "0 6px 12px rgba(0, 0, 0, 0.35)",
|
|
2547
|
+
lg: "0 12px 24px rgba(0, 0, 0, 0.45)",
|
|
2548
|
+
glow: "0 0 16px rgba(136, 192, 208, 0.35)"
|
|
2549
|
+
},
|
|
2550
|
+
components: {
|
|
2551
|
+
card: {
|
|
2552
|
+
background: "#3B4252",
|
|
2553
|
+
borderColor: "#88C0D0",
|
|
2554
|
+
borderRadius: 10,
|
|
2555
|
+
padding: 24
|
|
2556
|
+
},
|
|
2557
|
+
metric: {
|
|
2558
|
+
valueColor: "#88C0D0",
|
|
2559
|
+
labelColor: "#D8DEE9",
|
|
2560
|
+
borderRadius: 10
|
|
2561
|
+
},
|
|
2562
|
+
code: {
|
|
2563
|
+
background: "#242933",
|
|
2564
|
+
textColor: "#ECEFF4",
|
|
2565
|
+
borderRadius: 8
|
|
2566
|
+
},
|
|
2567
|
+
table: {
|
|
2568
|
+
headerBackground: "#434C5E",
|
|
2569
|
+
rowAlternateBackground: "#3B4252",
|
|
2570
|
+
borderColor: "#4C566A"
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
var draculaTheme = {
|
|
2575
|
+
name: "dracula",
|
|
2576
|
+
description: "Famous dark theme with rich purples, vibrant pinks and pastel highlights",
|
|
2577
|
+
colors: {
|
|
2578
|
+
primary: "#BD93F9",
|
|
2579
|
+
secondary: "#FF79C6",
|
|
2580
|
+
background: "#282A36",
|
|
2581
|
+
surface: "#343746",
|
|
2582
|
+
elevatedSurface: "#44475A",
|
|
2583
|
+
text: "#F8F8F2",
|
|
2584
|
+
muted: "#6272A4",
|
|
2585
|
+
accent: "#8BE9FD",
|
|
2586
|
+
border: "#44475A",
|
|
2587
|
+
divider: "#6272A4",
|
|
2588
|
+
success: "#50FA7B",
|
|
2589
|
+
warning: "#F1FA8C",
|
|
2590
|
+
danger: "#FF5555",
|
|
2591
|
+
info: "#8BE9FD"
|
|
2592
|
+
},
|
|
2593
|
+
typography: {
|
|
2594
|
+
headingFont: "Outfit, Inter, sans-serif",
|
|
2595
|
+
bodyFont: "Inter, sans-serif",
|
|
2596
|
+
codeFont: "Fira Code, JetBrains Mono, monospace",
|
|
2597
|
+
sizes: {
|
|
2598
|
+
display: 56,
|
|
2599
|
+
h1: 44,
|
|
2600
|
+
h2: 36,
|
|
2601
|
+
h3: 28,
|
|
2602
|
+
h4: 22,
|
|
2603
|
+
body: 18,
|
|
2604
|
+
small: 14,
|
|
2605
|
+
caption: 12,
|
|
2606
|
+
code: 16,
|
|
2607
|
+
quote: 20,
|
|
2608
|
+
metadata: 12
|
|
2609
|
+
},
|
|
2610
|
+
weights: {
|
|
2611
|
+
normal: 400,
|
|
2612
|
+
medium: 500,
|
|
2613
|
+
bold: 700
|
|
2614
|
+
},
|
|
2615
|
+
lineHeights: {
|
|
2616
|
+
tight: 1.15,
|
|
2617
|
+
snug: 1.3,
|
|
2618
|
+
normal: 1.55,
|
|
2619
|
+
relaxed: 1.7
|
|
2620
|
+
},
|
|
2621
|
+
letterSpacing: {
|
|
2622
|
+
tight: "-0.02em",
|
|
2623
|
+
normal: "0em",
|
|
2624
|
+
wide: "0.03em"
|
|
2625
|
+
}
|
|
2626
|
+
},
|
|
2627
|
+
spacing: {
|
|
2628
|
+
unit: 8,
|
|
2629
|
+
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
2630
|
+
slidePadding: 48,
|
|
2631
|
+
elementGap: 24,
|
|
2632
|
+
safeArea: { top: 48, bottom: 48, left: 48, right: 48 }
|
|
2633
|
+
},
|
|
2634
|
+
radius: {
|
|
2635
|
+
none: 0,
|
|
2636
|
+
sm: 4,
|
|
2637
|
+
md: 10,
|
|
2638
|
+
lg: 16,
|
|
2639
|
+
xl: 24,
|
|
2640
|
+
full: 9999,
|
|
2641
|
+
default: 10
|
|
2642
|
+
},
|
|
2643
|
+
shadows: {
|
|
2644
|
+
none: "none",
|
|
2645
|
+
sm: "0 2px 5px rgba(0, 0, 0, 0.3)",
|
|
2646
|
+
md: "0 8px 16px rgba(0, 0, 0, 0.45)",
|
|
2647
|
+
lg: "0 16px 32px rgba(0, 0, 0, 0.6)",
|
|
2648
|
+
glow: "0 0 20px rgba(189, 147, 249, 0.4)"
|
|
2649
|
+
},
|
|
2650
|
+
components: {
|
|
2651
|
+
card: {
|
|
2652
|
+
background: "#343746",
|
|
2653
|
+
borderColor: "#BD93F9",
|
|
2654
|
+
borderRadius: 12,
|
|
2655
|
+
padding: 24
|
|
2656
|
+
},
|
|
2657
|
+
metric: {
|
|
2658
|
+
valueColor: "#FF79C6",
|
|
2659
|
+
labelColor: "#6272A4",
|
|
2660
|
+
borderRadius: 12
|
|
2661
|
+
},
|
|
2662
|
+
code: {
|
|
2663
|
+
background: "#1E1F29",
|
|
2664
|
+
textColor: "#F8F8F2",
|
|
2665
|
+
borderRadius: 8
|
|
2666
|
+
},
|
|
2667
|
+
table: {
|
|
2668
|
+
headerBackground: "#44475A",
|
|
2669
|
+
rowAlternateBackground: "#343746",
|
|
2670
|
+
borderColor: "#6272A4"
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
};
|
|
2674
|
+
var tokyoNightTheme = {
|
|
2675
|
+
name: "tokyo-night",
|
|
2676
|
+
description: "Sleek Tokyo Night neon indigo theme with cyan, violet and magenta tones",
|
|
2677
|
+
colors: {
|
|
2678
|
+
primary: "#7AA2F7",
|
|
2679
|
+
secondary: "#BB9AF7",
|
|
2680
|
+
background: "#1A1B26",
|
|
2681
|
+
surface: "#24283B",
|
|
2682
|
+
elevatedSurface: "#2F354A",
|
|
2683
|
+
text: "#C0CAF5",
|
|
2684
|
+
muted: "#565F89",
|
|
2685
|
+
accent: "#7DCFFF",
|
|
2686
|
+
border: "#2F354A",
|
|
2687
|
+
divider: "#414868",
|
|
2688
|
+
success: "#9ECE6A",
|
|
2689
|
+
warning: "#E0AF68",
|
|
2690
|
+
danger: "#F7768E",
|
|
2691
|
+
info: "#7DCFFF"
|
|
2692
|
+
},
|
|
2693
|
+
typography: {
|
|
2694
|
+
headingFont: "Outfit, Inter, sans-serif",
|
|
2695
|
+
bodyFont: "Inter, sans-serif",
|
|
2696
|
+
codeFont: "JetBrains Mono, monospace",
|
|
2697
|
+
sizes: {
|
|
2698
|
+
display: 58,
|
|
2699
|
+
h1: 46,
|
|
2700
|
+
h2: 36,
|
|
2701
|
+
h3: 28,
|
|
2702
|
+
h4: 22,
|
|
2703
|
+
body: 18,
|
|
2704
|
+
small: 14,
|
|
2705
|
+
caption: 12,
|
|
2706
|
+
code: 16,
|
|
2707
|
+
quote: 20,
|
|
2708
|
+
metadata: 12
|
|
2709
|
+
},
|
|
2710
|
+
weights: {
|
|
2711
|
+
normal: 400,
|
|
2712
|
+
medium: 500,
|
|
2713
|
+
bold: 700
|
|
2714
|
+
},
|
|
2715
|
+
lineHeights: {
|
|
2716
|
+
tight: 1.15,
|
|
2717
|
+
snug: 1.3,
|
|
2718
|
+
normal: 1.55,
|
|
2719
|
+
relaxed: 1.7
|
|
2720
|
+
},
|
|
2721
|
+
letterSpacing: {
|
|
2722
|
+
tight: "-0.02em",
|
|
2723
|
+
normal: "0em",
|
|
2724
|
+
wide: "0.03em"
|
|
2725
|
+
}
|
|
2726
|
+
},
|
|
2727
|
+
spacing: {
|
|
2728
|
+
unit: 8,
|
|
2729
|
+
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
2730
|
+
slidePadding: 48,
|
|
2731
|
+
elementGap: 24,
|
|
2732
|
+
safeArea: { top: 48, bottom: 48, left: 48, right: 48 }
|
|
2733
|
+
},
|
|
2734
|
+
radius: {
|
|
2735
|
+
none: 0,
|
|
2736
|
+
sm: 6,
|
|
2737
|
+
md: 10,
|
|
2738
|
+
lg: 16,
|
|
2739
|
+
xl: 24,
|
|
2740
|
+
full: 9999,
|
|
2741
|
+
default: 10
|
|
2742
|
+
},
|
|
2743
|
+
shadows: {
|
|
2744
|
+
none: "none",
|
|
2745
|
+
sm: "0 2px 4px rgba(0, 0, 0, 0.3)",
|
|
2746
|
+
md: "0 6px 14px rgba(0, 0, 0, 0.45)",
|
|
2747
|
+
lg: "0 14px 28px rgba(0, 0, 0, 0.6)",
|
|
2748
|
+
glow: "0 0 18px rgba(122, 162, 247, 0.4)"
|
|
2749
|
+
},
|
|
2750
|
+
components: {
|
|
2751
|
+
card: {
|
|
2752
|
+
background: "#24283B",
|
|
2753
|
+
borderColor: "#7AA2F7",
|
|
2754
|
+
borderRadius: 12,
|
|
2755
|
+
padding: 24
|
|
2756
|
+
},
|
|
2757
|
+
metric: {
|
|
2758
|
+
valueColor: "#7AA2F7",
|
|
2759
|
+
labelColor: "#565F89",
|
|
2760
|
+
borderRadius: 12
|
|
2761
|
+
},
|
|
2762
|
+
code: {
|
|
2763
|
+
background: "#16161E",
|
|
2764
|
+
textColor: "#C0CAF5",
|
|
2765
|
+
borderRadius: 8
|
|
2766
|
+
},
|
|
2767
|
+
table: {
|
|
2768
|
+
headerBackground: "#2F354A",
|
|
2769
|
+
rowAlternateBackground: "#24283B",
|
|
2770
|
+
borderColor: "#414868"
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
};
|
|
2774
|
+
var emeraldTheme = {
|
|
2775
|
+
name: "emerald",
|
|
2776
|
+
description: "Deep forest luxury green with mint and emerald highlights",
|
|
2777
|
+
colors: {
|
|
2778
|
+
primary: "#10B981",
|
|
2779
|
+
secondary: "#34D399",
|
|
2780
|
+
background: "#022C22",
|
|
2781
|
+
surface: "#064E3B",
|
|
2782
|
+
elevatedSurface: "#065F46",
|
|
2783
|
+
text: "#ECFDF5",
|
|
2784
|
+
muted: "#6EE7B7",
|
|
2785
|
+
accent: "#A7F3D0",
|
|
2786
|
+
border: "#047857",
|
|
2787
|
+
divider: "#065F46",
|
|
2788
|
+
success: "#34D399",
|
|
2789
|
+
warning: "#FBBF24",
|
|
2790
|
+
danger: "#F87171",
|
|
2791
|
+
info: "#38BDF8"
|
|
2792
|
+
},
|
|
2793
|
+
typography: {
|
|
2794
|
+
headingFont: "Outfit, Inter, sans-serif",
|
|
2795
|
+
bodyFont: "Inter, sans-serif",
|
|
2796
|
+
codeFont: "JetBrains Mono, monospace",
|
|
2797
|
+
sizes: {
|
|
2798
|
+
display: 56,
|
|
2799
|
+
h1: 44,
|
|
2800
|
+
h2: 36,
|
|
2801
|
+
h3: 28,
|
|
2802
|
+
h4: 22,
|
|
2803
|
+
body: 18,
|
|
2804
|
+
small: 14,
|
|
2805
|
+
caption: 12,
|
|
2806
|
+
code: 16,
|
|
2807
|
+
quote: 20,
|
|
2808
|
+
metadata: 12
|
|
2809
|
+
},
|
|
2810
|
+
weights: {
|
|
2811
|
+
normal: 400,
|
|
2812
|
+
medium: 500,
|
|
2813
|
+
bold: 700
|
|
2814
|
+
},
|
|
2815
|
+
lineHeights: {
|
|
2816
|
+
tight: 1.15,
|
|
2817
|
+
snug: 1.3,
|
|
2818
|
+
normal: 1.55,
|
|
2819
|
+
relaxed: 1.7
|
|
2820
|
+
},
|
|
2821
|
+
letterSpacing: {
|
|
2822
|
+
tight: "-0.02em",
|
|
2823
|
+
normal: "0em",
|
|
2824
|
+
wide: "0.03em"
|
|
2825
|
+
}
|
|
2826
|
+
},
|
|
2827
|
+
spacing: {
|
|
2828
|
+
unit: 8,
|
|
2829
|
+
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
2830
|
+
slidePadding: 48,
|
|
2831
|
+
elementGap: 24,
|
|
2832
|
+
safeArea: { top: 48, bottom: 48, left: 48, right: 48 }
|
|
2833
|
+
},
|
|
2834
|
+
radius: {
|
|
2835
|
+
none: 0,
|
|
2836
|
+
sm: 4,
|
|
2837
|
+
md: 8,
|
|
2838
|
+
lg: 16,
|
|
2839
|
+
xl: 24,
|
|
2840
|
+
full: 9999,
|
|
2841
|
+
default: 8
|
|
2842
|
+
},
|
|
2843
|
+
shadows: {
|
|
2844
|
+
none: "none",
|
|
2845
|
+
sm: "0 2px 4px rgba(0, 0, 0, 0.3)",
|
|
2846
|
+
md: "0 6px 14px rgba(0, 0, 0, 0.45)",
|
|
2847
|
+
lg: "0 14px 28px rgba(0, 0, 0, 0.6)",
|
|
2848
|
+
glow: "0 0 18px rgba(16, 185, 129, 0.4)"
|
|
2849
|
+
},
|
|
2850
|
+
components: {
|
|
2851
|
+
card: {
|
|
2852
|
+
background: "#064E3B",
|
|
2853
|
+
borderColor: "#10B981",
|
|
2854
|
+
borderRadius: 12,
|
|
2855
|
+
padding: 24
|
|
2856
|
+
},
|
|
2857
|
+
metric: {
|
|
2858
|
+
valueColor: "#10B981",
|
|
2859
|
+
labelColor: "#6EE7B7",
|
|
2860
|
+
borderRadius: 12
|
|
2861
|
+
},
|
|
2862
|
+
code: {
|
|
2863
|
+
background: "#011A14",
|
|
2864
|
+
textColor: "#ECFDF5",
|
|
2865
|
+
borderRadius: 8
|
|
2866
|
+
},
|
|
2867
|
+
table: {
|
|
2868
|
+
headerBackground: "#065F46",
|
|
2869
|
+
rowAlternateBackground: "#064E3B",
|
|
2870
|
+
borderColor: "#047857"
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
};
|
|
2874
|
+
var synthwaveTheme = {
|
|
2875
|
+
name: "synthwave",
|
|
2876
|
+
description: "80s retro neon sunset with hot pink, glowing cyan and electric violet",
|
|
2877
|
+
colors: {
|
|
2878
|
+
primary: "#FF71CE",
|
|
2879
|
+
secondary: "#01CDFE",
|
|
2880
|
+
background: "#1A0E2E",
|
|
2881
|
+
surface: "#261447",
|
|
2882
|
+
elevatedSurface: "#351B63",
|
|
2883
|
+
text: "#FFFFFF",
|
|
2884
|
+
muted: "#B967FF",
|
|
2885
|
+
accent: "#05FFA1",
|
|
2886
|
+
border: "#4D288C",
|
|
2887
|
+
divider: "#6432B8",
|
|
2888
|
+
success: "#05FFA1",
|
|
2889
|
+
warning: "#FFFB96",
|
|
2890
|
+
danger: "#FF2A6D",
|
|
2891
|
+
info: "#01CDFE"
|
|
2892
|
+
},
|
|
2893
|
+
typography: {
|
|
2894
|
+
headingFont: "Outfit, Inter, sans-serif",
|
|
2895
|
+
bodyFont: "Inter, sans-serif",
|
|
2896
|
+
codeFont: "Fira Code, monospace",
|
|
2897
|
+
sizes: {
|
|
2898
|
+
display: 58,
|
|
2899
|
+
h1: 46,
|
|
2900
|
+
h2: 38,
|
|
2901
|
+
h3: 28,
|
|
2902
|
+
h4: 22,
|
|
2903
|
+
body: 18,
|
|
2904
|
+
small: 14,
|
|
2905
|
+
caption: 12,
|
|
2906
|
+
code: 16,
|
|
2907
|
+
quote: 20,
|
|
2908
|
+
metadata: 12
|
|
2909
|
+
},
|
|
2910
|
+
weights: {
|
|
2911
|
+
normal: 400,
|
|
2912
|
+
medium: 500,
|
|
2913
|
+
bold: 700
|
|
2914
|
+
},
|
|
2915
|
+
lineHeights: {
|
|
2916
|
+
tight: 1.15,
|
|
2917
|
+
snug: 1.3,
|
|
2918
|
+
normal: 1.55,
|
|
2919
|
+
relaxed: 1.7
|
|
2920
|
+
},
|
|
2921
|
+
letterSpacing: {
|
|
2922
|
+
tight: "-0.02em",
|
|
2923
|
+
normal: "0em",
|
|
2924
|
+
wide: "0.04em"
|
|
2925
|
+
}
|
|
2926
|
+
},
|
|
2927
|
+
spacing: {
|
|
2928
|
+
unit: 8,
|
|
2929
|
+
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
2930
|
+
slidePadding: 48,
|
|
2931
|
+
elementGap: 24,
|
|
2932
|
+
safeArea: { top: 48, bottom: 48, left: 48, right: 48 }
|
|
2933
|
+
},
|
|
2934
|
+
radius: {
|
|
2935
|
+
none: 0,
|
|
2936
|
+
sm: 6,
|
|
2937
|
+
md: 12,
|
|
2938
|
+
lg: 18,
|
|
2939
|
+
xl: 26,
|
|
2940
|
+
full: 9999,
|
|
2941
|
+
default: 12
|
|
2942
|
+
},
|
|
2943
|
+
shadows: {
|
|
2944
|
+
none: "none",
|
|
2945
|
+
sm: "0 2px 6px rgba(0, 0, 0, 0.4)",
|
|
2946
|
+
md: "0 8px 18px rgba(0, 0, 0, 0.6)",
|
|
2947
|
+
lg: "0 16px 36px rgba(0, 0, 0, 0.75)",
|
|
2948
|
+
glow: "0 0 22px rgba(255, 113, 206, 0.5)"
|
|
2949
|
+
},
|
|
2950
|
+
components: {
|
|
2951
|
+
card: {
|
|
2952
|
+
background: "#261447",
|
|
2953
|
+
borderColor: "#FF71CE",
|
|
2954
|
+
borderRadius: 14,
|
|
2955
|
+
padding: 24
|
|
2956
|
+
},
|
|
2957
|
+
metric: {
|
|
2958
|
+
valueColor: "#FF71CE",
|
|
2959
|
+
labelColor: "#B967FF",
|
|
2960
|
+
borderRadius: 14
|
|
2961
|
+
},
|
|
2962
|
+
code: {
|
|
2963
|
+
background: "#11091F",
|
|
2964
|
+
textColor: "#05FFA1",
|
|
2965
|
+
borderRadius: 8
|
|
2966
|
+
},
|
|
2967
|
+
table: {
|
|
2968
|
+
headerBackground: "#351B63",
|
|
2969
|
+
rowAlternateBackground: "#261447",
|
|
2970
|
+
borderColor: "#4D288C"
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
};
|
|
2974
|
+
var THEME_REGISTRY = {
|
|
2975
|
+
default: defaultTheme,
|
|
2976
|
+
cyberpunk: cyberpunkTheme,
|
|
2977
|
+
minimal: minimalTheme,
|
|
2978
|
+
corporate: corporateTheme,
|
|
2979
|
+
terminal: terminalTheme,
|
|
2980
|
+
academic: academicTheme,
|
|
2981
|
+
nord: nordTheme,
|
|
2982
|
+
dracula: draculaTheme,
|
|
2983
|
+
"tokyo-night": tokyoNightTheme,
|
|
2984
|
+
tokyonight: tokyoNightTheme,
|
|
2985
|
+
midnight: tokyoNightTheme,
|
|
2986
|
+
emerald: emeraldTheme,
|
|
2987
|
+
forest: emeraldTheme,
|
|
2988
|
+
synthwave: synthwaveTheme,
|
|
2989
|
+
sunset: synthwaveTheme
|
|
2990
|
+
};
|
|
2991
|
+
function resolveTheme(themeNameOrRef, explicitOverrides) {
|
|
2992
|
+
const name = typeof themeNameOrRef === "string" ? themeNameOrRef : themeNameOrRef?.name || "default";
|
|
2993
|
+
const baseTheme = THEME_REGISTRY[name.toLowerCase()] || defaultTheme;
|
|
2994
|
+
const refOverrides = typeof themeNameOrRef === "object" ? themeNameOrRef.overrides : void 0;
|
|
2995
|
+
const mergedOverrides = {
|
|
2996
|
+
...refOverrides,
|
|
2997
|
+
...explicitOverrides,
|
|
2998
|
+
colors: { ...baseTheme.colors, ...refOverrides?.colors, ...explicitOverrides?.colors },
|
|
2999
|
+
typography: {
|
|
3000
|
+
...baseTheme.typography,
|
|
3001
|
+
...refOverrides?.typography,
|
|
3002
|
+
...explicitOverrides?.typography,
|
|
3003
|
+
sizes: {
|
|
3004
|
+
...baseTheme.typography.sizes,
|
|
3005
|
+
...refOverrides?.typography?.sizes,
|
|
3006
|
+
...explicitOverrides?.typography?.sizes
|
|
3007
|
+
},
|
|
3008
|
+
weights: {
|
|
3009
|
+
...baseTheme.typography.weights,
|
|
3010
|
+
...refOverrides?.typography?.weights,
|
|
3011
|
+
...explicitOverrides?.typography?.weights
|
|
3012
|
+
},
|
|
3013
|
+
lineHeights: {
|
|
3014
|
+
...baseTheme.typography.lineHeights,
|
|
3015
|
+
...refOverrides?.typography?.lineHeights,
|
|
3016
|
+
...explicitOverrides?.typography?.lineHeights
|
|
3017
|
+
}
|
|
3018
|
+
},
|
|
3019
|
+
spacing: {
|
|
3020
|
+
...baseTheme.spacing,
|
|
3021
|
+
...refOverrides?.spacing,
|
|
3022
|
+
...explicitOverrides?.spacing,
|
|
3023
|
+
safeArea: {
|
|
3024
|
+
...baseTheme.spacing.safeArea,
|
|
3025
|
+
...refOverrides?.spacing?.safeArea,
|
|
3026
|
+
...explicitOverrides?.spacing?.safeArea
|
|
1800
3027
|
}
|
|
1801
3028
|
},
|
|
1802
3029
|
radius: {
|
|
@@ -2248,6 +3475,174 @@ function lint(sourceOrPresentation, options) {
|
|
|
2248
3475
|
return defaultCompiler.lint(sourceOrPresentation, options);
|
|
2249
3476
|
}
|
|
2250
3477
|
|
|
3478
|
+
// ../renderer/dist/icons.js
|
|
3479
|
+
var BUILTIN_ICONS = {
|
|
3480
|
+
// Lucide & General
|
|
3481
|
+
rocket: {
|
|
3482
|
+
name: "rocket",
|
|
3483
|
+
provider: "lucide",
|
|
3484
|
+
viewBox: "0 0 24 24",
|
|
3485
|
+
path: '<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/>'
|
|
3486
|
+
},
|
|
3487
|
+
code: {
|
|
3488
|
+
name: "code",
|
|
3489
|
+
provider: "lucide",
|
|
3490
|
+
viewBox: "0 0 24 24",
|
|
3491
|
+
path: '<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>'
|
|
3492
|
+
},
|
|
3493
|
+
terminal: {
|
|
3494
|
+
name: "terminal",
|
|
3495
|
+
provider: "lucide",
|
|
3496
|
+
viewBox: "0 0 24 24",
|
|
3497
|
+
path: '<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>'
|
|
3498
|
+
},
|
|
3499
|
+
cpu: {
|
|
3500
|
+
name: "cpu",
|
|
3501
|
+
provider: "lucide",
|
|
3502
|
+
viewBox: "0 0 24 24",
|
|
3503
|
+
path: '<rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="1" x2="9" y2="4"/><line x1="15" y1="1" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="23"/><line x1="15" y1="20" x2="15" y2="23"/><line x1="20" y1="9" x2="23" y2="9"/><line x1="20" y1="14" x2="23" y2="14"/><line x1="1" y1="9" x2="4" y2="9"/><line x1="1" y1="14" x2="4" y2="14"/>'
|
|
3504
|
+
},
|
|
3505
|
+
database: {
|
|
3506
|
+
name: "database",
|
|
3507
|
+
provider: "lucide",
|
|
3508
|
+
viewBox: "0 0 24 24",
|
|
3509
|
+
path: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>'
|
|
3510
|
+
},
|
|
3511
|
+
zap: {
|
|
3512
|
+
name: "zap",
|
|
3513
|
+
provider: "lucide",
|
|
3514
|
+
viewBox: "0 0 24 24",
|
|
3515
|
+
path: '<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>'
|
|
3516
|
+
},
|
|
3517
|
+
shield: {
|
|
3518
|
+
name: "shield",
|
|
3519
|
+
provider: "lucide",
|
|
3520
|
+
viewBox: "0 0 24 24",
|
|
3521
|
+
path: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>'
|
|
3522
|
+
},
|
|
3523
|
+
activity: {
|
|
3524
|
+
name: "activity",
|
|
3525
|
+
provider: "lucide",
|
|
3526
|
+
viewBox: "0 0 24 24",
|
|
3527
|
+
path: '<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>'
|
|
3528
|
+
},
|
|
3529
|
+
palette: {
|
|
3530
|
+
name: "palette",
|
|
3531
|
+
provider: "lucide",
|
|
3532
|
+
viewBox: "0 0 24 24",
|
|
3533
|
+
path: '<circle cx="13.5" cy="6.5" r=".5"/><circle cx="17.5" cy="10.5" r=".5"/><circle cx="8.5" cy="7.5" r=".5"/><circle cx="6.5" cy="12.5" r=".5"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/>'
|
|
3534
|
+
},
|
|
3535
|
+
chart: {
|
|
3536
|
+
name: "chart",
|
|
3537
|
+
provider: "lucide",
|
|
3538
|
+
viewBox: "0 0 24 24",
|
|
3539
|
+
path: '<line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/>'
|
|
3540
|
+
},
|
|
3541
|
+
layers: {
|
|
3542
|
+
name: "layers",
|
|
3543
|
+
provider: "lucide",
|
|
3544
|
+
viewBox: "0 0 24 24",
|
|
3545
|
+
path: '<polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>'
|
|
3546
|
+
},
|
|
3547
|
+
users: {
|
|
3548
|
+
name: "users",
|
|
3549
|
+
provider: "lucide",
|
|
3550
|
+
viewBox: "0 0 24 24",
|
|
3551
|
+
path: '<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>'
|
|
3552
|
+
},
|
|
3553
|
+
check: {
|
|
3554
|
+
name: "check",
|
|
3555
|
+
provider: "lucide",
|
|
3556
|
+
viewBox: "0 0 24 24",
|
|
3557
|
+
path: '<polyline points="20 6 9 17 4 12"/>'
|
|
3558
|
+
},
|
|
3559
|
+
"git-branch": {
|
|
3560
|
+
name: "git-branch",
|
|
3561
|
+
provider: "lucide",
|
|
3562
|
+
viewBox: "0 0 24 24",
|
|
3563
|
+
path: '<line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>'
|
|
3564
|
+
},
|
|
3565
|
+
globe: {
|
|
3566
|
+
name: "globe",
|
|
3567
|
+
provider: "lucide",
|
|
3568
|
+
viewBox: "0 0 24 24",
|
|
3569
|
+
path: '<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>'
|
|
3570
|
+
},
|
|
3571
|
+
sparkles: {
|
|
3572
|
+
name: "sparkles",
|
|
3573
|
+
provider: "lucide",
|
|
3574
|
+
viewBox: "0 0 24 24",
|
|
3575
|
+
path: '<path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/><path d="M5 3v4"/><path d="M19 17v4"/><path d="M3 5h4"/><path d="M17 19h4"/>'
|
|
3576
|
+
}
|
|
3577
|
+
};
|
|
3578
|
+
var IconResolver = class {
|
|
3579
|
+
cache = /* @__PURE__ */ new Map();
|
|
3580
|
+
customProviders = /* @__PURE__ */ new Map();
|
|
3581
|
+
constructor() {
|
|
3582
|
+
for (const [key, def] of Object.entries(BUILTIN_ICONS)) {
|
|
3583
|
+
this.cache.set(key, def);
|
|
3584
|
+
this.cache.set(`lucide:${key}`, def);
|
|
3585
|
+
this.cache.set(`material:${key}`, { ...def, provider: "material" });
|
|
3586
|
+
this.cache.set(`fa:${key}`, { ...def, provider: "fa" });
|
|
3587
|
+
this.cache.set(`tabler:${key}`, { ...def, provider: "tabler" });
|
|
3588
|
+
this.cache.set(`heroicons:${key}`, { ...def, provider: "heroicons" });
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
registerProvider(name, resolver) {
|
|
3592
|
+
this.customProviders.set(name.toLowerCase(), resolver);
|
|
3593
|
+
}
|
|
3594
|
+
resolve(rawName, options = {}) {
|
|
3595
|
+
const trimmed = rawName.trim();
|
|
3596
|
+
if (!trimmed) {
|
|
3597
|
+
return this.getFallback("unknown");
|
|
3598
|
+
}
|
|
3599
|
+
if (this.cache.has(trimmed.toLowerCase())) {
|
|
3600
|
+
return this.cache.get(trimmed.toLowerCase());
|
|
3601
|
+
}
|
|
3602
|
+
let provider = options.defaultProvider || "lucide";
|
|
3603
|
+
let iconName = trimmed;
|
|
3604
|
+
if (trimmed.includes(":")) {
|
|
3605
|
+
const parts = trimmed.split(":");
|
|
3606
|
+
provider = parts[0].toLowerCase();
|
|
3607
|
+
iconName = parts.slice(1).join(":").toLowerCase();
|
|
3608
|
+
}
|
|
3609
|
+
if (this.customProviders.has(provider)) {
|
|
3610
|
+
const customDef = this.customProviders.get(provider)(iconName);
|
|
3611
|
+
if (customDef) {
|
|
3612
|
+
this.cache.set(trimmed.toLowerCase(), customDef);
|
|
3613
|
+
return customDef;
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
if (this.cache.has(iconName)) {
|
|
3617
|
+
const def = { ...this.cache.get(iconName), provider };
|
|
3618
|
+
this.cache.set(trimmed.toLowerCase(), def);
|
|
3619
|
+
return def;
|
|
3620
|
+
}
|
|
3621
|
+
if (options.strict) {
|
|
3622
|
+
throw new Error(`Icon '${trimmed}' not found in registry (provider: ${provider})`);
|
|
3623
|
+
}
|
|
3624
|
+
const fallback = this.getFallback(iconName, provider);
|
|
3625
|
+
this.cache.set(trimmed.toLowerCase(), fallback);
|
|
3626
|
+
return fallback;
|
|
3627
|
+
}
|
|
3628
|
+
getFallback(iconName, provider = "lucide") {
|
|
3629
|
+
const initial = iconName.charAt(0).toUpperCase() || "\u2605";
|
|
3630
|
+
return {
|
|
3631
|
+
name: iconName,
|
|
3632
|
+
provider,
|
|
3633
|
+
viewBox: "0 0 24 24",
|
|
3634
|
+
path: `<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><text x="12" y="16" text-anchor="middle" font-size="11" font-weight="bold" fill="currentColor" font-family="sans-serif">${initial}</text>`
|
|
3635
|
+
};
|
|
3636
|
+
}
|
|
3637
|
+
toSvg(rawName, size = 24, color, className = "yumia-icon") {
|
|
3638
|
+
const icon = this.resolve(rawName);
|
|
3639
|
+
const fill = color ? `color="${color}"` : "";
|
|
3640
|
+
const style = color ? `style="color:${color}; fill:none; stroke:currentColor;"` : 'style="fill:none; stroke:currentColor;"';
|
|
3641
|
+
return `<svg class="${className}" width="${size}" height="${size}" viewBox="${icon.viewBox}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ${fill} ${style}>${icon.path}</svg>`;
|
|
3642
|
+
}
|
|
3643
|
+
};
|
|
3644
|
+
var defaultIconResolver = new IconResolver();
|
|
3645
|
+
|
|
2251
3646
|
// ../renderer-pptx/dist/renderer.js
|
|
2252
3647
|
import pptxgen from "pptxgenjs";
|
|
2253
3648
|
var CSS_NAMED_COLORS = {
|
|
@@ -2294,6 +3689,8 @@ function cleanFontFace(fontString) {
|
|
|
2294
3689
|
return "Segoe UI";
|
|
2295
3690
|
}
|
|
2296
3691
|
function parseInlineMarkdown(rawText, baseOptions) {
|
|
3692
|
+
if (!rawText)
|
|
3693
|
+
return [];
|
|
2297
3694
|
const chunks = [];
|
|
2298
3695
|
const regex = /(\*\*.*?\*\*|\*.*?\*|`.*?`)/g;
|
|
2299
3696
|
const parts = rawText.split(regex);
|
|
@@ -2356,7 +3753,7 @@ var PptxRenderer = class {
|
|
|
2356
3753
|
pptxSlide.background = { color: bgColor };
|
|
2357
3754
|
const slideLayout = this.layoutEngine.computeSlide(slide, pixelViewport);
|
|
2358
3755
|
for (const node of slideLayout.nodes) {
|
|
2359
|
-
this.renderNode(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
3756
|
+
this.renderNode(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation);
|
|
2360
3757
|
}
|
|
2361
3758
|
if (slide.notes) {
|
|
2362
3759
|
pptxSlide.addNotes(slide.notes);
|
|
@@ -2371,7 +3768,7 @@ var PptxRenderer = class {
|
|
|
2371
3768
|
fileName: `${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}.pptx`
|
|
2372
3769
|
};
|
|
2373
3770
|
}
|
|
2374
|
-
renderNode(pptxSlide, pptx, node, scaleX, scaleY, theme) {
|
|
3771
|
+
renderNode(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation) {
|
|
2375
3772
|
const { element, bounds } = node;
|
|
2376
3773
|
const rect = this.toInches(bounds, scaleX, scaleY);
|
|
2377
3774
|
switch (element.type) {
|
|
@@ -2400,10 +3797,10 @@ var PptxRenderer = class {
|
|
|
2400
3797
|
this.renderMetric(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
2401
3798
|
break;
|
|
2402
3799
|
case "card":
|
|
2403
|
-
this.renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
3800
|
+
this.renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation);
|
|
2404
3801
|
break;
|
|
2405
3802
|
case "columns":
|
|
2406
|
-
this.renderColumns(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
3803
|
+
this.renderColumns(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation);
|
|
2407
3804
|
break;
|
|
2408
3805
|
case "badge":
|
|
2409
3806
|
this.renderBadge(pptxSlide, pptx, element, rect, theme);
|
|
@@ -2417,12 +3814,42 @@ var PptxRenderer = class {
|
|
|
2417
3814
|
case "compare":
|
|
2418
3815
|
this.renderCompare(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
2419
3816
|
break;
|
|
3817
|
+
case "section":
|
|
3818
|
+
this.renderSection(pptxSlide, pptx, element, rect, theme);
|
|
3819
|
+
break;
|
|
3820
|
+
case "toc":
|
|
3821
|
+
this.renderToc(pptxSlide, pptx, element, rect, theme, presentation);
|
|
3822
|
+
break;
|
|
2420
3823
|
case "mermaid":
|
|
2421
3824
|
this.renderMermaid(pptxSlide, pptx, element, rect, theme);
|
|
2422
3825
|
break;
|
|
2423
3826
|
case "math":
|
|
2424
3827
|
this.renderMath(pptxSlide, pptx, element, rect, theme);
|
|
2425
3828
|
break;
|
|
3829
|
+
case "icon": {
|
|
3830
|
+
const ic = element;
|
|
3831
|
+
const iconName = ic.name.replace(/^[^:]+:/, "").toUpperCase();
|
|
3832
|
+
pptxSlide.addText(`\u2605 ${iconName}`, {
|
|
3833
|
+
x: rect.x,
|
|
3834
|
+
y: rect.y,
|
|
3835
|
+
w: Math.max(rect.w, 1.5),
|
|
3836
|
+
h: Math.max(rect.h, 0.4),
|
|
3837
|
+
fontSize: 14,
|
|
3838
|
+
bold: true,
|
|
3839
|
+
color: this.cleanHexColor(theme.colors.primary),
|
|
3840
|
+
valign: "middle"
|
|
3841
|
+
});
|
|
3842
|
+
break;
|
|
3843
|
+
}
|
|
3844
|
+
case "grid":
|
|
3845
|
+
case "stack": {
|
|
3846
|
+
if (node.children) {
|
|
3847
|
+
for (const childNode of node.children) {
|
|
3848
|
+
this.renderNode(pptxSlide, pptx, childNode, scaleX, scaleY, theme, presentation);
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
break;
|
|
3852
|
+
}
|
|
2426
3853
|
default:
|
|
2427
3854
|
break;
|
|
2428
3855
|
}
|
|
@@ -2636,7 +4063,7 @@ var PptxRenderer = class {
|
|
|
2636
4063
|
});
|
|
2637
4064
|
}
|
|
2638
4065
|
}
|
|
2639
|
-
renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme) {
|
|
4066
|
+
renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation) {
|
|
2640
4067
|
const card = node.element;
|
|
2641
4068
|
const rect = this.toInches(node.bounds, scaleX, scaleY);
|
|
2642
4069
|
const cardTheme = theme.components?.card;
|
|
@@ -2657,6 +4084,14 @@ var PptxRenderer = class {
|
|
|
2657
4084
|
line: { color: borderColor, width: 1.5 },
|
|
2658
4085
|
rectRadius: 0.08
|
|
2659
4086
|
});
|
|
4087
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4088
|
+
x: rect.x + 0.02,
|
|
4089
|
+
y: rect.y + 0.04,
|
|
4090
|
+
w: 0.06,
|
|
4091
|
+
h: rect.h - 0.08,
|
|
4092
|
+
fill: { color: borderColor },
|
|
4093
|
+
rectRadius: 0.03
|
|
4094
|
+
});
|
|
2660
4095
|
if (card.title) {
|
|
2661
4096
|
pptxSlide.addText(card.title, {
|
|
2662
4097
|
x: rect.x + 0.25,
|
|
@@ -2671,16 +4106,16 @@ var PptxRenderer = class {
|
|
|
2671
4106
|
}
|
|
2672
4107
|
if (node.children) {
|
|
2673
4108
|
for (const childNode of node.children) {
|
|
2674
|
-
this.renderNode(pptxSlide, pptx, childNode, scaleX, scaleY, theme);
|
|
4109
|
+
this.renderNode(pptxSlide, pptx, childNode, scaleX, scaleY, theme, presentation);
|
|
2675
4110
|
}
|
|
2676
4111
|
}
|
|
2677
4112
|
}
|
|
2678
|
-
renderColumns(pptxSlide, pptx, node, scaleX, scaleY, theme) {
|
|
4113
|
+
renderColumns(pptxSlide, pptx, node, scaleX, scaleY, theme, presentation) {
|
|
2679
4114
|
if (node.children) {
|
|
2680
4115
|
for (const colNode of node.children) {
|
|
2681
4116
|
if (colNode.children) {
|
|
2682
4117
|
for (const itemNode of colNode.children) {
|
|
2683
|
-
this.renderNode(pptxSlide, pptx, itemNode, scaleX, scaleY, theme);
|
|
4118
|
+
this.renderNode(pptxSlide, pptx, itemNode, scaleX, scaleY, theme, presentation);
|
|
2684
4119
|
}
|
|
2685
4120
|
}
|
|
2686
4121
|
}
|
|
@@ -2688,26 +4123,88 @@ var PptxRenderer = class {
|
|
|
2688
4123
|
}
|
|
2689
4124
|
renderCode(pptxSlide, pptx, code, rect, theme) {
|
|
2690
4125
|
const codeTheme = theme.components?.code;
|
|
2691
|
-
const bgColor = this.cleanHexColor(codeTheme?.background || "#
|
|
4126
|
+
const bgColor = this.cleanHexColor(codeTheme?.background || "#0a0f1d");
|
|
2692
4127
|
const textColor = this.cleanHexColor(codeTheme?.textColor || "#f8fafc");
|
|
4128
|
+
const primaryColor = this.cleanHexColor(theme.colors.primary || "#00F0FF");
|
|
4129
|
+
const mutedColor = this.cleanHexColor(theme.colors.muted || "#64748b");
|
|
2693
4130
|
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
2694
4131
|
x: rect.x,
|
|
2695
4132
|
y: rect.y,
|
|
2696
4133
|
w: rect.w,
|
|
2697
4134
|
h: rect.h,
|
|
2698
4135
|
fill: { color: bgColor },
|
|
4136
|
+
line: { color: this.cleanHexColor(theme.colors.border || "#1e293b"), width: 1 },
|
|
2699
4137
|
rectRadius: 0.05
|
|
2700
4138
|
});
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
4139
|
+
const lines = code.code.split("\n");
|
|
4140
|
+
if (code.highlight) {
|
|
4141
|
+
const highlightSet = /* @__PURE__ */ new Set();
|
|
4142
|
+
const parts = code.highlight.split(",");
|
|
4143
|
+
for (const part of parts) {
|
|
4144
|
+
const trimmed = part.trim();
|
|
4145
|
+
if (!trimmed)
|
|
4146
|
+
continue;
|
|
4147
|
+
if (trimmed.includes("-")) {
|
|
4148
|
+
const [startStr, endStr] = trimmed.split("-");
|
|
4149
|
+
const start = parseInt(startStr || "0", 10);
|
|
4150
|
+
const end = parseInt(endStr || "0", 10);
|
|
4151
|
+
if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
4152
|
+
for (let n = start; n <= end; n++)
|
|
4153
|
+
highlightSet.add(n);
|
|
4154
|
+
}
|
|
4155
|
+
} else {
|
|
4156
|
+
const num = parseInt(trimmed, 10);
|
|
4157
|
+
if (!isNaN(num))
|
|
4158
|
+
highlightSet.add(num);
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
const chunks = [];
|
|
4162
|
+
lines.forEach((line, idx) => {
|
|
4163
|
+
const lineNum = idx + 1;
|
|
4164
|
+
const isHl = highlightSet.has(lineNum);
|
|
4165
|
+
const lineNumPad = String(lineNum).padStart(2, "0");
|
|
4166
|
+
const numColor = isHl ? primaryColor : mutedColor;
|
|
4167
|
+
const contentColor = isHl ? primaryColor : mutedColor;
|
|
4168
|
+
chunks.push({
|
|
4169
|
+
text: `${lineNumPad} `,
|
|
4170
|
+
options: {
|
|
4171
|
+
fontSize: 12,
|
|
4172
|
+
fontFace: "Consolas",
|
|
4173
|
+
color: numColor,
|
|
4174
|
+
bold: isHl
|
|
4175
|
+
}
|
|
4176
|
+
});
|
|
4177
|
+
chunks.push({
|
|
4178
|
+
text: line || " ",
|
|
4179
|
+
options: {
|
|
4180
|
+
fontSize: 12,
|
|
4181
|
+
fontFace: "Consolas",
|
|
4182
|
+
color: contentColor,
|
|
4183
|
+
bold: isHl,
|
|
4184
|
+
breakLine: idx < lines.length - 1
|
|
4185
|
+
}
|
|
4186
|
+
});
|
|
4187
|
+
});
|
|
4188
|
+
pptxSlide.addText(chunks, {
|
|
4189
|
+
x: rect.x + 0.2,
|
|
4190
|
+
y: rect.y + 0.15,
|
|
4191
|
+
w: rect.w - 0.4,
|
|
4192
|
+
h: rect.h - 0.3,
|
|
4193
|
+
valign: "top",
|
|
4194
|
+
margin: 0
|
|
4195
|
+
});
|
|
4196
|
+
} else {
|
|
4197
|
+
pptxSlide.addText(code.code, {
|
|
4198
|
+
x: rect.x + 0.2,
|
|
4199
|
+
y: rect.y + 0.15,
|
|
4200
|
+
w: rect.w - 0.4,
|
|
4201
|
+
h: rect.h - 0.3,
|
|
4202
|
+
fontSize: 13,
|
|
4203
|
+
fontFace: "Consolas",
|
|
4204
|
+
color: textColor,
|
|
4205
|
+
valign: "top"
|
|
4206
|
+
});
|
|
4207
|
+
}
|
|
2711
4208
|
}
|
|
2712
4209
|
renderQuote(pptxSlide, pptx, quote, rect, theme) {
|
|
2713
4210
|
const accentColor = this.cleanHexColor(theme.colors.accent || theme.colors.primary);
|
|
@@ -2734,7 +4231,8 @@ var PptxRenderer = class {
|
|
|
2734
4231
|
renderBadge(pptxSlide, pptx, badge, rect, theme) {
|
|
2735
4232
|
const colorKey = badge.variant || "primary";
|
|
2736
4233
|
const badgeColor = this.cleanHexColor(theme.colors[colorKey] || theme.colors.primary);
|
|
2737
|
-
const
|
|
4234
|
+
const badgeText = badge.text;
|
|
4235
|
+
const badgeW = Math.min(2.5, Math.max(1, badgeText.length * 0.12 + 0.4));
|
|
2738
4236
|
const badgeH = Math.min(0.38, rect.h);
|
|
2739
4237
|
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
2740
4238
|
x: rect.x,
|
|
@@ -2745,7 +4243,7 @@ var PptxRenderer = class {
|
|
|
2745
4243
|
line: { color: badgeColor, width: 1.5 },
|
|
2746
4244
|
rectRadius: 0.15
|
|
2747
4245
|
});
|
|
2748
|
-
pptxSlide.addText(
|
|
4246
|
+
pptxSlide.addText(badgeText.toUpperCase(), {
|
|
2749
4247
|
x: rect.x,
|
|
2750
4248
|
y: rect.y,
|
|
2751
4249
|
w: badgeW,
|
|
@@ -2853,9 +4351,10 @@ var PptxRenderer = class {
|
|
|
2853
4351
|
align: "center"
|
|
2854
4352
|
});
|
|
2855
4353
|
}
|
|
4354
|
+
const cleanTitle = item.title;
|
|
2856
4355
|
const descText = item.description ? `
|
|
2857
4356
|
${item.description}` : "";
|
|
2858
|
-
pptxSlide.addText(`${
|
|
4357
|
+
pptxSlide.addText(`${cleanTitle}${descText}`, {
|
|
2859
4358
|
x: itemX + 0.05,
|
|
2860
4359
|
y: lineY + 0.45,
|
|
2861
4360
|
w: itemW - 0.1,
|
|
@@ -2879,7 +4378,7 @@ ${item.description}` : "";
|
|
|
2879
4378
|
w: colW,
|
|
2880
4379
|
h: rect.h,
|
|
2881
4380
|
fill: { color: this.cleanHexColor(theme.colors.surface) },
|
|
2882
|
-
line: { color: this.cleanHexColor(theme.colors.border), width: 1 },
|
|
4381
|
+
line: { color: this.cleanHexColor(theme.colors.border), width: 1.5 },
|
|
2883
4382
|
rectRadius: 0.1
|
|
2884
4383
|
});
|
|
2885
4384
|
if (compare.leftTitle) {
|
|
@@ -2888,34 +4387,244 @@ ${item.description}` : "";
|
|
|
2888
4387
|
y: rect.y + 0.15,
|
|
2889
4388
|
w: colW - 0.3,
|
|
2890
4389
|
h: 0.4,
|
|
2891
|
-
fontSize:
|
|
4390
|
+
fontSize: 15,
|
|
4391
|
+
bold: true,
|
|
4392
|
+
color: this.cleanHexColor(theme.colors.primary),
|
|
4393
|
+
fontFace: cleanFontFace(theme.typography.headingFont)
|
|
4394
|
+
});
|
|
4395
|
+
}
|
|
4396
|
+
const rightX = rect.x + colW + 0.4;
|
|
4397
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4398
|
+
x: rightX,
|
|
4399
|
+
y: rect.y,
|
|
4400
|
+
w: colW,
|
|
4401
|
+
h: rect.h,
|
|
4402
|
+
fill: { color: this.cleanHexColor(theme.colors.surface) },
|
|
4403
|
+
line: { color: this.cleanHexColor(theme.colors.border), width: 1.5 },
|
|
4404
|
+
rectRadius: 0.1
|
|
4405
|
+
});
|
|
4406
|
+
if (compare.rightTitle) {
|
|
4407
|
+
pptxSlide.addText(compare.rightTitle, {
|
|
4408
|
+
x: rightX + 0.15,
|
|
4409
|
+
y: rect.y + 0.15,
|
|
4410
|
+
w: colW - 0.3,
|
|
4411
|
+
h: 0.4,
|
|
4412
|
+
fontSize: 15,
|
|
2892
4413
|
bold: true,
|
|
2893
4414
|
color: this.cleanHexColor(theme.colors.primary),
|
|
2894
4415
|
fontFace: cleanFontFace(theme.typography.headingFont)
|
|
2895
4416
|
});
|
|
2896
4417
|
}
|
|
2897
|
-
const
|
|
2898
|
-
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
2899
|
-
x:
|
|
2900
|
-
y: rect.y,
|
|
2901
|
-
w:
|
|
2902
|
-
h:
|
|
2903
|
-
fill: { color: this.cleanHexColor(theme.colors.
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
4418
|
+
const vsX = rect.x + colW + 0.05;
|
|
4419
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4420
|
+
x: vsX,
|
|
4421
|
+
y: rect.y + rect.h / 2 - 0.18,
|
|
4422
|
+
w: 0.3,
|
|
4423
|
+
h: 0.3,
|
|
4424
|
+
fill: { color: this.cleanHexColor(theme.colors.border || "#334155") },
|
|
4425
|
+
rectRadius: 0.15
|
|
4426
|
+
});
|
|
4427
|
+
pptxSlide.addText("VS", {
|
|
4428
|
+
x: vsX,
|
|
4429
|
+
y: rect.y + rect.h / 2 - 0.18,
|
|
4430
|
+
w: 0.3,
|
|
4431
|
+
h: 0.3,
|
|
4432
|
+
fontSize: 10,
|
|
4433
|
+
bold: true,
|
|
4434
|
+
color: this.cleanHexColor(theme.colors.muted || "#94a3b8"),
|
|
4435
|
+
fontFace: cleanFontFace(theme.typography.headingFont),
|
|
4436
|
+
align: "center",
|
|
4437
|
+
valign: "middle"
|
|
4438
|
+
});
|
|
4439
|
+
}
|
|
4440
|
+
renderSection(pptxSlide, pptx, section, rect, theme) {
|
|
4441
|
+
const cardBg = this.cleanHexColor(theme.colors.surface || "#0f172a");
|
|
4442
|
+
const primaryHex = this.cleanHexColor(theme.colors.primary || "#00F0FF");
|
|
4443
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4444
|
+
x: rect.x,
|
|
4445
|
+
y: rect.y,
|
|
4446
|
+
w: rect.w,
|
|
4447
|
+
h: rect.h,
|
|
4448
|
+
fill: { color: cardBg },
|
|
4449
|
+
line: { color: primaryHex, width: 2 },
|
|
4450
|
+
rectRadius: 0.1
|
|
4451
|
+
});
|
|
4452
|
+
if (section.number !== void 0) {
|
|
4453
|
+
const numStr = String(section.number);
|
|
4454
|
+
const pillW = Math.min(2.4, Math.max(1.4, numStr.length * 0.15 + 0.8));
|
|
4455
|
+
const pillX = rect.x + (rect.w - pillW) / 2;
|
|
4456
|
+
const pillY = rect.y + 0.35;
|
|
4457
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4458
|
+
x: pillX,
|
|
4459
|
+
y: pillY,
|
|
4460
|
+
w: pillW,
|
|
4461
|
+
h: 0.36,
|
|
4462
|
+
fill: { color: primaryHex },
|
|
4463
|
+
rectRadius: 0.18
|
|
4464
|
+
});
|
|
4465
|
+
pptxSlide.addText(`SECTION ${numStr}`.toUpperCase(), {
|
|
4466
|
+
x: pillX,
|
|
4467
|
+
y: pillY,
|
|
4468
|
+
w: pillW,
|
|
4469
|
+
h: 0.36,
|
|
4470
|
+
fontSize: 11,
|
|
4471
|
+
bold: true,
|
|
4472
|
+
color: "000000",
|
|
4473
|
+
fontFace: cleanFontFace(theme.typography.headingFont),
|
|
4474
|
+
align: "center",
|
|
4475
|
+
valign: "middle"
|
|
4476
|
+
});
|
|
4477
|
+
}
|
|
4478
|
+
const titleY = section.number !== void 0 ? rect.y + 0.85 : rect.y + 0.45;
|
|
4479
|
+
pptxSlide.addText(section.title, {
|
|
4480
|
+
x: rect.x + 0.3,
|
|
4481
|
+
y: titleY,
|
|
4482
|
+
w: rect.w - 0.6,
|
|
4483
|
+
h: 0.85,
|
|
4484
|
+
fontSize: 28,
|
|
4485
|
+
bold: true,
|
|
4486
|
+
color: this.cleanHexColor(theme.colors.text || "#ffffff"),
|
|
4487
|
+
fontFace: cleanFontFace(theme.typography.headingFont),
|
|
4488
|
+
align: "center",
|
|
4489
|
+
valign: "middle"
|
|
4490
|
+
});
|
|
4491
|
+
if (section.subtitle) {
|
|
4492
|
+
pptxSlide.addText(section.subtitle, {
|
|
4493
|
+
x: rect.x + 0.4,
|
|
4494
|
+
y: titleY + 0.85,
|
|
4495
|
+
w: rect.w - 0.8,
|
|
4496
|
+
h: 0.55,
|
|
4497
|
+
fontSize: 15,
|
|
4498
|
+
color: this.cleanHexColor(theme.colors.muted || "#94a3b8"),
|
|
4499
|
+
fontFace: cleanFontFace(theme.typography.bodyFont),
|
|
4500
|
+
align: "center",
|
|
4501
|
+
valign: "top"
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
renderToc(pptxSlide, pptx, toc, rect, theme, presentation) {
|
|
4506
|
+
const items = toc.items ? [...toc.items] : [];
|
|
4507
|
+
if (items.length === 0 && presentation) {
|
|
4508
|
+
let autoIdx = 1;
|
|
4509
|
+
for (const s of presentation.slides) {
|
|
4510
|
+
for (const el of s.elements) {
|
|
4511
|
+
if (el.type === "section") {
|
|
4512
|
+
const sec = el;
|
|
4513
|
+
items.push({
|
|
4514
|
+
number: sec.number !== void 0 ? String(sec.number) : String(autoIdx++),
|
|
4515
|
+
title: sec.title,
|
|
4516
|
+
description: sec.subtitle
|
|
4517
|
+
});
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
if (items.length === 0) {
|
|
4522
|
+
presentation.slides.forEach((s, idx) => {
|
|
4523
|
+
const heading = s.elements.find((el) => el.type === "heading");
|
|
4524
|
+
if (heading) {
|
|
4525
|
+
items.push({
|
|
4526
|
+
number: String(idx + 1),
|
|
4527
|
+
title: heading.text
|
|
4528
|
+
});
|
|
4529
|
+
}
|
|
4530
|
+
});
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
if (items.length === 0)
|
|
4534
|
+
return;
|
|
4535
|
+
const primaryHex = this.cleanHexColor(theme.colors.primary || "#00F0FF");
|
|
4536
|
+
const surfaceHex = this.cleanHexColor(theme.colors.surface || "#0f172a");
|
|
4537
|
+
const borderHex = this.cleanHexColor(theme.colors.border || "#334155");
|
|
4538
|
+
const textHex = this.cleanHexColor(theme.colors.text || "#ffffff");
|
|
4539
|
+
const mutedHex = this.cleanHexColor(theme.colors.muted || "#94a3b8");
|
|
4540
|
+
let currentY = rect.y;
|
|
4541
|
+
if (toc.title) {
|
|
4542
|
+
pptxSlide.addText(toc.title, {
|
|
4543
|
+
x: rect.x,
|
|
4544
|
+
y: currentY,
|
|
4545
|
+
w: rect.w,
|
|
4546
|
+
h: 0.5,
|
|
4547
|
+
fontSize: 22,
|
|
2914
4548
|
bold: true,
|
|
2915
|
-
color:
|
|
4549
|
+
color: primaryHex,
|
|
2916
4550
|
fontFace: cleanFontFace(theme.typography.headingFont)
|
|
2917
4551
|
});
|
|
4552
|
+
currentY += 0.65;
|
|
2918
4553
|
}
|
|
4554
|
+
const availableH = rect.h - (currentY - rect.y);
|
|
4555
|
+
const cols = items.length > 4 ? 2 : 1;
|
|
4556
|
+
const rows = Math.ceil(items.length / cols);
|
|
4557
|
+
const colW = (rect.w - (cols - 1) * 0.3) / cols;
|
|
4558
|
+
const itemH = Math.min(0.85, (availableH - (rows - 1) * 0.12) / rows);
|
|
4559
|
+
items.forEach((item, idx) => {
|
|
4560
|
+
const c = idx % cols;
|
|
4561
|
+
const r = Math.floor(idx / cols);
|
|
4562
|
+
const itemX = rect.x + c * (colW + 0.3);
|
|
4563
|
+
const itemY = currentY + r * (itemH + 0.12);
|
|
4564
|
+
const num = item.number !== void 0 ? String(item.number) : String(idx + 1);
|
|
4565
|
+
const descText = item.description || item.subtitle;
|
|
4566
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4567
|
+
x: itemX,
|
|
4568
|
+
y: itemY,
|
|
4569
|
+
w: colW,
|
|
4570
|
+
h: itemH,
|
|
4571
|
+
fill: { color: surfaceHex },
|
|
4572
|
+
line: { color: borderHex, width: 1 },
|
|
4573
|
+
rectRadius: 0.08
|
|
4574
|
+
});
|
|
4575
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
4576
|
+
x: itemX + 0.12,
|
|
4577
|
+
y: itemY + (itemH - 0.36) / 2,
|
|
4578
|
+
w: 0.36,
|
|
4579
|
+
h: 0.36,
|
|
4580
|
+
fill: { color: primaryHex },
|
|
4581
|
+
rectRadius: 0.08
|
|
4582
|
+
});
|
|
4583
|
+
pptxSlide.addText(num, {
|
|
4584
|
+
x: itemX + 0.12,
|
|
4585
|
+
y: itemY + (itemH - 0.36) / 2,
|
|
4586
|
+
w: 0.36,
|
|
4587
|
+
h: 0.36,
|
|
4588
|
+
fontSize: 11,
|
|
4589
|
+
bold: true,
|
|
4590
|
+
color: "000000",
|
|
4591
|
+
fontFace: cleanFontFace(theme.typography.headingFont),
|
|
4592
|
+
align: "center",
|
|
4593
|
+
valign: "middle"
|
|
4594
|
+
});
|
|
4595
|
+
const textX = itemX + 0.55;
|
|
4596
|
+
const textW = colW - 0.65;
|
|
4597
|
+
const titleChunks = [
|
|
4598
|
+
{
|
|
4599
|
+
text: item.title,
|
|
4600
|
+
options: {
|
|
4601
|
+
fontSize: 13,
|
|
4602
|
+
bold: true,
|
|
4603
|
+
color: textHex,
|
|
4604
|
+
fontFace: cleanFontFace(theme.typography.headingFont),
|
|
4605
|
+
breakLine: Boolean(descText)
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
];
|
|
4609
|
+
if (descText) {
|
|
4610
|
+
titleChunks.push({
|
|
4611
|
+
text: descText,
|
|
4612
|
+
options: {
|
|
4613
|
+
fontSize: 10,
|
|
4614
|
+
color: mutedHex,
|
|
4615
|
+
fontFace: cleanFontFace(theme.typography.bodyFont)
|
|
4616
|
+
}
|
|
4617
|
+
});
|
|
4618
|
+
}
|
|
4619
|
+
pptxSlide.addText(titleChunks, {
|
|
4620
|
+
x: textX,
|
|
4621
|
+
y: itemY + 0.06,
|
|
4622
|
+
w: textW,
|
|
4623
|
+
h: itemH - 0.12,
|
|
4624
|
+
valign: "middle",
|
|
4625
|
+
margin: 0
|
|
4626
|
+
});
|
|
4627
|
+
});
|
|
2919
4628
|
}
|
|
2920
4629
|
renderMermaid(pptxSlide, pptx, mermaid, rect, theme) {
|
|
2921
4630
|
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
@@ -3076,7 +4785,9 @@ var HtmlRenderer = class {
|
|
|
3076
4785
|
})();
|
|
3077
4786
|
</script>
|
|
3078
4787
|
` : "";
|
|
3079
|
-
const slidesHtml = presentation.slides.map((slide, idx) => this.renderSlide(slide, idx + 1, presentation.slides.length, theme)).join("\n");
|
|
4788
|
+
const slidesHtml = presentation.slides.map((slide, idx) => this.renderSlide(slide, idx + 1, presentation.slides.length, theme, presentation.metadata.watermark, presentation)).join("\n");
|
|
4789
|
+
const customStyles = presentation.metadata.styles ? (Array.isArray(presentation.metadata.styles) ? presentation.metadata.styles : [presentation.metadata.styles]).map((url) => `<link rel="stylesheet" href="${url}">`).join("\n ") : "";
|
|
4790
|
+
const customScripts = presentation.metadata.scripts ? (Array.isArray(presentation.metadata.scripts) ? presentation.metadata.scripts : [presentation.metadata.scripts]).map((url) => `<script src="${url}"></script>`).join("\n ") : "";
|
|
3080
4791
|
const html = `<!DOCTYPE html>
|
|
3081
4792
|
<html lang="en">
|
|
3082
4793
|
<head>
|
|
@@ -3085,6 +4796,11 @@ var HtmlRenderer = class {
|
|
|
3085
4796
|
<title>${this.escapeHtml(title)}</title>
|
|
3086
4797
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
3087
4798
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
4799
|
+
${customStyles}
|
|
4800
|
+
${customScripts}
|
|
4801
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" crossorigin="anonymous">
|
|
4802
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" crossorigin="anonymous"></script>
|
|
4803
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" crossorigin="anonymous"></script>
|
|
3088
4804
|
<script type="module">
|
|
3089
4805
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
|
3090
4806
|
try {
|
|
@@ -3246,9 +4962,6 @@ var HtmlRenderer = class {
|
|
|
3246
4962
|
margin-bottom: 0.8em;
|
|
3247
4963
|
overflow-wrap: break-word;
|
|
3248
4964
|
}
|
|
3249
|
-
color: var(--yumia-text);
|
|
3250
|
-
margin-bottom: 0.8em;
|
|
3251
|
-
}
|
|
3252
4965
|
|
|
3253
4966
|
p strong, li strong {
|
|
3254
4967
|
color: var(--yumia-primary);
|
|
@@ -3470,7 +5183,7 @@ var HtmlRenderer = class {
|
|
|
3470
5183
|
padding: 6px 14px;
|
|
3471
5184
|
border-radius: 30px;
|
|
3472
5185
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
3473
|
-
z-index:
|
|
5186
|
+
z-index: 2500;
|
|
3474
5187
|
font-size: 13px;
|
|
3475
5188
|
color: #e2e8f0;
|
|
3476
5189
|
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5);
|
|
@@ -3685,20 +5398,40 @@ var HtmlRenderer = class {
|
|
|
3685
5398
|
border: 1.5px solid var(--yumia-border);
|
|
3686
5399
|
border-left: 4px solid var(--yumia-primary);
|
|
3687
5400
|
border-radius: var(--yumia-radius-card);
|
|
3688
|
-
padding: 1.
|
|
3689
|
-
margin:
|
|
5401
|
+
padding: 0.75rem 1.4rem;
|
|
5402
|
+
margin: 0.7rem 0;
|
|
3690
5403
|
display: flex;
|
|
3691
5404
|
align-items: center;
|
|
3692
5405
|
justify-content: center;
|
|
3693
5406
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25);
|
|
5407
|
+
overflow-x: auto;
|
|
5408
|
+
max-width: 100%;
|
|
3694
5409
|
}
|
|
3695
5410
|
|
|
3696
5411
|
.yumia-math-equation {
|
|
3697
|
-
font-
|
|
3698
|
-
font-size: clamp(1.2rem, 2.2vw, 1.8rem);
|
|
3699
|
-
font-style: italic;
|
|
5412
|
+
font-size: clamp(1.1rem, 1.8vw, 1.45rem);
|
|
3700
5413
|
color: var(--yumia-text);
|
|
3701
|
-
letter-spacing: 0.
|
|
5414
|
+
letter-spacing: 0.03em;
|
|
5415
|
+
}
|
|
5416
|
+
|
|
5417
|
+
/* Watermark Branding */
|
|
5418
|
+
.yumia-watermark {
|
|
5419
|
+
position: absolute;
|
|
5420
|
+
bottom: 12px;
|
|
5421
|
+
left: 20px;
|
|
5422
|
+
font-size: 11px;
|
|
5423
|
+
font-weight: 600;
|
|
5424
|
+
letter-spacing: 0.08em;
|
|
5425
|
+
text-transform: uppercase;
|
|
5426
|
+
color: var(--yumia-muted);
|
|
5427
|
+
opacity: 0.35;
|
|
5428
|
+
pointer-events: none;
|
|
5429
|
+
user-select: none;
|
|
5430
|
+
z-index: 10;
|
|
5431
|
+
transition: opacity 0.2s ease;
|
|
5432
|
+
}
|
|
5433
|
+
.yumia-slide-wrapper:hover .yumia-watermark {
|
|
5434
|
+
opacity: 0.65;
|
|
3702
5435
|
}
|
|
3703
5436
|
|
|
3704
5437
|
/* Slide Transitions */
|
|
@@ -3728,17 +5461,177 @@ var HtmlRenderer = class {
|
|
|
3728
5461
|
to { opacity: 1; transform: scale(1); }
|
|
3729
5462
|
}
|
|
3730
5463
|
|
|
3731
|
-
/*
|
|
3732
|
-
.yumia-
|
|
3733
|
-
|
|
5464
|
+
/* Code Block Line Highlighting & Numbers */
|
|
5465
|
+
.yumia-code-block {
|
|
5466
|
+
display: block;
|
|
5467
|
+
padding: 0.75rem 0;
|
|
5468
|
+
font-family: var(--yumia-font-code);
|
|
5469
|
+
font-size: 0.95rem;
|
|
5470
|
+
line-height: 1.6;
|
|
5471
|
+
overflow-x: auto;
|
|
5472
|
+
border-radius: var(--yumia-radius-card);
|
|
5473
|
+
background: rgba(10, 15, 30, 0.88);
|
|
5474
|
+
border: 1.5px solid var(--yumia-border);
|
|
5475
|
+
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.35);
|
|
5476
|
+
margin: 0.8rem 0;
|
|
5477
|
+
}
|
|
5478
|
+
.yumia-code-block code {
|
|
5479
|
+
display: block;
|
|
5480
|
+
padding: 0;
|
|
5481
|
+
background: transparent;
|
|
5482
|
+
border: none;
|
|
5483
|
+
}
|
|
5484
|
+
.yumia-code-line {
|
|
5485
|
+
display: flex;
|
|
5486
|
+
align-items: center;
|
|
5487
|
+
min-height: 1.6em;
|
|
5488
|
+
padding: 0 1rem;
|
|
5489
|
+
transition: background 0.15s ease, opacity 0.15s ease;
|
|
3734
5490
|
}
|
|
3735
|
-
.yumia-
|
|
3736
|
-
opacity: 0.
|
|
3737
|
-
transform: translateY(4px);
|
|
5491
|
+
.yumia-code-line.dimmed {
|
|
5492
|
+
opacity: 0.35;
|
|
3738
5493
|
}
|
|
3739
|
-
.yumia-
|
|
5494
|
+
.yumia-code-line.highlighted {
|
|
5495
|
+
background: rgba(0, 240, 255, 0.16);
|
|
5496
|
+
border-left: 3.5px solid var(--yumia-primary);
|
|
3740
5497
|
opacity: 1;
|
|
3741
|
-
|
|
5498
|
+
font-weight: 600;
|
|
5499
|
+
}
|
|
5500
|
+
.yumia-code-line .line-num {
|
|
5501
|
+
user-select: none;
|
|
5502
|
+
width: 28px;
|
|
5503
|
+
margin-right: 14px;
|
|
5504
|
+
color: rgba(255, 255, 255, 0.3);
|
|
5505
|
+
font-size: 0.8rem;
|
|
5506
|
+
text-align: right;
|
|
5507
|
+
}
|
|
5508
|
+
.yumia-code-line .line-text {
|
|
5509
|
+
flex: 1;
|
|
5510
|
+
}
|
|
5511
|
+
|
|
5512
|
+
/* Section Divider Card */
|
|
5513
|
+
.yumia-section-card {
|
|
5514
|
+
display: flex;
|
|
5515
|
+
flex-direction: column;
|
|
5516
|
+
align-items: center;
|
|
5517
|
+
justify-content: center;
|
|
5518
|
+
text-align: center;
|
|
5519
|
+
padding: 3rem 2rem;
|
|
5520
|
+
margin: auto 0;
|
|
5521
|
+
background: radial-gradient(circle at center, rgba(0, 240, 255, 0.12) 0%, rgba(15, 23, 42, 0.6) 100%);
|
|
5522
|
+
border: 1.5px solid var(--yumia-primary);
|
|
5523
|
+
border-radius: var(--yumia-radius-card);
|
|
5524
|
+
box-shadow: 0 12px 35px rgba(0, 0, 0, 0.5), 0 0 20px rgba(0, 240, 255, 0.2);
|
|
5525
|
+
width: 100%;
|
|
5526
|
+
}
|
|
5527
|
+
.yumia-section-pill {
|
|
5528
|
+
display: inline-flex;
|
|
5529
|
+
align-items: center;
|
|
5530
|
+
padding: 4px 14px;
|
|
5531
|
+
border-radius: 999px;
|
|
5532
|
+
background: var(--yumia-primary);
|
|
5533
|
+
color: #000;
|
|
5534
|
+
font-weight: 800;
|
|
5535
|
+
font-size: 0.85rem;
|
|
5536
|
+
letter-spacing: 0.08em;
|
|
5537
|
+
text-transform: uppercase;
|
|
5538
|
+
margin-bottom: 1.2rem;
|
|
5539
|
+
}
|
|
5540
|
+
.yumia-section-title {
|
|
5541
|
+
font-size: clamp(2rem, 3.5vw, 3rem);
|
|
5542
|
+
font-weight: 800;
|
|
5543
|
+
color: var(--yumia-text);
|
|
5544
|
+
margin-bottom: 0.8rem;
|
|
5545
|
+
line-height: 1.2;
|
|
5546
|
+
}
|
|
5547
|
+
.yumia-section-subtitle {
|
|
5548
|
+
font-size: 1.15rem;
|
|
5549
|
+
color: var(--yumia-muted);
|
|
5550
|
+
max-width: 650px;
|
|
5551
|
+
}
|
|
5552
|
+
|
|
5553
|
+
/* Table of Contents Grid */
|
|
5554
|
+
.yumia-toc-grid {
|
|
5555
|
+
display: grid;
|
|
5556
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
5557
|
+
gap: 16px;
|
|
5558
|
+
width: 100%;
|
|
5559
|
+
margin: 1.2rem 0;
|
|
5560
|
+
}
|
|
5561
|
+
.yumia-toc-item {
|
|
5562
|
+
display: flex;
|
|
5563
|
+
align-items: center;
|
|
5564
|
+
gap: 14px;
|
|
5565
|
+
background: var(--yumia-surface);
|
|
5566
|
+
border: 1.5px solid var(--yumia-border);
|
|
5567
|
+
border-radius: 10px;
|
|
5568
|
+
padding: 14px 18px;
|
|
5569
|
+
transition: transform 0.2s ease, border-color 0.2s ease;
|
|
5570
|
+
}
|
|
5571
|
+
.yumia-toc-item:hover {
|
|
5572
|
+
transform: translateX(4px);
|
|
5573
|
+
border-color: var(--yumia-primary);
|
|
5574
|
+
}
|
|
5575
|
+
.yumia-toc-num {
|
|
5576
|
+
display: flex;
|
|
5577
|
+
align-items: center;
|
|
5578
|
+
justify-content: center;
|
|
5579
|
+
width: 34px;
|
|
5580
|
+
height: 34px;
|
|
5581
|
+
border-radius: 8px;
|
|
5582
|
+
background: rgba(0, 240, 255, 0.15);
|
|
5583
|
+
color: var(--yumia-primary);
|
|
5584
|
+
font-weight: 800;
|
|
5585
|
+
font-size: 0.95rem;
|
|
5586
|
+
}
|
|
5587
|
+
.yumia-toc-title {
|
|
5588
|
+
font-weight: 600;
|
|
5589
|
+
font-size: 1.05rem;
|
|
5590
|
+
color: var(--yumia-text);
|
|
5591
|
+
}
|
|
5592
|
+
|
|
5593
|
+
/* Print & Export Media Styles */
|
|
5594
|
+
@media print {
|
|
5595
|
+
@page {
|
|
5596
|
+
size: landscape;
|
|
5597
|
+
margin: 0;
|
|
5598
|
+
}
|
|
5599
|
+
body {
|
|
5600
|
+
background: #0f172a !important;
|
|
5601
|
+
color: #f8fafc !important;
|
|
5602
|
+
overflow: visible !important;
|
|
5603
|
+
-webkit-print-color-adjust: exact !important;
|
|
5604
|
+
print-color-adjust: exact !important;
|
|
5605
|
+
}
|
|
5606
|
+
#deck-container {
|
|
5607
|
+
display: block !important;
|
|
5608
|
+
width: 100% !important;
|
|
5609
|
+
height: auto !important;
|
|
5610
|
+
}
|
|
5611
|
+
#yumia-deck {
|
|
5612
|
+
display: block !important;
|
|
5613
|
+
position: static !important;
|
|
5614
|
+
width: 100% !important;
|
|
5615
|
+
height: auto !important;
|
|
5616
|
+
}
|
|
5617
|
+
.yumia-slide-wrapper {
|
|
5618
|
+
display: flex !important;
|
|
5619
|
+
page-break-after: always !important;
|
|
5620
|
+
break-after: page !important;
|
|
5621
|
+
page-break-inside: avoid !important;
|
|
5622
|
+
position: relative !important;
|
|
5623
|
+
width: 100vw !important;
|
|
5624
|
+
height: 100vh !important;
|
|
5625
|
+
min-height: 100vh !important;
|
|
5626
|
+
margin: 0 !important;
|
|
5627
|
+
box-shadow: none !important;
|
|
5628
|
+
opacity: 1 !important;
|
|
5629
|
+
visibility: visible !important;
|
|
5630
|
+
transform: none !important;
|
|
5631
|
+
}
|
|
5632
|
+
.yumia-controls, .yumia-notes-drawer, .yumia-overview-modal, .yumia-progress-bar {
|
|
5633
|
+
display: none !important;
|
|
5634
|
+
}
|
|
3742
5635
|
}
|
|
3743
5636
|
|
|
3744
5637
|
/* Notes Drawer */
|
|
@@ -3747,11 +5640,11 @@ var HtmlRenderer = class {
|
|
|
3747
5640
|
bottom: 0;
|
|
3748
5641
|
left: 0;
|
|
3749
5642
|
right: 0;
|
|
3750
|
-
max-height:
|
|
5643
|
+
max-height: 260px;
|
|
3751
5644
|
background: rgba(10, 10, 18, 0.96);
|
|
3752
5645
|
backdrop-filter: blur(16px);
|
|
3753
5646
|
border-top: 2px solid var(--yumia-primary);
|
|
3754
|
-
padding: 18px
|
|
5647
|
+
padding: 14px 24px 18px 24px;
|
|
3755
5648
|
overflow-y: auto;
|
|
3756
5649
|
display: none;
|
|
3757
5650
|
z-index: 2000;
|
|
@@ -3765,6 +5658,22 @@ var HtmlRenderer = class {
|
|
|
3765
5658
|
display: block;
|
|
3766
5659
|
}
|
|
3767
5660
|
|
|
5661
|
+
.yumia-notes-header {
|
|
5662
|
+
display: flex;
|
|
5663
|
+
justify-content: space-between;
|
|
5664
|
+
align-items: center;
|
|
5665
|
+
margin-bottom: 8px;
|
|
5666
|
+
padding-bottom: 6px;
|
|
5667
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
5668
|
+
font-weight: 700;
|
|
5669
|
+
font-size: 14px;
|
|
5670
|
+
color: var(--yumia-primary);
|
|
5671
|
+
}
|
|
5672
|
+
|
|
5673
|
+
.yumia-notes-content {
|
|
5674
|
+
padding-right: 200px;
|
|
5675
|
+
}
|
|
5676
|
+
|
|
3768
5677
|
/* Slide Overview Modal */
|
|
3769
5678
|
.yumia-overview-modal {
|
|
3770
5679
|
position: fixed;
|
|
@@ -3952,11 +5861,18 @@ var HtmlRenderer = class {
|
|
|
3952
5861
|
<button class="yumia-btn" id="btn-next" title="Next Slide (\u2192)">\u25B6</button>
|
|
3953
5862
|
<button class="yumia-btn" id="btn-overview" title="Slide Overview (ESC / O)">\u25A6</button>
|
|
3954
5863
|
<button class="yumia-btn" id="btn-speaker" title="Speaker View (S)">\u{1F3A4}</button>
|
|
5864
|
+
<button class="yumia-btn" id="btn-print" title="Stampa / Salva PDF (Ctrl+P)">\u{1F5A8}\uFE0F</button>
|
|
3955
5865
|
<button class="yumia-btn" id="btn-notes" title="Toggle Notes (N)">\u{1F4DD}</button>
|
|
3956
5866
|
<button class="yumia-btn" id="btn-fs" title="Fullscreen (F)">\u26F6</button>
|
|
3957
5867
|
</div>
|
|
3958
5868
|
|
|
3959
|
-
<div id="notes-drawer" class="yumia-notes-drawer"
|
|
5869
|
+
<div id="notes-drawer" class="yumia-notes-drawer">
|
|
5870
|
+
<div class="yumia-notes-header">
|
|
5871
|
+
<span>\u{1F4DD} Speaker Notes</span>
|
|
5872
|
+
<button class="yumia-btn" id="btn-close-notes" title="Close Notes (N / ESC)" style="font-size: 13px; padding: 2px 8px; border: 1px solid rgba(255,255,255,0.2);">\u2715 Close</button>
|
|
5873
|
+
</div>
|
|
5874
|
+
<div id="notes-drawer-content" class="yumia-notes-content"></div>
|
|
5875
|
+
</div>
|
|
3960
5876
|
|
|
3961
5877
|
<div id="overview-modal" class="yumia-overview-modal">
|
|
3962
5878
|
<div class="yumia-overview-header">
|
|
@@ -4043,8 +5959,9 @@ var HtmlRenderer = class {
|
|
|
4043
5959
|
|
|
4044
5960
|
const currentSlide = slides[currentIdx];
|
|
4045
5961
|
const notes = currentSlide ? currentSlide.getAttribute('data-notes') : '';
|
|
4046
|
-
|
|
4047
|
-
|
|
5962
|
+
const notesContent = document.getElementById('notes-drawer-content');
|
|
5963
|
+
if (notesContent) {
|
|
5964
|
+
notesContent.innerHTML = notes ? notes : '<em>No speaker notes for this slide.</em>';
|
|
4048
5965
|
}
|
|
4049
5966
|
|
|
4050
5967
|
window.location.hash = '#' + (currentIdx + 1);
|
|
@@ -4057,9 +5974,40 @@ var HtmlRenderer = class {
|
|
|
4057
5974
|
if (window.renderMermaidInSlide && slides[currentIdx]) {
|
|
4058
5975
|
window.renderMermaidInSlide(slides[currentIdx]);
|
|
4059
5976
|
}
|
|
5977
|
+
if (slides[currentIdx]) {
|
|
5978
|
+
renderMathInSlide(slides[currentIdx]);
|
|
5979
|
+
}
|
|
4060
5980
|
}, 50);
|
|
4061
5981
|
}
|
|
4062
5982
|
|
|
5983
|
+
function renderMathInSlide(slideEl) {
|
|
5984
|
+
if (!slideEl) return;
|
|
5985
|
+
if (window.renderMathInElement) {
|
|
5986
|
+
try {
|
|
5987
|
+
window.renderMathInElement(slideEl, {
|
|
5988
|
+
delimiters: [
|
|
5989
|
+
{ left: '$$', right: '$$', display: true }
|
|
5990
|
+
],
|
|
5991
|
+
throwOnError: false
|
|
5992
|
+
});
|
|
5993
|
+
} catch (e) {
|
|
5994
|
+
console.warn('KaTeX auto-render notice:', e);
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5997
|
+
if (window.katex) {
|
|
5998
|
+
slideEl.querySelectorAll('.yumia-math-equation:not([data-katex="true"])').forEach(function(el) {
|
|
5999
|
+
try {
|
|
6000
|
+
const rawExpr =
|
|
6001
|
+
el.getAttribute('data-expr') || el.textContent.replace(/^[$]{2}|[$]{2}$/g, '').trim();
|
|
6002
|
+
window.katex.render(rawExpr, el, { displayMode: true, throwOnError: false });
|
|
6003
|
+
el.setAttribute('data-katex', 'true');
|
|
6004
|
+
} catch (err) {
|
|
6005
|
+
console.warn('KaTeX equation render notice:', err);
|
|
6006
|
+
}
|
|
6007
|
+
});
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
6010
|
+
|
|
4063
6011
|
function openSpeakerWindow() {
|
|
4064
6012
|
const url = new URL(window.location.href);
|
|
4065
6013
|
url.searchParams.set('speaker', 'true');
|
|
@@ -4208,8 +6156,15 @@ var HtmlRenderer = class {
|
|
|
4208
6156
|
const hash = window.location.hash.replace('#', '');
|
|
4209
6157
|
const initialIdx = parseInt(hash, 10) - 1;
|
|
4210
6158
|
goToSlide(isNaN(initialIdx) ? 0 : initialIdx, false);
|
|
6159
|
+
setTimeout(() => {
|
|
6160
|
+
slides.forEach(renderMathInSlide);
|
|
6161
|
+
}, 100);
|
|
4211
6162
|
}
|
|
4212
6163
|
|
|
6164
|
+
window.addEventListener('load', () => {
|
|
6165
|
+
slides.forEach(renderMathInSlide);
|
|
6166
|
+
});
|
|
6167
|
+
|
|
4213
6168
|
window.deckController = {
|
|
4214
6169
|
init: init,
|
|
4215
6170
|
next: function() { goToSlide(currentIdx + 1); },
|
|
@@ -4217,6 +6172,7 @@ var HtmlRenderer = class {
|
|
|
4217
6172
|
toggleNotes: function() { notesDrawer?.classList.toggle('open'); },
|
|
4218
6173
|
toggleOverview: function() { toggleOverview(); },
|
|
4219
6174
|
openSpeaker: openSpeakerWindow,
|
|
6175
|
+
print: function() { window.print(); },
|
|
4220
6176
|
toggleFs: function() {
|
|
4221
6177
|
if (!document.fullscreenElement) {
|
|
4222
6178
|
document.documentElement.requestFullscreen().catch(() => {});
|
|
@@ -4229,9 +6185,13 @@ var HtmlRenderer = class {
|
|
|
4229
6185
|
document.getElementById('btn-next')?.addEventListener('click', window.deckController.next);
|
|
4230
6186
|
document.getElementById('btn-prev')?.addEventListener('click', window.deckController.prev);
|
|
4231
6187
|
document.getElementById('btn-notes')?.addEventListener('click', window.deckController.toggleNotes);
|
|
6188
|
+
document.getElementById('btn-close-notes')?.addEventListener('click', () => {
|
|
6189
|
+
notesDrawer?.classList.remove('open');
|
|
6190
|
+
});
|
|
4232
6191
|
document.getElementById('btn-overview')?.addEventListener('click', window.deckController.toggleOverview);
|
|
4233
6192
|
document.getElementById('btn-close-overview')?.addEventListener('click', () => toggleOverview(false));
|
|
4234
6193
|
document.getElementById('btn-speaker')?.addEventListener('click', window.deckController.openSpeaker);
|
|
6194
|
+
document.getElementById('btn-print')?.addEventListener('click', window.deckController.print);
|
|
4235
6195
|
document.getElementById('btn-fs')?.addEventListener('click', window.deckController.toggleFs);
|
|
4236
6196
|
|
|
4237
6197
|
window.addEventListener('keydown', function(e) {
|
|
@@ -4242,6 +6202,18 @@ var HtmlRenderer = class {
|
|
|
4242
6202
|
return;
|
|
4243
6203
|
}
|
|
4244
6204
|
|
|
6205
|
+
if (e.key === 'Escape') {
|
|
6206
|
+
if (notesDrawer && notesDrawer.classList.contains('open')) {
|
|
6207
|
+
notesDrawer.classList.remove('open');
|
|
6208
|
+
return;
|
|
6209
|
+
}
|
|
6210
|
+
}
|
|
6211
|
+
|
|
6212
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'p') {
|
|
6213
|
+
// let default browser print work or call print explicitly
|
|
6214
|
+
return;
|
|
6215
|
+
}
|
|
6216
|
+
|
|
4245
6217
|
if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'PageDown' || e.key.toLowerCase() === 'l') {
|
|
4246
6218
|
e.preventDefault();
|
|
4247
6219
|
window.deckController.next();
|
|
@@ -4252,6 +6224,8 @@ var HtmlRenderer = class {
|
|
|
4252
6224
|
window.deckController.toggleFs();
|
|
4253
6225
|
} else if (e.key.toLowerCase() === 's') {
|
|
4254
6226
|
window.deckController.openSpeaker();
|
|
6227
|
+
} else if (e.key.toLowerCase() === 'p') {
|
|
6228
|
+
window.deckController.print();
|
|
4255
6229
|
} else if (e.key.toLowerCase() === 'n') {
|
|
4256
6230
|
window.deckController.toggleNotes();
|
|
4257
6231
|
} else if (e.key === 'Escape' || e.key.toLowerCase() === 'o') {
|
|
@@ -4282,21 +6256,25 @@ var HtmlRenderer = class {
|
|
|
4282
6256
|
slideCount: presentation.slides.length
|
|
4283
6257
|
};
|
|
4284
6258
|
}
|
|
4285
|
-
renderSlide(slide, slideNum, totalSlides, theme) {
|
|
6259
|
+
renderSlide(slide, slideNum, totalSlides, theme, watermarkOpt, presentation) {
|
|
4286
6260
|
const activeClass = slideNum === 1 ? "active" : "";
|
|
4287
6261
|
const notesAttr = slide.notes ? this.escapeHtml(slide.notes.replace(/\n/g, "<br>")) : "";
|
|
4288
6262
|
const progressPercent = Math.round(slideNum / totalSlides * 100);
|
|
4289
6263
|
const transition = slide.transition || "fade";
|
|
4290
6264
|
const transType = typeof transition === "string" ? transition : transition.type;
|
|
4291
6265
|
const transClass = `transition-${transType || "fade"}`;
|
|
4292
|
-
const
|
|
6266
|
+
const isWatermarkEnabled = watermarkOpt !== false;
|
|
6267
|
+
const watermarkText = typeof watermarkOpt === "string" && watermarkOpt.trim().length > 0 ? watermarkOpt : "YumiaMD";
|
|
6268
|
+
const watermarkHtml = isWatermarkEnabled ? `<div class="yumia-watermark">${this.escapeHtml(watermarkText)}</div>` : "";
|
|
6269
|
+
const elementsHtml = slide.elements.map((el) => this.renderElement(el, theme, presentation)).join("\n");
|
|
4293
6270
|
return `
|
|
4294
6271
|
<div class="yumia-slide-wrapper ${activeClass} ${transClass}" id="slide-${slideNum}" data-notes="${notesAttr}">
|
|
4295
6272
|
${elementsHtml}
|
|
6273
|
+
${watermarkHtml}
|
|
4296
6274
|
<div class="yumia-progress-bar" style="width: ${progressPercent}%;"></div>
|
|
4297
6275
|
</div>`;
|
|
4298
6276
|
}
|
|
4299
|
-
renderElement(element, theme) {
|
|
6277
|
+
renderElement(element, theme, presentation) {
|
|
4300
6278
|
switch (element.type) {
|
|
4301
6279
|
case "heading": {
|
|
4302
6280
|
const h = element;
|
|
@@ -4316,8 +6294,100 @@ var HtmlRenderer = class {
|
|
|
4316
6294
|
case "code": {
|
|
4317
6295
|
const c = element;
|
|
4318
6296
|
const langClass = c.language ? `class="language-${c.language}"` : "";
|
|
6297
|
+
const lines = c.code.split("\n");
|
|
6298
|
+
if (c.highlight) {
|
|
6299
|
+
const highlightSet = /* @__PURE__ */ new Set();
|
|
6300
|
+
const parts = c.highlight.split(",");
|
|
6301
|
+
for (const part of parts) {
|
|
6302
|
+
const trimmed = part.trim();
|
|
6303
|
+
if (!trimmed)
|
|
6304
|
+
continue;
|
|
6305
|
+
if (trimmed.includes("-")) {
|
|
6306
|
+
const [startStr, endStr] = trimmed.split("-");
|
|
6307
|
+
const start = parseInt(startStr || "0", 10);
|
|
6308
|
+
const end = parseInt(endStr || "0", 10);
|
|
6309
|
+
if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
6310
|
+
for (let n = start; n <= end; n++)
|
|
6311
|
+
highlightSet.add(n);
|
|
6312
|
+
}
|
|
6313
|
+
} else {
|
|
6314
|
+
const num = parseInt(trimmed, 10);
|
|
6315
|
+
if (!isNaN(num))
|
|
6316
|
+
highlightSet.add(num);
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
const linesHtml = lines.map((line, idx) => {
|
|
6320
|
+
const lineNum = idx + 1;
|
|
6321
|
+
const isHl = highlightSet.has(lineNum);
|
|
6322
|
+
const hlClass = isHl ? "highlighted" : "dimmed";
|
|
6323
|
+
return `<div class="yumia-code-line ${hlClass}"><span class="line-num">${lineNum}</span><span class="line-text">${this.escapeHtml(line) || " "}</span></div>`;
|
|
6324
|
+
}).join("");
|
|
6325
|
+
return `<pre class="yumia-code-block"><code ${langClass}>${linesHtml}</code></pre>`;
|
|
6326
|
+
}
|
|
4319
6327
|
return `<pre><code ${langClass}>${this.escapeHtml(c.code)}</code></pre>`;
|
|
4320
6328
|
}
|
|
6329
|
+
case "section": {
|
|
6330
|
+
const s = element;
|
|
6331
|
+
const numStr = s.number !== void 0 ? `<div class="yumia-section-pill">SECTION ${this.escapeHtml(String(s.number))}</div>` : "";
|
|
6332
|
+
const subStr = s.subtitle ? `<div class="yumia-section-subtitle">${this.formatInline(s.subtitle)}</div>` : "";
|
|
6333
|
+
return `
|
|
6334
|
+
<div class="yumia-section-card">
|
|
6335
|
+
${numStr}
|
|
6336
|
+
<div class="yumia-section-title">${this.formatInline(s.title)}</div>
|
|
6337
|
+
${subStr}
|
|
6338
|
+
</div>`;
|
|
6339
|
+
}
|
|
6340
|
+
case "toc": {
|
|
6341
|
+
const t = element;
|
|
6342
|
+
const items = t.items ? [...t.items] : [];
|
|
6343
|
+
if (items.length === 0 && presentation) {
|
|
6344
|
+
let autoSecIdx = 1;
|
|
6345
|
+
for (const s of presentation.slides) {
|
|
6346
|
+
for (const el of s.elements) {
|
|
6347
|
+
if (el.type === "section") {
|
|
6348
|
+
const sec = el;
|
|
6349
|
+
items.push({
|
|
6350
|
+
number: sec.number !== void 0 ? String(sec.number) : String(autoSecIdx++),
|
|
6351
|
+
title: sec.title,
|
|
6352
|
+
description: sec.subtitle
|
|
6353
|
+
});
|
|
6354
|
+
}
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
if (items.length === 0) {
|
|
6358
|
+
presentation.slides.forEach((s, idx) => {
|
|
6359
|
+
const heading = s.elements.find((el) => el.type === "heading");
|
|
6360
|
+
if (heading) {
|
|
6361
|
+
items.push({
|
|
6362
|
+
number: String(idx + 1),
|
|
6363
|
+
title: heading.text
|
|
6364
|
+
});
|
|
6365
|
+
}
|
|
6366
|
+
});
|
|
6367
|
+
}
|
|
6368
|
+
}
|
|
6369
|
+
const titleHtml = t.title ? `<h2 style="margin-bottom:1.5rem;">${this.escapeHtml(t.title)}</h2>` : "";
|
|
6370
|
+
const itemsHtml = items.map((it, idx) => {
|
|
6371
|
+
const num = it.number !== void 0 ? String(it.number) : String(idx + 1);
|
|
6372
|
+
const descText = it.description || it.subtitle;
|
|
6373
|
+
const desc = descText ? `<div style="font-size:0.85rem; color:var(--yumia-muted); margin-top:2px;">${this.formatInline(descText)}</div>` : "";
|
|
6374
|
+
return `
|
|
6375
|
+
<div class="yumia-toc-item">
|
|
6376
|
+
<div class="yumia-toc-num">${this.escapeHtml(num)}</div>
|
|
6377
|
+
<div>
|
|
6378
|
+
<div class="yumia-toc-title">${this.formatInline(it.title)}</div>
|
|
6379
|
+
${desc}
|
|
6380
|
+
</div>
|
|
6381
|
+
</div>`;
|
|
6382
|
+
}).join("\n");
|
|
6383
|
+
return `
|
|
6384
|
+
<div class="yumia-toc-container">
|
|
6385
|
+
${titleHtml}
|
|
6386
|
+
<div class="yumia-toc-grid">
|
|
6387
|
+
${itemsHtml}
|
|
6388
|
+
</div>
|
|
6389
|
+
</div>`;
|
|
6390
|
+
}
|
|
4321
6391
|
case "quote": {
|
|
4322
6392
|
const q = element;
|
|
4323
6393
|
const author = q.author ? `<br><small>\u2014 ${this.escapeHtml(q.author)}</small>` : "";
|
|
@@ -4393,9 +6463,10 @@ var HtmlRenderer = class {
|
|
|
4393
6463
|
}
|
|
4394
6464
|
case "math": {
|
|
4395
6465
|
const mathEl = element;
|
|
6466
|
+
const expr = mathEl.expression;
|
|
4396
6467
|
return `
|
|
4397
6468
|
<div class="yumia-math-container">
|
|
4398
|
-
<div class="yumia-math-equation"
|
|
6469
|
+
<div class="yumia-math-equation" data-expr="${this.escapeHtml(expr)}">$$${this.escapeHtml(expr)}$$</div>
|
|
4399
6470
|
</div>`;
|
|
4400
6471
|
}
|
|
4401
6472
|
case "chart": {
|
|
@@ -4404,6 +6475,27 @@ var HtmlRenderer = class {
|
|
|
4404
6475
|
case "timeline": {
|
|
4405
6476
|
return this.renderTimeline(element);
|
|
4406
6477
|
}
|
|
6478
|
+
case "icon": {
|
|
6479
|
+
const ic = element;
|
|
6480
|
+
const iconSvg = defaultIconResolver.toSvg(ic.name, ic.size || 24, ic.color || "currentColor", "yumia-icon");
|
|
6481
|
+
return `<span class="yumia-icon-wrapper" style="display:inline-flex; align-items:center; vertical-align:middle;">${iconSvg}</span>`;
|
|
6482
|
+
}
|
|
6483
|
+
case "grid": {
|
|
6484
|
+
const g = element;
|
|
6485
|
+
const cols = typeof g.columns === "number" ? `repeat(${g.columns}, 1fr)` : g.columns;
|
|
6486
|
+
const gap = g.gap !== void 0 ? typeof g.gap === "number" ? `${g.gap}px` : g.gap : "1.5rem";
|
|
6487
|
+
const inner = g.elements.map((child) => this.renderElement(child, theme, presentation)).join("\n");
|
|
6488
|
+
return `<div class="yumia-grid" style="display:grid; grid-template-columns:${cols}; gap:${gap}; width:100%;">${inner}</div>`;
|
|
6489
|
+
}
|
|
6490
|
+
case "stack": {
|
|
6491
|
+
const st = element;
|
|
6492
|
+
const dir = st.direction === "horizontal" ? "row" : "column";
|
|
6493
|
+
const gap = st.gap !== void 0 ? typeof st.gap === "number" ? `${st.gap}px` : st.gap : "1rem";
|
|
6494
|
+
const align = st.align ? `align-items:${st.align};` : "";
|
|
6495
|
+
const justify = st.justify ? `justify-content:${st.justify};` : "";
|
|
6496
|
+
const inner = st.elements.map((child) => this.renderElement(child, theme, presentation)).join("\n");
|
|
6497
|
+
return `<div class="yumia-stack" style="display:flex; flex-direction:${dir}; gap:${gap}; ${align} ${justify} width:100%;">${inner}</div>`;
|
|
6498
|
+
}
|
|
4407
6499
|
case "compare": {
|
|
4408
6500
|
return this.renderCompare(element, theme);
|
|
4409
6501
|
}
|
|
@@ -4557,8 +6649,7 @@ var HtmlRenderer = class {
|
|
|
4557
6649
|
</div>`;
|
|
4558
6650
|
}
|
|
4559
6651
|
formatInline(text) {
|
|
4560
|
-
|
|
4561
|
-
return escaped.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\*(.*?)\*/g, "<em>$1</em>").replace(/`(.*?)`/g, "<code>$1</code>");
|
|
6652
|
+
return this.escapeHtml(text).replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\*(.*?)\*/g, "<em>$1</em>").replace(/`(.*?)`/g, "<code>$1</code>");
|
|
4562
6653
|
}
|
|
4563
6654
|
escapeHtml(str) {
|
|
4564
6655
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -4603,7 +6694,7 @@ var PdfRenderer = class {
|
|
|
4603
6694
|
const totalSlides = presentation.slides.length;
|
|
4604
6695
|
for (let i = 0; i < totalSlides; i++) {
|
|
4605
6696
|
const slide = presentation.slides[i];
|
|
4606
|
-
this.renderSlide(doc, slide, i + 1, totalSlides, pageWidth, pageHeight, theme);
|
|
6697
|
+
this.renderSlide(doc, slide, i + 1, totalSlides, pageWidth, pageHeight, theme, presentation);
|
|
4607
6698
|
}
|
|
4608
6699
|
doc.end();
|
|
4609
6700
|
} catch (err) {
|
|
@@ -4611,7 +6702,7 @@ var PdfRenderer = class {
|
|
|
4611
6702
|
}
|
|
4612
6703
|
});
|
|
4613
6704
|
}
|
|
4614
|
-
renderSlide(doc, slide, slideNum, totalSlides, pageWidth, pageHeight, theme) {
|
|
6705
|
+
renderSlide(doc, slide, slideNum, totalSlides, pageWidth, pageHeight, theme, presentation) {
|
|
4615
6706
|
doc.addPage({
|
|
4616
6707
|
size: [pageWidth, pageHeight],
|
|
4617
6708
|
margins: { top: 0, bottom: 0, left: 0, right: 0 }
|
|
@@ -4622,7 +6713,7 @@ var PdfRenderer = class {
|
|
|
4622
6713
|
const contentWidth = pageWidth - padX * 2;
|
|
4623
6714
|
let cursorY = padY;
|
|
4624
6715
|
for (const element of slide.elements) {
|
|
4625
|
-
cursorY = this.renderElement(doc, element, padX, cursorY, contentWidth, theme);
|
|
6716
|
+
cursorY = this.renderElement(doc, element, padX, cursorY, contentWidth, theme, presentation);
|
|
4626
6717
|
cursorY += 12;
|
|
4627
6718
|
}
|
|
4628
6719
|
const progressWidth = slideNum / totalSlides * pageWidth;
|
|
@@ -4632,7 +6723,7 @@ var PdfRenderer = class {
|
|
|
4632
6723
|
align: "right"
|
|
4633
6724
|
});
|
|
4634
6725
|
}
|
|
4635
|
-
renderElement(doc, element, x, y, width, theme) {
|
|
6726
|
+
renderElement(doc, element, x, y, width, theme, presentation) {
|
|
4636
6727
|
switch (element.type) {
|
|
4637
6728
|
case "heading": {
|
|
4638
6729
|
const h = element;
|
|
@@ -4684,12 +6775,42 @@ var PdfRenderer = class {
|
|
|
4684
6775
|
}
|
|
4685
6776
|
case "code": {
|
|
4686
6777
|
const c = element;
|
|
4687
|
-
const
|
|
4688
|
-
doc.font("Courier").fontSize(
|
|
4689
|
-
const
|
|
4690
|
-
const boxHeight =
|
|
6778
|
+
const lines = c.code.split("\n");
|
|
6779
|
+
doc.font("Courier").fontSize(10);
|
|
6780
|
+
const lineHeight = 14;
|
|
6781
|
+
const boxHeight = lines.length * lineHeight + 20;
|
|
4691
6782
|
doc.roundedRect(x, y, width, boxHeight, 6).fill("#0a0a10").strokeColor(theme.colors.border || "rgba(255,255,255,0.1)").stroke();
|
|
4692
|
-
|
|
6783
|
+
const highlightSet = /* @__PURE__ */ new Set();
|
|
6784
|
+
if (c.highlight) {
|
|
6785
|
+
const parts = c.highlight.split(",");
|
|
6786
|
+
for (const part of parts) {
|
|
6787
|
+
const trimmed = part.trim();
|
|
6788
|
+
if (!trimmed)
|
|
6789
|
+
continue;
|
|
6790
|
+
if (trimmed.includes("-")) {
|
|
6791
|
+
const [startStr, endStr] = trimmed.split("-");
|
|
6792
|
+
const start = parseInt(startStr || "0", 10);
|
|
6793
|
+
const end = parseInt(endStr || "0", 10);
|
|
6794
|
+
if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
6795
|
+
for (let n = start; n <= end; n++)
|
|
6796
|
+
highlightSet.add(n);
|
|
6797
|
+
}
|
|
6798
|
+
} else {
|
|
6799
|
+
const num = parseInt(trimmed, 10);
|
|
6800
|
+
if (!isNaN(num))
|
|
6801
|
+
highlightSet.add(num);
|
|
6802
|
+
}
|
|
6803
|
+
}
|
|
6804
|
+
}
|
|
6805
|
+
lines.forEach((line, idx) => {
|
|
6806
|
+
const lineNum = idx + 1;
|
|
6807
|
+
const lineY = y + 10 + idx * lineHeight;
|
|
6808
|
+
const isHl = highlightSet.has(lineNum);
|
|
6809
|
+
const numColor = isHl ? theme.colors.primary : theme.colors.muted || "#555566";
|
|
6810
|
+
const textColor = c.highlight ? isHl ? theme.colors.primary || "#00f0ff" : theme.colors.muted || "#666677" : theme.colors.accent || "#38bdf8";
|
|
6811
|
+
doc.font("Courier").fontSize(9).fillColor(numColor).text(String(lineNum).padStart(2, " "), x + 10, lineY, { width: 22 });
|
|
6812
|
+
doc.font("Courier").fontSize(10).fillColor(textColor).text(line || " ", x + 36, lineY, { width: width - 48 });
|
|
6813
|
+
});
|
|
4693
6814
|
return y + boxHeight;
|
|
4694
6815
|
}
|
|
4695
6816
|
case "card": {
|
|
@@ -4897,7 +7018,7 @@ var PdfRenderer = class {
|
|
|
4897
7018
|
const barY = topY + plotH - h;
|
|
4898
7019
|
doc.rect(barX, barY, barW, h).fill(theme.colors.primary);
|
|
4899
7020
|
doc.font("Helvetica").fontSize(9).fillColor(theme.colors.text).text(String(val), barX, barY - 12, { width: barW, align: "center" });
|
|
4900
|
-
if (ch.labels[idx]) {
|
|
7021
|
+
if (ch.labels?.[idx]) {
|
|
4901
7022
|
doc.font("Helvetica").fontSize(9).fillColor(theme.colors.muted || "#888888").text(this.stripFormatting(ch.labels[idx]), barX - 10, topY + plotH + 4, {
|
|
4902
7023
|
width: barW + 20,
|
|
4903
7024
|
align: "center"
|
|
@@ -4926,6 +7047,116 @@ var PdfRenderer = class {
|
|
|
4926
7047
|
});
|
|
4927
7048
|
return y + boxH + 8;
|
|
4928
7049
|
}
|
|
7050
|
+
case "section": {
|
|
7051
|
+
const s = element;
|
|
7052
|
+
const boxH = 130;
|
|
7053
|
+
doc.roundedRect(x, y, width, boxH, 8).fill(theme.colors.surface || "rgba(255,255,255,0.06)");
|
|
7054
|
+
doc.roundedRect(x, y, width, boxH, 8).lineWidth(2).strokeColor(theme.colors.primary).stroke();
|
|
7055
|
+
let curY = y + 18;
|
|
7056
|
+
if (s.number !== void 0) {
|
|
7057
|
+
const numStr = String(s.number);
|
|
7058
|
+
doc.roundedRect(x + width / 2 - 40, curY, 80, 18, 9).fill(theme.colors.primary);
|
|
7059
|
+
doc.font("Helvetica-Bold").fontSize(9).fillColor("#000000").text(`SECTION ${numStr}`.toUpperCase(), x, curY + 4, { width, align: "center" });
|
|
7060
|
+
curY += 28;
|
|
7061
|
+
}
|
|
7062
|
+
doc.font("Helvetica-Bold").fontSize(22).fillColor(theme.colors.text).text(this.stripFormatting(s.title), x + 20, curY, {
|
|
7063
|
+
width: width - 40,
|
|
7064
|
+
align: "center"
|
|
7065
|
+
});
|
|
7066
|
+
curY += 28;
|
|
7067
|
+
if (s.subtitle) {
|
|
7068
|
+
doc.font("Helvetica").fontSize(12).fillColor(theme.colors.muted || "#999999").text(this.stripFormatting(s.subtitle), x + 30, curY, {
|
|
7069
|
+
width: width - 60,
|
|
7070
|
+
align: "center"
|
|
7071
|
+
});
|
|
7072
|
+
}
|
|
7073
|
+
return y + boxH + 8;
|
|
7074
|
+
}
|
|
7075
|
+
case "toc": {
|
|
7076
|
+
const t = element;
|
|
7077
|
+
const items = t.items ? [...t.items] : [];
|
|
7078
|
+
if (items.length === 0 && presentation) {
|
|
7079
|
+
let autoIdx = 1;
|
|
7080
|
+
for (const s of presentation.slides) {
|
|
7081
|
+
for (const el of s.elements) {
|
|
7082
|
+
if (el.type === "section") {
|
|
7083
|
+
const sec = el;
|
|
7084
|
+
items.push({
|
|
7085
|
+
number: sec.number !== void 0 ? String(sec.number) : String(autoIdx++),
|
|
7086
|
+
title: sec.title,
|
|
7087
|
+
description: sec.subtitle
|
|
7088
|
+
});
|
|
7089
|
+
}
|
|
7090
|
+
}
|
|
7091
|
+
}
|
|
7092
|
+
if (items.length === 0) {
|
|
7093
|
+
presentation.slides.forEach((s, idx) => {
|
|
7094
|
+
const heading = s.elements.find((el) => el.type === "heading");
|
|
7095
|
+
if (heading) {
|
|
7096
|
+
items.push({
|
|
7097
|
+
number: String(idx + 1),
|
|
7098
|
+
title: heading.text
|
|
7099
|
+
});
|
|
7100
|
+
}
|
|
7101
|
+
});
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
7104
|
+
let curY = y;
|
|
7105
|
+
if (t.title) {
|
|
7106
|
+
doc.font("Helvetica-Bold").fontSize(18).fillColor(theme.colors.primary).text(this.stripFormatting(t.title), x, curY, { width });
|
|
7107
|
+
curY += 26;
|
|
7108
|
+
}
|
|
7109
|
+
const itemH = 34;
|
|
7110
|
+
items.forEach((item, idx) => {
|
|
7111
|
+
const num = item.number !== void 0 ? String(item.number) : String(idx + 1);
|
|
7112
|
+
const descText = item.description || item.subtitle;
|
|
7113
|
+
const itemY = curY + idx * (itemH + 8);
|
|
7114
|
+
doc.roundedRect(x, itemY, width, itemH, 6).fill(theme.colors.surface || "rgba(255,255,255,0.04)");
|
|
7115
|
+
doc.roundedRect(x, itemY, width, itemH, 6).strokeColor(theme.colors.border || "rgba(255,255,255,0.1)").stroke();
|
|
7116
|
+
doc.roundedRect(x + 10, itemY + 6, 22, 22, 4).fill(theme.colors.primary);
|
|
7117
|
+
doc.font("Helvetica-Bold").fontSize(10).fillColor("#000000").text(num, x + 10, itemY + 11, { width: 22, align: "center" });
|
|
7118
|
+
doc.font("Helvetica-Bold").fontSize(12).fillColor(theme.colors.text).text(this.stripFormatting(item.title), x + 40, itemY + (descText ? 5 : 10), {
|
|
7119
|
+
width: width - 50
|
|
7120
|
+
});
|
|
7121
|
+
if (descText) {
|
|
7122
|
+
doc.font("Helvetica").fontSize(9).fillColor(theme.colors.muted || "#888888").text(this.stripFormatting(descText), x + 40, itemY + 19, {
|
|
7123
|
+
width: width - 50
|
|
7124
|
+
});
|
|
7125
|
+
}
|
|
7126
|
+
});
|
|
7127
|
+
return curY + items.length * (itemH + 8) + 8;
|
|
7128
|
+
}
|
|
7129
|
+
case "icon": {
|
|
7130
|
+
const ic = element;
|
|
7131
|
+
const iconText = `\u2605 ${ic.name.replace(/^[^:]+:/, "").toUpperCase()}`;
|
|
7132
|
+
doc.font("Helvetica-Bold").fontSize(11).fillColor(theme.colors.primary);
|
|
7133
|
+
doc.text(iconText, x, y, { width: 120 });
|
|
7134
|
+
return y + 20;
|
|
7135
|
+
}
|
|
7136
|
+
case "grid": {
|
|
7137
|
+
const g = element;
|
|
7138
|
+
const colCount = typeof g.columns === "number" ? g.columns : parseInt(String(g.columns), 10) || 2;
|
|
7139
|
+
const gap = 16;
|
|
7140
|
+
const availableWidth = width - gap * (colCount - 1);
|
|
7141
|
+
const colWidth = availableWidth / colCount;
|
|
7142
|
+
let maxY = y;
|
|
7143
|
+
for (let i = 0; i < g.elements.length; i++) {
|
|
7144
|
+
const colIdx = i % colCount;
|
|
7145
|
+
const colX = x + colIdx * (colWidth + gap);
|
|
7146
|
+
const childY = this.renderElement(doc, g.elements[i], colX, y, colWidth, theme, presentation);
|
|
7147
|
+
if (childY > maxY)
|
|
7148
|
+
maxY = childY;
|
|
7149
|
+
}
|
|
7150
|
+
return maxY + 8;
|
|
7151
|
+
}
|
|
7152
|
+
case "stack": {
|
|
7153
|
+
const st = element;
|
|
7154
|
+
let curY = y;
|
|
7155
|
+
for (const child of st.elements) {
|
|
7156
|
+
curY = this.renderElement(doc, child, x, curY, width, theme, presentation) + 8;
|
|
7157
|
+
}
|
|
7158
|
+
return curY;
|
|
7159
|
+
}
|
|
4929
7160
|
default:
|
|
4930
7161
|
return y;
|
|
4931
7162
|
}
|
|
@@ -4981,8 +7212,15 @@ function startDevServer(filePath, options = {}) {
|
|
|
4981
7212
|
}
|
|
4982
7213
|
}
|
|
4983
7214
|
const server = createServer(async (req, res) => {
|
|
4984
|
-
const
|
|
4985
|
-
|
|
7215
|
+
const rawUrl = req.url || "/";
|
|
7216
|
+
let pathname = "/";
|
|
7217
|
+
try {
|
|
7218
|
+
const parsed = new URL(rawUrl, `http://localhost:${port}`);
|
|
7219
|
+
pathname = parsed.pathname;
|
|
7220
|
+
} catch {
|
|
7221
|
+
pathname = rawUrl.split("?")[0] || "/";
|
|
7222
|
+
}
|
|
7223
|
+
if (pathname === "/__yumia_live_reload") {
|
|
4986
7224
|
res.writeHead(200, {
|
|
4987
7225
|
"Content-Type": "text/event-stream",
|
|
4988
7226
|
"Cache-Control": "no-cache",
|
|
@@ -4996,7 +7234,7 @@ function startDevServer(filePath, options = {}) {
|
|
|
4996
7234
|
});
|
|
4997
7235
|
return;
|
|
4998
7236
|
}
|
|
4999
|
-
if (
|
|
7237
|
+
if (pathname === "/" || pathname === "/index.html" || pathname.startsWith("/#")) {
|
|
5000
7238
|
const html = await getCompiledHtml();
|
|
5001
7239
|
res.writeHead(200, {
|
|
5002
7240
|
"Content-Type": "text/html; charset=utf-8",
|
|
@@ -5057,7 +7295,7 @@ function startDevServer(filePath, options = {}) {
|
|
|
5057
7295
|
// src/cli.ts
|
|
5058
7296
|
import { mkdirSync, readFileSync as readFileSync2, watch as fsWatch, writeFileSync } from "fs";
|
|
5059
7297
|
import { basename, dirname, extname, join, resolve as resolve2 } from "path";
|
|
5060
|
-
var VERSION = "0.1.
|
|
7298
|
+
var VERSION = "0.1.21";
|
|
5061
7299
|
function printHelp() {
|
|
5062
7300
|
return `
|
|
5063
7301
|
YumiaMD \u2014 Markdown-based presentation compiler (v${VERSION})
|
|
@@ -5596,10 +7834,21 @@ export {
|
|
|
5596
7834
|
createGroup,
|
|
5597
7835
|
createColumn,
|
|
5598
7836
|
createColumns,
|
|
7837
|
+
createSection,
|
|
7838
|
+
createToc,
|
|
5599
7839
|
createMath,
|
|
5600
7840
|
createLayoutDirective,
|
|
7841
|
+
createIcon,
|
|
7842
|
+
createGrid,
|
|
7843
|
+
createStack,
|
|
7844
|
+
createComponent,
|
|
7845
|
+
createSlot,
|
|
7846
|
+
NativeYumiaParser,
|
|
7847
|
+
parseNativeYumia,
|
|
7848
|
+
parseHighlightLines,
|
|
5601
7849
|
DefaultYumiaParser,
|
|
5602
7850
|
parseYumia,
|
|
7851
|
+
migrateMarkdownToNative,
|
|
5603
7852
|
DEFAULT_VIEWPORT,
|
|
5604
7853
|
VIEWPORT_PRESETS,
|
|
5605
7854
|
DefaultLayoutEngine,
|
|
@@ -5609,6 +7858,11 @@ export {
|
|
|
5609
7858
|
corporateTheme,
|
|
5610
7859
|
terminalTheme,
|
|
5611
7860
|
academicTheme,
|
|
7861
|
+
nordTheme,
|
|
7862
|
+
draculaTheme,
|
|
7863
|
+
tokyoNightTheme,
|
|
7864
|
+
emeraldTheme,
|
|
7865
|
+
synthwaveTheme,
|
|
5612
7866
|
THEME_REGISTRY,
|
|
5613
7867
|
resolveTheme,
|
|
5614
7868
|
createTheme,
|
|
@@ -5617,6 +7871,8 @@ export {
|
|
|
5617
7871
|
parse,
|
|
5618
7872
|
validate,
|
|
5619
7873
|
lint,
|
|
7874
|
+
IconResolver,
|
|
7875
|
+
defaultIconResolver,
|
|
5620
7876
|
cleanFontFace,
|
|
5621
7877
|
parseInlineMarkdown,
|
|
5622
7878
|
PptxRenderer,
|