@thanh01.pmt/presentation-kit 0.2.15 → 0.2.16
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/ai/index.cjs +145 -16
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.d.cts +15 -15
- package/dist/ai/index.d.ts +15 -15
- package/dist/ai/index.js +132 -3
- package/dist/ai/index.js.map +1 -1
- package/dist/{chunk-YPYAP4TF.js → chunk-7QHDWDSB.js} +218 -4
- package/dist/chunk-7QHDWDSB.js.map +1 -0
- package/dist/{chunk-SUGKWGJJ.cjs → chunk-JNTRKKJX.cjs} +218 -3
- package/dist/chunk-JNTRKKJX.cjs.map +1 -0
- package/dist/index.cjs +19 -15
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -2
- package/dist/react/index.cjs +5 -5
- package/dist/react/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-SUGKWGJJ.cjs.map +0 -1
- package/dist/chunk-YPYAP4TF.js.map +0 -1
|
@@ -3375,6 +3375,219 @@ function generateHtmlShell(options) {
|
|
|
3375
3375
|
</html>`;
|
|
3376
3376
|
}
|
|
3377
3377
|
|
|
3378
|
+
// src/html-engine/normalizer.ts
|
|
3379
|
+
function normalizeSlideSlots(slide) {
|
|
3380
|
+
if (!slide || typeof slide !== "object") {
|
|
3381
|
+
return { title: "Slide" };
|
|
3382
|
+
}
|
|
3383
|
+
const slots = {
|
|
3384
|
+
...slide,
|
|
3385
|
+
...slide.slots || {}
|
|
3386
|
+
};
|
|
3387
|
+
delete slots.slots;
|
|
3388
|
+
slots.title = String(slots.title || slide.title || slide.heading || slide.name || "").trim();
|
|
3389
|
+
slots.tag = String(slots.tag || slide.tag || slide.badge || "").trim();
|
|
3390
|
+
const rawContent = typeof slots.content === "string" && slots.content.trim() ? slots.content.trim() : typeof slide.content === "string" && slide.content.trim() ? slide.content.trim() : "";
|
|
3391
|
+
const layoutId = slide.layoutId || "hero-cover";
|
|
3392
|
+
switch (layoutId) {
|
|
3393
|
+
case "hero-cover": {
|
|
3394
|
+
slots.subtitle = slots.subtitle || slide.subtitle || slots.desc || rawContent || "";
|
|
3395
|
+
slots.author = slots.author || slide.author || "";
|
|
3396
|
+
slots.date = slots.date || slide.date || "";
|
|
3397
|
+
break;
|
|
3398
|
+
}
|
|
3399
|
+
case "split-concept-code": {
|
|
3400
|
+
if (!slots.code) {
|
|
3401
|
+
if (slide.code) {
|
|
3402
|
+
slots.code = slide.code;
|
|
3403
|
+
} else if (rawContent) {
|
|
3404
|
+
const fenceMatch = rawContent.match(/```(?:\w+)?\s*\n?([\s\S]*?)\n?```/);
|
|
3405
|
+
if (fenceMatch) {
|
|
3406
|
+
slots.code = fenceMatch[1].trim();
|
|
3407
|
+
} else if (/Code(?:\s+snippet)?:\s*/i.test(rawContent)) {
|
|
3408
|
+
const parts = rawContent.split(/Code(?:\s+snippet)?:\s*/i);
|
|
3409
|
+
if (parts[1] && parts[1].trim()) {
|
|
3410
|
+
slots.code = parts[1].trim();
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
if (!Array.isArray(slots.points) || slots.points.length === 0) {
|
|
3416
|
+
if (Array.isArray(slide.points) && slide.points.length > 0) {
|
|
3417
|
+
slots.points = slide.points;
|
|
3418
|
+
} else if (rawContent) {
|
|
3419
|
+
const textOnly = rawContent.replace(/```[\s\S]*?```/g, "").replace(/Code(?:\s+snippet)?:\s*[\s\S]*/i, "").trim();
|
|
3420
|
+
const lines = textOnly.split(/\n|\.\s+/).map((l) => l.replace(/^(?:Concept:\s*|[-*•]|\d+\.)\s*/i, "").trim()).filter((l) => l.length > 3);
|
|
3421
|
+
slots.points = lines.length > 0 ? lines.slice(0, 4) : [textOnly || slots.title || "Core Concept"];
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
if (!slots.code || slots.code === "...") {
|
|
3425
|
+
const lang = (slots.language || "code").toLowerCase();
|
|
3426
|
+
if (lang.includes("swift")) {
|
|
3427
|
+
slots.code = `// ${slots.title || "Swift Implementation"}
|
|
3428
|
+
import SwiftUI
|
|
3429
|
+
|
|
3430
|
+
struct PreviewView: View {
|
|
3431
|
+
var body: some View {
|
|
3432
|
+
Text("${slots.title || "Hello, World!"}")
|
|
3433
|
+
.padding()
|
|
3434
|
+
}
|
|
3435
|
+
}`;
|
|
3436
|
+
slots.language = slots.language || "swift";
|
|
3437
|
+
} else if (lang.includes("py")) {
|
|
3438
|
+
slots.code = `# ${slots.title || "Python Implementation"}
|
|
3439
|
+
def execute():
|
|
3440
|
+
print("${slots.title || "Ready"}")
|
|
3441
|
+
|
|
3442
|
+
execute()`;
|
|
3443
|
+
slots.language = slots.language || "python";
|
|
3444
|
+
} else {
|
|
3445
|
+
slots.code = `// ${slots.title || "Code Example"}
|
|
3446
|
+
function main() {
|
|
3447
|
+
console.log("${slots.title || "Executing"}");
|
|
3448
|
+
}
|
|
3449
|
+
main();`;
|
|
3450
|
+
slots.language = slots.language || "typescript";
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
break;
|
|
3454
|
+
}
|
|
3455
|
+
case "two-columns-compare": {
|
|
3456
|
+
slots.col1Title = slots.col1Title || slide.col1Title || "Approach A";
|
|
3457
|
+
slots.col2Title = slots.col2Title || slide.col2Title || "Approach B";
|
|
3458
|
+
if (!Array.isArray(slots.col1Items) || slots.col1Items.length === 0) {
|
|
3459
|
+
if (Array.isArray(slide.col1Items) && slide.col1Items.length > 0) {
|
|
3460
|
+
slots.col1Items = slide.col1Items;
|
|
3461
|
+
} else if (rawContent) {
|
|
3462
|
+
const items = rawContent.split(/\n|\.\s+/).map((l) => l.replace(/^(?:[-*•]|\d+\.)\s*/, "").trim()).filter((l) => l.length > 3);
|
|
3463
|
+
const half = Math.max(1, Math.ceil(items.length / 2));
|
|
3464
|
+
slots.col1Items = items.slice(0, half);
|
|
3465
|
+
if (!slots.col2Items || !Array.isArray(slots.col2Items)) {
|
|
3466
|
+
slots.col2Items = items.slice(half);
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
slots.col1Items = Array.isArray(slots.col1Items) && slots.col1Items.length > 0 ? slots.col1Items : ["Primary Characteristics", "Standard Practice"];
|
|
3471
|
+
slots.col2Items = Array.isArray(slots.col2Items) && slots.col2Items.length > 0 ? slots.col2Items : Array.isArray(slide.col2Items) ? slide.col2Items : ["Alternative Paradigm", "Trade-offs & Edge Cases"];
|
|
3472
|
+
break;
|
|
3473
|
+
}
|
|
3474
|
+
case "three-cards-grid": {
|
|
3475
|
+
if (!Array.isArray(slots.cards) || slots.cards.length === 0) {
|
|
3476
|
+
if (Array.isArray(slide.cards) && slide.cards.length > 0) {
|
|
3477
|
+
slots.cards = slide.cards;
|
|
3478
|
+
} else if (rawContent) {
|
|
3479
|
+
const cardTokens = rawContent.split(/Card\s*\d+:\s*|(?:\r?\n){2,}|\.\s+/i).map((c) => c.trim()).filter(Boolean);
|
|
3480
|
+
if (cardTokens.length >= 2) {
|
|
3481
|
+
slots.cards = cardTokens.slice(0, 3).map((txt, idx) => {
|
|
3482
|
+
const colonIdx = txt.indexOf(":");
|
|
3483
|
+
const cardTitle = colonIdx > 0 && colonIdx < 30 ? txt.slice(0, colonIdx).trim() : `Pillar ${idx + 1}`;
|
|
3484
|
+
const cardDesc = colonIdx > 0 && colonIdx < 30 ? txt.slice(colonIdx + 1).trim() : txt;
|
|
3485
|
+
return { badge: `0${idx + 1}`, title: cardTitle, desc: cardDesc };
|
|
3486
|
+
});
|
|
3487
|
+
} else {
|
|
3488
|
+
const lines = rawContent.split(/\n|\.\s+/).map((l) => l.replace(/^(?:[-*•]|\d+\.)\s*/, "").trim()).filter((l) => l.length > 3);
|
|
3489
|
+
slots.cards = lines.slice(0, 3).map((line, idx) => ({
|
|
3490
|
+
badge: `0${idx + 1}`,
|
|
3491
|
+
title: line.split(":")[0]?.slice(0, 30) || `Pillar 0${idx + 1}`,
|
|
3492
|
+
desc: line
|
|
3493
|
+
}));
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
if (!Array.isArray(slots.cards) || slots.cards.length === 0) {
|
|
3498
|
+
slots.cards = [
|
|
3499
|
+
{ badge: "01", title: "Foundation", desc: rawContent || "Core fundamentals and design principles" },
|
|
3500
|
+
{ badge: "02", title: "Architecture", desc: "Component relationships and data flow patterns" },
|
|
3501
|
+
{ badge: "03", title: "Practice", desc: "Real-world application and hands-on synthesis" }
|
|
3502
|
+
];
|
|
3503
|
+
}
|
|
3504
|
+
break;
|
|
3505
|
+
}
|
|
3506
|
+
case "timeline-steps": {
|
|
3507
|
+
if (!Array.isArray(slots.steps) || slots.steps.length === 0) {
|
|
3508
|
+
if (Array.isArray(slide.steps) && slide.steps.length > 0) {
|
|
3509
|
+
slots.steps = slide.steps;
|
|
3510
|
+
} else if (rawContent) {
|
|
3511
|
+
const stepMatches = rawContent.split(/(?:\d+\.|\bStep\s*\d+:)\s*/i).map((s) => s.trim()).filter(Boolean);
|
|
3512
|
+
if (stepMatches.length > 0) {
|
|
3513
|
+
slots.steps = stepMatches.slice(0, 5).map((txt, idx) => {
|
|
3514
|
+
const periodIdx = txt.indexOf(".");
|
|
3515
|
+
const stepTitle = periodIdx > 0 && periodIdx < 35 ? txt.slice(0, periodIdx).trim() : txt.slice(0, 30);
|
|
3516
|
+
const stepDesc = periodIdx > 0 && periodIdx < 35 ? txt.slice(periodIdx + 1).trim() : txt;
|
|
3517
|
+
return { stepNum: idx + 1, title: stepTitle || `Step ${idx + 1}`, desc: stepDesc || stepTitle };
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
if (!Array.isArray(slots.steps) || slots.steps.length === 0) {
|
|
3523
|
+
slots.steps = [
|
|
3524
|
+
{ stepNum: 1, title: "Analyze", desc: "Deconstruct requirements and constraints" },
|
|
3525
|
+
{ stepNum: 2, title: "Implement", desc: rawContent || "Build component logic and structure" },
|
|
3526
|
+
{ stepNum: 3, title: "Verify", desc: "Test behavior and validate outcomes" }
|
|
3527
|
+
];
|
|
3528
|
+
}
|
|
3529
|
+
break;
|
|
3530
|
+
}
|
|
3531
|
+
case "metric-callout": {
|
|
3532
|
+
slots.desc = slots.desc || slide.desc || rawContent || "";
|
|
3533
|
+
slots.metricLabel = slots.metricLabel || slide.metricLabel || "KEY METRIC";
|
|
3534
|
+
if (!slots.metric) {
|
|
3535
|
+
const numMatch = (slots.desc || slots.title).match(/(\d+(?:\.\d+)?%?|O\([^)]+\)|\d+x|\b[A-Z0-9_-]{2,}\b)/i);
|
|
3536
|
+
slots.metric = numMatch ? numMatch[1] : "100%";
|
|
3537
|
+
}
|
|
3538
|
+
break;
|
|
3539
|
+
}
|
|
3540
|
+
case "checkpoint-quiz": {
|
|
3541
|
+
slots.question = slots.question || slide.question || slots.title || "Check Your Understanding";
|
|
3542
|
+
if (!Array.isArray(slots.options) || slots.options.length === 0) {
|
|
3543
|
+
if (Array.isArray(slide.options) && slide.options.length > 0) {
|
|
3544
|
+
slots.options = slide.options;
|
|
3545
|
+
} else if (rawContent) {
|
|
3546
|
+
const items = rawContent.split(/(?:\d+\.|\b[A-D]\))\s*/i).map((l) => l.trim()).filter((l) => l.length > 3);
|
|
3547
|
+
if (items.length >= 2) {
|
|
3548
|
+
slots.options = items.slice(0, 4).map((text, idx) => ({
|
|
3549
|
+
label: String.fromCharCode(65 + idx),
|
|
3550
|
+
text
|
|
3551
|
+
}));
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
if (!Array.isArray(slots.options) || slots.options.length === 0) {
|
|
3556
|
+
slots.options = [
|
|
3557
|
+
{ label: "A", text: "Option A (Core Concept)" },
|
|
3558
|
+
{ label: "B", text: "Option B (Alternative Approach)" },
|
|
3559
|
+
{ label: "C", text: "Option C (Edge Case)" }
|
|
3560
|
+
];
|
|
3561
|
+
}
|
|
3562
|
+
slots.explanation = slots.explanation || slide.explanation || "";
|
|
3563
|
+
break;
|
|
3564
|
+
}
|
|
3565
|
+
case "summary-takeaways": {
|
|
3566
|
+
if (!Array.isArray(slots.takeaways) || slots.takeaways.length === 0) {
|
|
3567
|
+
if (Array.isArray(slide.takeaways) && slide.takeaways.length > 0) {
|
|
3568
|
+
slots.takeaways = slide.takeaways;
|
|
3569
|
+
} else if (rawContent) {
|
|
3570
|
+
const lines = rawContent.split(/\n|\.\s+/).map((l) => l.replace(/^(?:[-*•]|\d+\.)\s*/, "").trim()).filter((l) => l.length > 3);
|
|
3571
|
+
slots.takeaways = lines.length > 0 ? lines.slice(0, 4) : [rawContent];
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
if (!Array.isArray(slots.takeaways) || slots.takeaways.length === 0) {
|
|
3575
|
+
slots.takeaways = [
|
|
3576
|
+
slots.title || "Key lesson principles mastered",
|
|
3577
|
+
"Applied hands-on practice through guided examples",
|
|
3578
|
+
"Ready for independent challenge and synthesis"
|
|
3579
|
+
];
|
|
3580
|
+
}
|
|
3581
|
+
slots.nextStep = slots.nextStep || slide.nextStep || "Next: Practical Hands-On Lab";
|
|
3582
|
+
break;
|
|
3583
|
+
}
|
|
3584
|
+
}
|
|
3585
|
+
if (rawContent && !slots.rawContent) {
|
|
3586
|
+
slots.rawContent = rawContent;
|
|
3587
|
+
}
|
|
3588
|
+
return slots;
|
|
3589
|
+
}
|
|
3590
|
+
|
|
3378
3591
|
// src/html-engine/compiler.ts
|
|
3379
3592
|
function compileHtmlDeck(deckData, options) {
|
|
3380
3593
|
const theme = options?.themeOverride || resolveHtmlTheme(deckData.theme);
|
|
@@ -3382,7 +3595,8 @@ function compileHtmlDeck(deckData, options) {
|
|
|
3382
3595
|
const slideCount = Math.max(slides.length, 1);
|
|
3383
3596
|
const renderedSlides = slides.map((slide, index) => {
|
|
3384
3597
|
const preset = HTML_SLIDE_PRESETS[slide.layoutId] || HTML_SLIDE_PRESETS["hero-cover"];
|
|
3385
|
-
const
|
|
3598
|
+
const normalizedSlots = normalizeSlideSlots(slide);
|
|
3599
|
+
const innerHtml = preset.template(normalizedSlots, theme);
|
|
3386
3600
|
const notesAttr = slide.notes ? ` data-notes="${encodeURIComponent(slide.notes)}"` : "";
|
|
3387
3601
|
const customClass = slide.customClass ? ` ${slide.customClass}` : "";
|
|
3388
3602
|
return `
|
|
@@ -3416,11 +3630,12 @@ exports.compileHtmlDeck = compileHtmlDeck;
|
|
|
3416
3630
|
exports.generateHtmlShell = generateHtmlShell;
|
|
3417
3631
|
exports.getSlideLayoutPresetById = getSlideLayoutPresetById;
|
|
3418
3632
|
exports.getSlideLayoutPresetsByCategory = getSlideLayoutPresetsByCategory;
|
|
3633
|
+
exports.normalizeSlideSlots = normalizeSlideSlots;
|
|
3419
3634
|
exports.removeSlideElementFromMarkdown = removeSlideElementFromMarkdown;
|
|
3420
3635
|
exports.resolveHtmlTheme = resolveHtmlTheme;
|
|
3421
3636
|
exports.serializeLayoutToComment = serializeLayoutToComment;
|
|
3422
3637
|
exports.splitMarkdownSlides = splitMarkdownSlides;
|
|
3423
3638
|
exports.updateSlideLayoutInMarkdown = updateSlideLayoutInMarkdown;
|
|
3424
3639
|
exports.updateSlideTextInMarkdown = updateSlideTextInMarkdown;
|
|
3425
|
-
//# sourceMappingURL=chunk-
|
|
3426
|
-
//# sourceMappingURL=chunk-
|
|
3640
|
+
//# sourceMappingURL=chunk-JNTRKKJX.cjs.map
|
|
3641
|
+
//# sourceMappingURL=chunk-JNTRKKJX.cjs.map
|