taleem-engine 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.
Files changed (65) hide show
  1. package/package.json +51 -0
  2. package/readme.md +472 -0
  3. package/src/compiler/TaleemCompiler.js +122 -0
  4. package/src/compiler/animation-primtives/eqHighlightOne.js +41 -0
  5. package/src/compiler/animation-primtives/progressiveReveal.js +14 -0
  6. package/src/compiler/animation-primtives/runPrimitive.js +71 -0
  7. package/src/compiler/animation-primtives/showAllHighlightOne.js +34 -0
  8. package/src/compiler/animation-primtives/showOneAtATime.js +24 -0
  9. package/src/compiler/templates/compileBarChart.js +91 -0
  10. package/src/compiler/templates/compileBulletList.js +37 -0
  11. package/src/compiler/templates/compileEq.js +135 -0
  12. package/src/compiler/templates/compileFillImage.js +50 -0
  13. package/src/compiler/templates/compileFocusList.js +75 -0
  14. package/src/compiler/templates/compileImageGrid.js +60 -0
  15. package/src/compiler/templates/compileImageLeftBulletsRight.js +78 -0
  16. package/src/compiler/templates/compileImageRightBulletsLeft.js +79 -0
  17. package/src/compiler/templates/compileImageSlide.js +52 -0
  18. package/src/compiler/templates/compileImageStrip.js +60 -0
  19. package/src/compiler/templates/compileImageWithCaption.js +75 -0
  20. package/src/compiler/templates/compileImageWithTitle.js +75 -0
  21. package/src/compiler/templates/compileKeyIdeasSlide.js +62 -0
  22. package/src/compiler/templates/compileProgressbar.js +74 -0
  23. package/src/compiler/templates/compileQuoteSlide.js +72 -0
  24. package/src/compiler/templates/compileSkeletonSlide.js +80 -0
  25. package/src/compiler/templates/compileTable.js +70 -0
  26. package/src/compiler/templates/compileTextGrid.js +57 -0
  27. package/src/compiler/templates/compileTitleAndPara.js +79 -0
  28. package/src/compiler/templates/compileTitleAndSubtitle.js +84 -0
  29. package/src/compiler/templates/compileTwoColumnText.js +116 -0
  30. package/src/compiler/templates/helpers/addIdToItems.js +17 -0
  31. package/src/compiler/templates/helpers/buildSequentialStates.js +24 -0
  32. package/src/compiler/templates/index.js +108 -0
  33. package/src/compiler/utils/applyBackground.js +9 -0
  34. package/src/compiler/utils/assignMockTimings.js +47 -0
  35. package/src/compiler/utils/compileTimings.js +16 -0
  36. package/src/compiler/utils/getDeckImages.js +40 -0
  37. package/src/compiler/utils/resolveAssetPaths.js +42 -0
  38. package/src/compiler/utils/resolveBackground.js +29 -0
  39. package/src/dsl/Taleem.js +400 -0
  40. package/src/dsl/TimelineContext.js +256 -0
  41. package/src/dsl/slides/BarChart.js +31 -0
  42. package/src/dsl/slides/BulletListBuilder.js +23 -0
  43. package/src/dsl/slides/Eq.js +65 -0
  44. package/src/dsl/slides/FillImage.js +25 -0
  45. package/src/dsl/slides/FocusListBuilder.js +37 -0
  46. package/src/dsl/slides/ImageGrid.js +25 -0
  47. package/src/dsl/slides/ImageLeftBulletsRight.js +37 -0
  48. package/src/dsl/slides/ImageRightBulletsLeft.js +37 -0
  49. package/src/dsl/slides/ImageSlide.js +25 -0
  50. package/src/dsl/slides/ImageStrip.js +25 -0
  51. package/src/dsl/slides/ImageWithCaption.js +37 -0
  52. package/src/dsl/slides/ImageWithTitle.js +37 -0
  53. package/src/dsl/slides/KeyIdeasSlide.js +31 -0
  54. package/src/dsl/slides/Progressbar.js +31 -0
  55. package/src/dsl/slides/QuoteSlide.js +37 -0
  56. package/src/dsl/slides/SkeletonSlideBuilder.js +43 -0
  57. package/src/dsl/slides/Table.js +25 -0
  58. package/src/dsl/slides/TextGrid.js +25 -0
  59. package/src/dsl/slides/TitleAndPara.js +37 -0
  60. package/src/dsl/slides/TitleAndSubtitle.js +37 -0
  61. package/src/dsl/slides/TwoColumnText.js +61 -0
  62. package/src/index.js +4 -0
  63. package/src/primitives/index.js +0 -0
  64. package/src/types/index.js +0 -0
  65. package/src/utils/index.js +0 -0
