canva-pptx 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1147 -0
- package/package.json +63 -0
- package/src/AdvancedComponents/accordionList.js +39 -0
- package/src/AdvancedComponents/calendarGrid.js +50 -0
- package/src/AdvancedComponents/certificateFrame.js +35 -0
- package/src/AdvancedComponents/deviceMockup.js +59 -0
- package/src/AdvancedComponents/featureGrid.js +70 -0
- package/src/AdvancedComponents/funnelDiagram.js +49 -0
- package/src/AdvancedComponents/ganttChart.js +35 -0
- package/src/AdvancedComponents/invoiceTable.js +32 -0
- package/src/AdvancedComponents/matrixGrid.js +43 -0
- package/src/AdvancedComponents/mindMap.js +43 -0
- package/src/AdvancedComponents/orgChart.js +76 -0
- package/src/AdvancedComponents/personaCard.js +44 -0
- package/src/AdvancedComponents/processCycle.js +47 -0
- package/src/AdvancedComponents/pyramidHierarchy.js +38 -0
- package/src/AdvancedComponents/saasFeatureBlock.js +38 -0
- package/src/AdvancedComponents/swotMatrix.js +55 -0
- package/src/AdvancedComponents/teamMemberProfile.js +75 -0
- package/src/AdvancedComponents/trafficLight.js +35 -0
- package/src/AdvancedComponents/vennDiagram.js +35 -0
- package/src/AdvancedComponents/winLossChart.js +43 -0
- package/src/components/StatMetric.js +43 -0
- package/src/components/alertBox.js +46 -0
- package/src/components/avatarGroup.js +56 -0
- package/src/components/badge.js +40 -0
- package/src/components/breadcrumbNav.js +31 -0
- package/src/components/browserWindow.js +86 -0
- package/src/components/brushStroke.js +23 -0
- package/src/components/callToAction.js +27 -0
- package/src/components/card.js +64 -0
- package/src/components/chart.js +19 -0
- package/src/components/codeBlock.js +40 -0
- package/src/components/codeDiff.js +51 -0
- package/src/components/comparisonTable.js +43 -0
- package/src/components/cornerAccent.js +32 -0
- package/src/components/dotPattern.js +30 -0
- package/src/components/geometricConfetti.js +34 -0
- package/src/components/gradientMesh.js +32 -0
- package/src/components/iconList.js +43 -0
- package/src/components/image.js +11 -0
- package/src/components/kanbanColumn.js +38 -0
- package/src/components/link.js +23 -0
- package/src/components/organicBlob.js +45 -0
- package/src/components/pricingColumn.js +53 -0
- package/src/components/progressBar.js +55 -0
- package/src/components/ratingStars.js +25 -0
- package/src/components/shape.js +12 -0
- package/src/components/slide.js +5 -0
- package/src/components/socialBar.js +59 -0
- package/src/components/squiggleLine.js +26 -0
- package/src/components/stepProcess.js +39 -0
- package/src/components/table.js +23 -0
- package/src/components/tagCloud.js +39 -0
- package/src/components/testimonialCard.js +54 -0
- package/src/components/text.js +14 -0
- package/src/components/theme.js +7 -0
- package/src/components/timeline.js +73 -0
- package/src/components/waveDecoration.js +35 -0
- package/src/core/PPTManager.js +17 -0
- package/src/index.js +225 -0
- package/src/layout/bento.js +47 -0
- package/src/layout/checkerboard.js +36 -0
- package/src/layout/filmStrip.js +29 -0
- package/src/layout/gallery.js +50 -0
- package/src/layout/grid.js +37 -0
- package/src/layout/hero.js +30 -0
- package/src/layout/magazine.js +39 -0
- package/src/layout/radial.js +34 -0
- package/src/layout/sidebar.js +26 -0
- package/src/layout/splitScreen.js +36 -0
- package/src/layout/zPattern.js +29 -0
- package/src/system/animation.js +36 -0
- package/src/system/contrastChecker.js +35 -0
- package/src/system/dataAdapter.js +36 -0
- package/src/system/layoutDebugger.js +40 -0
- package/src/system/markdownEngine.js +45 -0
- package/src/system/masterOverlay.js +50 -0
- package/src/system/sectionDivider.js +41 -0
- package/src/system/smartIcon.js +33 -0
- package/src/system/smartText.js +44 -0
- package/src/system/speakerNotes.js +12 -0
- package/src/system/syntaxHighlighter.js +71 -0
- package/src/system/themeGenerator.js +25 -0
- package/src/system/tocGenerator.js +68 -0
- package/src/system/watermark.js +26 -0
- package/src/themes/index.js +93 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function addSmartText(slide, text, options = {}) {
|
|
2
|
+
const {
|
|
3
|
+
x = 1, y = 1, w = 4, h = 2,
|
|
4
|
+
maxFontSize = 24,
|
|
5
|
+
minFontSize = 8,
|
|
6
|
+
color = "000000"
|
|
7
|
+
} = options;
|
|
8
|
+
|
|
9
|
+
// Heuristic: Area = w * h
|
|
10
|
+
// Text Area needed ~= charCount * (fontSize * 0.6) * (fontSize * 1.2)
|
|
11
|
+
// This is an estimation loop.
|
|
12
|
+
|
|
13
|
+
let currentSize = maxFontSize;
|
|
14
|
+
const chars = text.length;
|
|
15
|
+
|
|
16
|
+
// Reduce font size until it theoretically fits
|
|
17
|
+
while (currentSize > minFontSize) {
|
|
18
|
+
// Approx char width ~0.5 of font height (variable width fonts vary, but average)
|
|
19
|
+
// Approx line height ~1.2 of font height
|
|
20
|
+
// Max chars per line = w / (currentSize converted to inches approx)
|
|
21
|
+
// 1 pt = 1/72 inch
|
|
22
|
+
|
|
23
|
+
const charW_inch = (currentSize / 72) * 0.5;
|
|
24
|
+
const lineH_inch = (currentSize / 72) * 1.2;
|
|
25
|
+
|
|
26
|
+
const charsPerLine = Math.floor(w / charW_inch);
|
|
27
|
+
const linesNeeded = Math.ceil(chars / charsPerLine);
|
|
28
|
+
const totalHeightNeeded = linesNeeded * lineH_inch;
|
|
29
|
+
|
|
30
|
+
if (totalHeightNeeded <= h) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
currentSize -= 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
slide.addText(text, {
|
|
38
|
+
x, y, w, h,
|
|
39
|
+
fontSize: currentSize,
|
|
40
|
+
color
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { addSmartText };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds speaker notes to a slide.
|
|
3
|
+
* These are visible in "Presenter View" but not on the main screen.
|
|
4
|
+
*/
|
|
5
|
+
function addSpeakerNotes(slide, notes) {
|
|
6
|
+
if (!slide || !notes) return;
|
|
7
|
+
|
|
8
|
+
// pptxgenjs has a native addNotes method
|
|
9
|
+
slide.addNotes(notes);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = { addSpeakerNotes };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a code block with syntax coloring (Basic JS support).
|
|
3
|
+
*/
|
|
4
|
+
function addSyntaxBlock(slide, code, options = {}) {
|
|
5
|
+
const {
|
|
6
|
+
x = 1, y = 1, w = 6, h = 3,
|
|
7
|
+
fontSize = 11,
|
|
8
|
+
background = "1E1E1E"
|
|
9
|
+
} = options;
|
|
10
|
+
|
|
11
|
+
// Draw Background
|
|
12
|
+
slide.addShape("rect", { x, y, w, h, fill: background });
|
|
13
|
+
|
|
14
|
+
// Simple Tokenizer (Regex based)
|
|
15
|
+
const tokens = [];
|
|
16
|
+
const lines = code.split("\n");
|
|
17
|
+
|
|
18
|
+
// Colors (VS Code Dark theme style)
|
|
19
|
+
const C_KEYWORD = "569CD6"; // Blue
|
|
20
|
+
const C_STRING = "CE9178"; // Orange
|
|
21
|
+
const C_COMMENT = "6A9955"; // Green
|
|
22
|
+
const C_DEFAULT = "D4D4D4"; // Grey
|
|
23
|
+
const C_FUNCTION = "DCDCAA"; // Yellow
|
|
24
|
+
|
|
25
|
+
// Regex Patterns
|
|
26
|
+
const reKeyword = /\b(const|let|var|function|return|if|else|for|while|import|from|class)\b/g;
|
|
27
|
+
const reString = /(['"`].*?['"`])/g;
|
|
28
|
+
const reComment = /(\/\/.*)/g;
|
|
29
|
+
const reFunction = /\b([a-zA-Z0-9_]+)(?=\()/g;
|
|
30
|
+
|
|
31
|
+
let currentY = y + 0.2;
|
|
32
|
+
const lineHeight = fontSize * 0.003; // Approximate conversion
|
|
33
|
+
|
|
34
|
+
lines.forEach(line => {
|
|
35
|
+
// We break the line into simple text objects for the slide
|
|
36
|
+
// Note: To do this perfectly inline is hard in PPTX without rich text array.
|
|
37
|
+
// We will construct a rich text array for the line.
|
|
38
|
+
|
|
39
|
+
let parts = [];
|
|
40
|
+
let lastIndex = 0;
|
|
41
|
+
|
|
42
|
+
// Very naive parser: Identify the *first* match type for simplicity in this demo.
|
|
43
|
+
// A real parser would tokenize character by character.
|
|
44
|
+
// Here we will just color the whole line if it's a comment,
|
|
45
|
+
// otherwise default (Full syntax highlighting requires complex state machine).
|
|
46
|
+
|
|
47
|
+
if (line.trim().startsWith("//")) {
|
|
48
|
+
slide.addText(line, { x: x+0.2, y: currentY, w: w-0.4, h: lineHeight, fontSize, color: C_COMMENT, fontFace: "Courier New" });
|
|
49
|
+
} else {
|
|
50
|
+
// Check for keywords to color (simplified: only highlights if word is isolated)
|
|
51
|
+
// This is a "Pseudo-Highlighter" for the sake of the library size.
|
|
52
|
+
const textObjs = [];
|
|
53
|
+
const words = line.split(/(\s+|[(){},.])/); // Split by delimiters
|
|
54
|
+
|
|
55
|
+
words.forEach(word => {
|
|
56
|
+
let color = C_DEFAULT;
|
|
57
|
+
if (reKeyword.test(word)) color = C_KEYWORD;
|
|
58
|
+
else if (reString.test(word)) color = C_STRING;
|
|
59
|
+
else if (reFunction.test(word)) color = C_FUNCTION;
|
|
60
|
+
|
|
61
|
+
textObjs.push({ text: word, options: { color: color, fontSize, fontFace: "Courier New" } });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
slide.addText(textObjs, { x: x+0.2, y: currentY, w: w-0.4, h: lineHeight, align:'left' });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
currentY += 0.25; // Line height spacing
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { addSyntaxBlock };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a tonal palette (Light, Dark, Muted) from a single HEX color.
|
|
3
|
+
* Useful for auto-generating themes that look consistent.
|
|
4
|
+
*/
|
|
5
|
+
function generateTheme(baseColorHex) {
|
|
6
|
+
// Simple helper to adjust brightness
|
|
7
|
+
// (In a prod env, use a library like 'chroma-js' or 'tinycolor2')
|
|
8
|
+
|
|
9
|
+
const adjust = (hex, amount) => {
|
|
10
|
+
return "#" + hex.replace(/^#/, '').replace(/../g, color => {
|
|
11
|
+
const val = parseInt(color, 16);
|
|
12
|
+
return Math.min(255, Math.max(0, val + amount)).toString(16).padStart(2, '0');
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
primary: baseColorHex,
|
|
18
|
+
light: adjust(baseColorHex, 150), // Tint (Backgrounds)
|
|
19
|
+
dark: adjust(baseColorHex, -50), // Shade (Text)
|
|
20
|
+
muted: adjust(baseColorHex, 80), // Soft accent
|
|
21
|
+
border: "E0E0E0"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = { generateTheme };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOC Generator System
|
|
3
|
+
* Tracks sections and generates an Agenda slide.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Private storage for the session
|
|
7
|
+
let sections = [];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Registers a section for the Table of Contents.
|
|
11
|
+
* Call this when adding a new slide that should appear in the TOC.
|
|
12
|
+
* @param {string} title - The title of the section.
|
|
13
|
+
* @param {number} slideIndex - The index of the slide (1-based).
|
|
14
|
+
*/
|
|
15
|
+
function addToTOC(title, slideIndex) {
|
|
16
|
+
sections.push({ title, slide: slideIndex });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Renders the Table of Contents slide.
|
|
21
|
+
* Usually called at the end of the presentation generation,
|
|
22
|
+
* but inserted at the beginning.
|
|
23
|
+
* @param {object} manager - The PPTManager instance.
|
|
24
|
+
* @param {object} options - Options { title, x, y, color }.
|
|
25
|
+
*/
|
|
26
|
+
function addTableOfContents(manager, options = {}) {
|
|
27
|
+
const {
|
|
28
|
+
title = "Agenda",
|
|
29
|
+
x = 1,
|
|
30
|
+
y = 1.5,
|
|
31
|
+
color = "007AFF"
|
|
32
|
+
} = options;
|
|
33
|
+
|
|
34
|
+
const pptx = manager.getPptx();
|
|
35
|
+
|
|
36
|
+
// Create a new slide
|
|
37
|
+
const slide = pptx.addSlide();
|
|
38
|
+
|
|
39
|
+
// Title
|
|
40
|
+
slide.addText(title, {
|
|
41
|
+
x: 1, y: 0.5, fontSize: 32, bold: true, color: "111111"
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Render List
|
|
45
|
+
sections.forEach((section, index) => {
|
|
46
|
+
slide.addText(`${index + 1}. ${section.title}`, {
|
|
47
|
+
x: x,
|
|
48
|
+
y: y + index * 0.6,
|
|
49
|
+
w: 8,
|
|
50
|
+
h: 0.5,
|
|
51
|
+
fontSize: 18,
|
|
52
|
+
color: color,
|
|
53
|
+
// Hyperlink to the specific slide number
|
|
54
|
+
hyperlink: { slide: section.slide }
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Optional: Logic to move this slide to index 1 could go here
|
|
59
|
+
// if the underlying library supports reordering.
|
|
60
|
+
// For now, it appends a slide. Users usually create this first or last.
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Reset function if you need to clear memory between requests
|
|
64
|
+
function resetTOC() {
|
|
65
|
+
sections = [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { addToTOC, addTableOfContents, resetTOC };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds a watermark to a slide.
|
|
3
|
+
*/
|
|
4
|
+
function addWatermark(slide, text = "CONFIDENTIAL", options = {}) {
|
|
5
|
+
const {
|
|
6
|
+
color = "CCCCCC",
|
|
7
|
+
opacity = 20, // 0-100 transparency
|
|
8
|
+
rotate = -45,
|
|
9
|
+
fontSize = 60
|
|
10
|
+
} = options;
|
|
11
|
+
|
|
12
|
+
slide.addText(text, {
|
|
13
|
+
x: 1,
|
|
14
|
+
y: 2,
|
|
15
|
+
w: 8,
|
|
16
|
+
h: 2,
|
|
17
|
+
color: color,
|
|
18
|
+
transparency: 100 - opacity, // PptxGenJS uses 'transparency' %
|
|
19
|
+
rotate: rotate,
|
|
20
|
+
align: "center",
|
|
21
|
+
fontSize: fontSize,
|
|
22
|
+
bold: true
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = { addWatermark };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme System
|
|
3
|
+
* Pre-defined themes and utilities for custom branding.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const themes = {
|
|
7
|
+
minimal: {
|
|
8
|
+
background: "FFFFFF",
|
|
9
|
+
heading: {
|
|
10
|
+
fontSize: 28,
|
|
11
|
+
color: "111111",
|
|
12
|
+
bold: true,
|
|
13
|
+
fontFace: "Arial",
|
|
14
|
+
},
|
|
15
|
+
body: {
|
|
16
|
+
fontSize: 16,
|
|
17
|
+
color: "444444",
|
|
18
|
+
fontFace: "Arial",
|
|
19
|
+
},
|
|
20
|
+
accent: "E5E7EB",
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
brand: {
|
|
24
|
+
background: "F8FAFC",
|
|
25
|
+
heading: {
|
|
26
|
+
fontSize: 30,
|
|
27
|
+
color: "0F172A",
|
|
28
|
+
bold: true,
|
|
29
|
+
fontFace: "Helvetica",
|
|
30
|
+
},
|
|
31
|
+
body: {
|
|
32
|
+
fontSize: 16,
|
|
33
|
+
color: "334155",
|
|
34
|
+
fontFace: "Helvetica",
|
|
35
|
+
},
|
|
36
|
+
accent: "2563EB",
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
dark: {
|
|
40
|
+
background: "020617",
|
|
41
|
+
heading: {
|
|
42
|
+
fontSize: 30,
|
|
43
|
+
color: "FFFFFF",
|
|
44
|
+
bold: true,
|
|
45
|
+
fontFace: "Verdana",
|
|
46
|
+
},
|
|
47
|
+
body: {
|
|
48
|
+
fontSize: 16,
|
|
49
|
+
color: "CBD5E1",
|
|
50
|
+
fontFace: "Verdana",
|
|
51
|
+
},
|
|
52
|
+
accent: "38BDF8",
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Register a custom brand theme.
|
|
58
|
+
* Merges user options with the 'minimal' theme to ensure all properties exist.
|
|
59
|
+
*/
|
|
60
|
+
function registerTheme(name, customOptions) {
|
|
61
|
+
// Deep merge logic (simplified)
|
|
62
|
+
themes[name] = {
|
|
63
|
+
...themes.minimal,
|
|
64
|
+
...customOptions,
|
|
65
|
+
heading: { ...themes.minimal.heading, ...customOptions.heading },
|
|
66
|
+
body: { ...themes.minimal.body, ...customOptions.body },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Retrieves a theme by name OR normalizes a custom theme object.
|
|
72
|
+
* @param {string|object} nameOrObject - Theme name ("brand") or direct object.
|
|
73
|
+
*/
|
|
74
|
+
function getTheme(nameOrObject = "minimal") {
|
|
75
|
+
// 1. If user passes an object (ad-hoc theme), merge it with default and return
|
|
76
|
+
if (typeof nameOrObject === "object") {
|
|
77
|
+
return {
|
|
78
|
+
...themes.minimal,
|
|
79
|
+
...nameOrObject,
|
|
80
|
+
heading: { ...themes.minimal.heading, ...nameOrObject.heading },
|
|
81
|
+
body: { ...themes.minimal.body, ...nameOrObject.body },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 2. If user passes a name, return registered theme or default
|
|
86
|
+
return themes[nameOrObject] || themes.minimal;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
getTheme,
|
|
91
|
+
registerTheme,
|
|
92
|
+
themes,
|
|
93
|
+
};
|