@@ -0,0 +1,57 @@
1
+ // /src/compiler/templates/compileTextGrid.js
2
+
3
+ import { addIdToItems } from "./helpers/addIdToItems.js";
4
+
5
+ export function compileTextGrid(slide) {
6
+ const rawItems = slide.data ?? [];
7
+
8
+ const items =
9
+ addIdToItems(rawItems);
10
+
11
+ const texts =
12
+ items.filter(
13
+ d => d.name === "text"
14
+ );
15
+
16
+ if (!texts.length) {
17
+ throw new Error(
18
+ "textGrid: requires text items"
19
+ );
20
+ }
21
+
22
+ const ids =
23
+ items.map(i => i.id);
24
+
25
+ const html = `
26
+ <section class="slide textGrid">
27
+
28
+ <div class="text-grid">
29
+
30
+ ${texts.map(text => `
31
+ <div
32
+ id="${text.id}"
33
+
34
+ class="
35
+ text-grid-item
36
+ hidden
37
+ ${text.classes || ""}
38
+ "
39
+ >
40
+ ${text.content}
41
+ </div>
42
+ `).join("")}
43
+
44
+ </div>
45
+
46
+ </section>
47
+ `;
48
+
49
+ return {
50
+ html,
51
+
52
+ animation:
53
+ "progressiveReveal",
54
+
55
+ ids
56
+ };
57
+ }
@@ -0,0 +1,79 @@
1
+
2
+ // /src/compiler/templates/compileTitleAndPara.js
3
+
4
+ import { addIdToItems } from "./helpers/addIdToItems.js";
5
+
6
+ export function compileTitleAndPara(slide) {
7
+ const rawItems = slide.data ?? [];
8
+
9
+ if (!rawItems.length) {
10
+ throw new Error(
11
+ "titleAndPara: requires data"
12
+ );
13
+ }
14
+
15
+ const items =
16
+ addIdToItems(rawItems);
17
+
18
+ const titleItem =
19
+ items.find(
20
+ d => d.name === "title"
21
+ );
22
+
23
+ const paraItem =
24
+ items.find(
25
+ d => d.name === "para"
26
+ );
27
+
28
+ if (!paraItem) {
29
+ throw new Error(
30
+ "titleAndPara: requires para"
31
+ );
32
+ }
33
+
34
+ const ids =
35
+ items.map(i => i.id);
36
+
37
+ const html = `
38
+ <section class="slide titleAndPara">
39
+
40
+ ${
41
+ titleItem
42
+ ? `
43
+ <h1
44
+ id="${titleItem.id}"
45
+
46
+ class="
47
+ hidden
48
+ taleem-heading-md
49
+ "
50
+ >
51
+ ${titleItem.content}
52
+ </h1>
53
+ `
54
+ : ""
55
+ }
56
+
57
+ <p
58
+ id="${paraItem.id}"
59
+
60
+ class="
61
+ hidden
62
+ taleem-para
63
+ "
64
+ >
65
+ ${paraItem.content}
66
+ </p>
67
+
68
+ </section>
69
+ `;
70
+
71
+ return {
72
+ html,
73
+
74
+ animation:
75
+ "progressiveReveal",
76
+
77
+ ids
78
+ };
79
+ }
@@ -0,0 +1,84 @@
1
+
2
+ // /src/compiler/templates/compileTitleAndSubtitle.js
3
+
4
+ import { addIdToItems } from "./helpers/addIdToItems.js";
5
+
6
+ export function compileTitleAndSubtitle(
7
+ slide
8
+ ) {
9
+ const rawItems =
10
+ slide.data ?? [];
11
+
12
+ if (!rawItems.length) {
13
+ throw new Error(
14
+ "titleAndSubtitle: requires title"
15
+ );
16
+ }
17
+
18
+ const items =
19
+ addIdToItems(rawItems);
20
+
21
+ const titleItem =
22
+ items.find(
23
+ d => d.name === "title"
24
+ );
25
+
26
+ const subtitleItem =
27
+ items.find(
28
+ d => d.name === "subtitle"
29
+ );
30
+
31
+ if (!titleItem) {
32
+ throw new Error(
33
+ "titleAndSubtitle: requires title"
34
+ );
35
+ }
36
+
37
+ const ids =
38
+ items.map(i => i.id);
39
+
40
+ const html = `
41
+ <section class="slide titleAndSubtitle">
42
+
43
+ <h1
44
+ id="${titleItem.id}"
45
+
46
+ class="
47
+ hidden
48
+ taleem-heading-lg
49
+ ${titleItem.classes || ""}
50
+ "
51
+ >
52
+ ${titleItem.content}
53
+ </h1>
54
+
55
+ ${
56
+ subtitleItem
57
+ ? `
58
+ <h2
59
+ id="${subtitleItem.id}"
60
+
61
+ class="
62
+ hidden
63
+ taleem-heading-md
64
+ ${subtitleItem.classes || ""}
65
+ "
66
+ >
67
+ ${subtitleItem.content}
68
+ </h2>
69
+ `
70
+ : ""
71
+ }
72
+
73
+ </section>
74
+ `;
75
+
76
+ return {
77
+ html,
78
+
79
+ animation:
80
+ "progressiveReveal",
81
+
82
+ ids
83
+ };
84
+ }
@@ -0,0 +1,116 @@
1
+ // /src/compiler/templates/compileTwoColumnText.js
2
+
3
+ import { addIdToItems } from "./helpers/addIdToItems.js";
4
+
5
+ export function compileTwoColumnText(
6
+ slide
7
+ ) {
8
+ const rawItems =
9
+ slide.data ?? [];
10
+
11
+ const items =
12
+ addIdToItems(rawItems);
13
+
14
+ const leftItems =
15
+ items.filter(
16
+ d =>
17
+ d.name === "leftText"
18
+ ||
19
+ d.name === "leftImage"
20
+ );
21
+
22
+ const rightItems =
23
+ items.filter(
24
+ d =>
25
+ d.name === "rightText"
26
+ ||
27
+ d.name === "rightImage"
28
+ );
29
+
30
+ if (
31
+ !leftItems.length
32
+ ||
33
+ !rightItems.length
34
+ ) {
35
+ throw new Error(
36
+ "twoColumnText: requires left and right content"
37
+ );
38
+ }
39
+
40
+ const ids =
41
+ items.map(i => i.id);
42
+
43
+ function renderItem(item) {
44
+ const classes =
45
+ item.classes || "";
46
+
47
+ if (
48
+ item.name === "leftText"
49
+ ||
50
+ item.name === "rightText"
51
+ ) {
52
+ return `
53
+ <div
54
+ id="${item.id}"
55
+
56
+ class="
57
+ hidden
58
+ ${classes}
59
+ "
60
+ >
61
+ ${item.content}
62
+ </div>
63
+ `;
64
+ }
65
+
66
+ if (
67
+ item.name === "leftImage"
68
+ ||
69
+ item.name === "rightImage"
70
+ ) {
71
+ return `
72
+ <img
73
+ id="${item.id}"
74
+
75
+ class="
76
+ hidden
77
+ ${classes}
78
+ "
79
+
80
+ src="${item.content}"
81
+
82
+ alt=""
83
+ />
84
+ `;
85
+ }
86
+
87
+ return "";
88
+ }
89
+
90
+ const html = `
91
+ <section class="slide twoColumnText">
92
+
93
+ <div class="col left">
94
+ ${leftItems
95
+ .map(renderItem)
96
+ .join("")}
97
+ </div>
98
+
99
+ <div class="col right">
100
+ ${rightItems
101
+ .map(renderItem)
102
+ .join("")}
103
+ </div>
104
+
105
+ </section>
106
+ `;
107
+
108
+ return {
109
+ html,
110
+
111
+ animation:
112
+ "progressiveReveal",
113
+
114
+ ids
115
+ };
116
+ }
@@ -0,0 +1,17 @@
1
+
2
+ let __idCounter = 0;
3
+
4
+ export function addIdToItems(items) {
5
+ if (!Array.isArray(items)) return [];
6
+
7
+ return items.map(item => {
8
+ __idCounter++;
9
+
10
+ const id = `i${Date.now().toString(36)}${__idCounter.toString(36)}`;
11
+
12
+ return {
13
+ ...item,
14
+ id
15
+ };
16
+ });
17
+ }
@@ -0,0 +1,24 @@
1
+
2
+
3
+ export function buildSequentialStates(timeline, allIds) {
4
+ const actions = [];
5
+ const visibleSet = new Set();
6
+
7
+ for (const step of timeline) {
8
+ visibleSet.add(step.id);
9
+
10
+ const visible = Array.from(visibleSet);
11
+
12
+ const hidden = allIds.filter(id => !visibleSet.has(id));
13
+
14
+ actions.push({
15
+ time: step.time,
16
+ state: {
17
+ visible,
18
+ hidden
19
+ }
20
+ });
21
+ }
22
+
23
+ return actions;
24
+ }
@@ -0,0 +1,108 @@
1
+ // /src/compiler/templates/index.js
2
+
3
+ import { compileBulletList } from "./compileBulletList.js";
4
+
5
+ import { compileSkeletonSlide } from "./compileSkeletonSlide.js";
6
+
7
+ import { compileFocusList } from "./compileFocusList.js";
8
+
9
+ import { compileEq } from "./compileEq.js";
10
+
11
+ import { compileTable } from "./compileTable.js";
12
+
13
+ import { compileBarChart } from "./compileBarChart.js";
14
+
15
+ import { compileProgressbar } from "./compileProgressbar.js";
16
+
17
+ import { compileTitleAndSubtitle } from "./compileTitleAndSubtitle.js";
18
+
19
+ import { compileTitleAndPara } from "./compileTitleAndPara.js";
20
+
21
+ import { compileTwoColumnText } from "./compileTwoColumnText.js";
22
+
23
+ import { compileImageSlide } from "./compileImageSlide.js";
24
+
25
+ import { compileImageWithTitle } from "./compileImageWithTitle.js";
26
+
27
+ import { compileImageWithCaption } from "./compileImageWithCaption.js";
28
+
29
+ import { compileImageLeftBulletsRight } from "./compileImageLeftBulletsRight.js";
30
+
31
+ import { compileImageRightBulletsLeft } from "./compileImageRightBulletsLeft.js";
32
+
33
+ import { compileQuoteSlide } from "./compileQuoteSlide.js";
34
+
35
+ import { compileKeyIdeasSlide } from "./compileKeyIdeasSlide.js";
36
+
37
+ import { compileFillImage } from "./compileFillImage.js";
38
+
39
+ import { compileImageStrip } from "./compileImageStrip.js";
40
+
41
+ import { compileImageGrid } from "./compileImageGrid.js";
42
+
43
+ import { compileTextGrid } from "./compileTextGrid.js";
44
+
45
+ export const templates = {
46
+ titleAndSubtitle:
47
+ compileTitleAndSubtitle,
48
+
49
+ titleAndPara:
50
+ compileTitleAndPara,
51
+
52
+ bulletList:
53
+ compileBulletList,
54
+
55
+ twoColumnText:
56
+ compileTwoColumnText,
57
+
58
+ imageSlide:
59
+ compileImageSlide,
60
+
61
+ imageWithTitle:
62
+ compileImageWithTitle,
63
+
64
+ imageWithCaption:
65
+ compileImageWithCaption,
66
+
67
+ imageLeftBulletsRight:
68
+ compileImageLeftBulletsRight,
69
+
70
+ imageRightBulletsLeft:
71
+ compileImageRightBulletsLeft,
72
+
73
+ table:
74
+ compileTable,
75
+
76
+ barChart:
77
+ compileBarChart,
78
+
79
+ progressbar:
80
+ compileProgressbar,
81
+
82
+ quoteSlide:
83
+ compileQuoteSlide,
84
+
85
+ keyIdeasSlide:
86
+ compileKeyIdeasSlide,
87
+
88
+ focusList:
89
+ compileFocusList,
90
+
91
+ eq:
92
+ compileEq,
93
+
94
+ fillImage:
95
+ compileFillImage,
96
+
97
+ imageStrip:
98
+ compileImageStrip,
99
+
100
+ imageGrid:
101
+ compileImageGrid,
102
+
103
+ textGrid:
104
+ compileTextGrid,
105
+
106
+ skeleton:
107
+ compileSkeletonSlide
108
+ };
@@ -0,0 +1,9 @@
1
+ export function applyBackground(el, background = {}) {
2
+ if (background.backgroundColor) {
3
+ el.style.backgroundColor = background.backgroundColor;
4
+ }
5
+
6
+ if (background.backgroundImage) {
7
+ el.style.backgroundImage = `url("${background.backgroundImage}")`;
8
+ }
9
+ }
@@ -0,0 +1,47 @@
1
+ // src/utils/assignMockTimings.js
2
+
3
+ /**
4
+ * Compile a golden / browser-ready deck into a player-ready deck
5
+ * by assigning mock absolute timings.
6
+ *
7
+ * @param {object} goldenDeck - deck object with a `deck` array
8
+ * @param {number} slideDuration - seconds per slide (default: 5)
9
+ * @returns {object} player-ready deck
10
+ */
11
+ export function assignMockTimings(goldenDeck, slideDuration = 5) {
12
+ if (
13
+ !goldenDeck ||
14
+ !Array.isArray(goldenDeck.deck) ||
15
+ typeof slideDuration !== "number"
16
+ ) {
17
+ throw new Error("assignMockTimings: invalid deck or slideDuration");
18
+ }
19
+
20
+ let currentTime = 0;
21
+
22
+ const deckWithTimings = {
23
+ ...goldenDeck,
24
+ deck: goldenDeck.deck.map(slide => {
25
+ const start = currentTime;
26
+ const end = start + slideDuration;
27
+ currentTime = end;
28
+
29
+ const data = Array.isArray(slide.data)
30
+ ? slide.data.map(item => ({
31
+ ...item,
32
+ showAt:
33
+ start + (typeof item.showAt === "number" ? item.showAt : 0)
34
+ }))
35
+ : slide.data;
36
+
37
+ return {
38
+ ...slide,
39
+ start,
40
+ end,
41
+ data
42
+ };
43
+ })
44
+ };
45
+
46
+ return deckWithTimings;
47
+ }
@@ -0,0 +1,16 @@
1
+ // /src/dsl/compileTimings.js
2
+
3
+ export function compileTimings(deck, presentationEnd) {
4
+ for (let i = 0; i < deck.length; i++) {
5
+ const currentSlide = deck[i];
6
+ const nextSlide = deck[i + 1];
7
+
8
+ if (nextSlide) {
9
+ currentSlide.end = nextSlide.start;
10
+ } else {
11
+ currentSlide.end = presentationEnd;
12
+ }
13
+ }
14
+
15
+ return deck;
16
+ }
@@ -0,0 +1,40 @@
1
+ // getDeckImages.js
2
+
3
+ export function getDeckImages(deck) {
4
+ const images = new Set();
5
+
6
+ // -----------------------------
7
+ // background image
8
+ // -----------------------------
9
+ if (
10
+ deck.background?.backgroundImage &&
11
+ typeof deck.background.backgroundImage === "string"
12
+ ) {
13
+ images.add(deck.background.backgroundImage.split("/").pop());
14
+ }
15
+
16
+ // -----------------------------
17
+ // slide-level images
18
+ // -----------------------------
19
+ if (!Array.isArray(deck.deck)) return [];
20
+
21
+ deck.deck.forEach(slide => {
22
+ slide.data?.forEach(item => {
23
+ // normal image
24
+ if (item.name === "image" && typeof item.content === "string") {
25
+ images.add(item.content.split("/").pop());
26
+ }
27
+
28
+ // EQ side panel spImage
29
+ if (Array.isArray(item.spItems)) {
30
+ item.spItems.forEach(sp => {
31
+ if (sp.type === "spImage" && typeof sp.content === "string") {
32
+ images.add(sp.content.split("/").pop());
33
+ }
34
+ });
35
+ }
36
+ });
37
+ });
38
+
39
+ return Array.from(images);
40
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Resolve image paths in a deck.
3
+ * App-level utility. Mutates deck in place.
4
+ */
5
+ export function resolveAssetPaths(deck, IMG_BASE) {
6
+ // -----------------------------
7
+ // background image
8
+ // -----------------------------
9
+ if (
10
+ deck.background?.backgroundImage &&
11
+ typeof deck.background.backgroundImage === "string"
12
+ ) {
13
+ deck.background.backgroundImage =
14
+ IMG_BASE + deck.background.backgroundImage.split("/").pop();
15
+ }
16
+
17
+ // -----------------------------
18
+ // slide-level images
19
+ // -----------------------------
20
+ deck.deck.forEach(slide => {
21
+ slide.data?.forEach(item => {
22
+ // normal image slides
23
+ if (item.name === "image" && typeof item.content === "string") {
24
+ item.content = IMG_BASE + item.content.split("/").pop();
25
+ }
26
+
27
+ // -----------------------------
28
+ // EQ side-panel images (spImage)
29
+ // -----------------------------
30
+ if (Array.isArray(item.spItems)) {
31
+ item.spItems.forEach(sp => {
32
+ // if (sp.type === "spImage" && typeof sp.content === "string") {
33
+ if (sp.name === "image" && typeof sp.content === "string") {
34
+ sp.content = IMG_BASE + sp.content.split("/").pop();
35
+ }
36
+ });
37
+ }
38
+ });
39
+ });
40
+
41
+ return deck;
42
+ }
@@ -0,0 +1,29 @@
1
+
2
+ /**
3
+ * Resolve background assets for a deck.
4
+ * App-level utility. Mutates deck in place.
5
+ *
6
+ * @param {object} deck - deck-v1 object
7
+ * @param {string} ASSET_BASE - base path for assets (e.g. "/images/")
8
+ */
9
+ export function resolveBackground(deck, ASSET_BASE) {
10
+ if (!deck || !deck.background) return deck;
11
+
12
+ const bg = deck.background;
13
+
14
+ if (
15
+ typeof bg.backgroundImage === "string" &&
16
+ bg.backgroundImage.length > 0
17
+ ) {
18
+ bg.backgroundImage =
19
+ ASSET_BASE + bg.backgroundImage.split("/").pop();
20
+ }
21
+
22
+ // defaults (defensive, not opinionated)
23
+ if (bg.backgroundImageOpacity === undefined) {
24
+ bg.backgroundImageOpacity = 1;
25
+ }
26
+
27
+ return deck;
28
+ }
29
+