yumiamd 0.1.7 → 0.1.8
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-GMIVPFBA.js → chunk-WUJKHJJU.js} +691 -56
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -3
- package/package.json +8 -8
package/dist/bin.js
CHANGED
|
@@ -47,6 +47,17 @@ function createCard(elements, title, variant) {
|
|
|
47
47
|
...variant ? { variant } : {}
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
+
function createMetric(value, label, variant, description, unit, change) {
|
|
51
|
+
return {
|
|
52
|
+
type: "metric",
|
|
53
|
+
value,
|
|
54
|
+
label,
|
|
55
|
+
...variant ? { variant } : {},
|
|
56
|
+
...description ? { description } : {},
|
|
57
|
+
...unit ? { unit } : {},
|
|
58
|
+
...change ? { change } : {}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
50
61
|
function createCode(code, language, highlightLines) {
|
|
51
62
|
return {
|
|
52
63
|
type: "code",
|
|
@@ -111,13 +122,14 @@ var DefaultYumiaParser = class {
|
|
|
111
122
|
}
|
|
112
123
|
const normalized = source.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
113
124
|
const { metadata, content, lineOffset } = this.extractFrontmatter(normalized);
|
|
125
|
+
if (!content.trim()) {
|
|
126
|
+
return createPresentation(metadata, []);
|
|
127
|
+
}
|
|
114
128
|
const slideChunks = this.splitSlides(content, lineOffset);
|
|
115
129
|
const slides = [];
|
|
116
130
|
for (const chunk of slideChunks) {
|
|
117
131
|
const slide = this.parseSlide(chunk.content, chunk.startLine);
|
|
118
|
-
|
|
119
|
-
slides.push(slide);
|
|
120
|
-
}
|
|
132
|
+
slides.push(slide);
|
|
121
133
|
}
|
|
122
134
|
const presentation = createPresentation(metadata, slides);
|
|
123
135
|
if (this.diagnostics.length > 0) {
|
|
@@ -346,6 +358,28 @@ var DefaultYumiaParser = class {
|
|
|
346
358
|
i++;
|
|
347
359
|
continue;
|
|
348
360
|
}
|
|
361
|
+
if (directiveHeader.startsWith("metric")) {
|
|
362
|
+
const valueMatch = directiveHeader.match(/value=['"](.*?)['"]/);
|
|
363
|
+
const labelMatch = directiveHeader.match(/label=['"](.*?)['"]/);
|
|
364
|
+
const variantMatch = directiveHeader.match(/variant=['"](.*?)['"]/);
|
|
365
|
+
const descMatch = directiveHeader.match(/description=['"](.*?)['"]/);
|
|
366
|
+
const unitMatch = directiveHeader.match(/unit=['"](.*?)['"]/);
|
|
367
|
+
const changeMatch = directiveHeader.match(/change=['"](.*?)['"]/);
|
|
368
|
+
const value = valueMatch ? valueMatch[1] : "0";
|
|
369
|
+
const label = labelMatch ? labelMatch[1] : "";
|
|
370
|
+
const variant = variantMatch ? variantMatch[1] : void 0;
|
|
371
|
+
const desc = descMatch ? descMatch[1] : void 0;
|
|
372
|
+
const unit = unitMatch ? unitMatch[1] : void 0;
|
|
373
|
+
const change = changeMatch ? changeMatch[1] : void 0;
|
|
374
|
+
const el = createMetric(value, label, variant, desc, unit, change);
|
|
375
|
+
el.loc = {
|
|
376
|
+
start: { line: currentLineNum, column: 1 },
|
|
377
|
+
end: { line: currentLineNum, column: rawLine.length + 1 }
|
|
378
|
+
};
|
|
379
|
+
elements.push(el);
|
|
380
|
+
i++;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
349
383
|
const [directiveName, ...args] = directiveHeader.split(" ");
|
|
350
384
|
const directiveArg = args.join(" ").trim();
|
|
351
385
|
const blockLines = [];
|
|
@@ -354,7 +388,8 @@ var DefaultYumiaParser = class {
|
|
|
354
388
|
let closed = false;
|
|
355
389
|
while (i < lines.length) {
|
|
356
390
|
const innerLine = lines[i]?.trim() ?? "";
|
|
357
|
-
|
|
391
|
+
const isSingleLine = innerLine.startsWith(":::metric") || innerLine.startsWith(":::layout");
|
|
392
|
+
if (innerLine.startsWith(":::") && innerLine.length > 3 && !isSingleLine) {
|
|
358
393
|
nestedCount++;
|
|
359
394
|
} else if (innerLine === ":::") {
|
|
360
395
|
nestedCount--;
|
|
@@ -382,9 +417,17 @@ var DefaultYumiaParser = class {
|
|
|
382
417
|
if (directiveName === "notes") {
|
|
383
418
|
notes = blockLines.map((l) => l.trim()).filter(Boolean).join("\n");
|
|
384
419
|
} else if (directiveName === "card") {
|
|
385
|
-
|
|
420
|
+
let cardTitle;
|
|
421
|
+
let cardVariant;
|
|
422
|
+
const variantMatch = directiveArg.match(/variant=['"](.*?)['"]/);
|
|
423
|
+
if (variantMatch) {
|
|
424
|
+
cardVariant = variantMatch[1];
|
|
425
|
+
cardTitle = directiveArg.replace(/variant=['"].*?['"]/, "").trim().replace(/^['"](.*)['"]$/, "$1") || void 0;
|
|
426
|
+
} else {
|
|
427
|
+
cardTitle = directiveArg.replace(/^['"](.*)['"]$/, "$1") || void 0;
|
|
428
|
+
}
|
|
386
429
|
const { elements: cardElements } = this.parseLines(blockLines, blockBaseLine);
|
|
387
|
-
const el = createCard(cardElements,
|
|
430
|
+
const el = createCard(cardElements, cardTitle, cardVariant);
|
|
388
431
|
el.loc = {
|
|
389
432
|
start: { line: directiveStartLine, column: 1 },
|
|
390
433
|
end: { line: baseLine + i - 1, column: 1 }
|
|
@@ -530,7 +573,8 @@ var DefaultYumiaParser = class {
|
|
|
530
573
|
let nestedCount = 1;
|
|
531
574
|
while (i < lines.length) {
|
|
532
575
|
const innerLine = lines[i]?.trim() ?? "";
|
|
533
|
-
|
|
576
|
+
const isSingleLine = innerLine.startsWith(":::metric") || innerLine.startsWith(":::layout");
|
|
577
|
+
if (innerLine.startsWith(":::") && innerLine.length > 3 && !isSingleLine) {
|
|
534
578
|
nestedCount++;
|
|
535
579
|
} else if (innerLine === ":::") {
|
|
536
580
|
nestedCount--;
|
|
@@ -645,6 +689,10 @@ var DefaultLayoutEngine = class {
|
|
|
645
689
|
const height = this.estimateImageHeight(element);
|
|
646
690
|
return { element, bounds: { x, y, width, height } };
|
|
647
691
|
}
|
|
692
|
+
case "metric": {
|
|
693
|
+
const height = this.estimateMetricHeight(element);
|
|
694
|
+
return { element, bounds: { x, y, width, height } };
|
|
695
|
+
}
|
|
648
696
|
case "card": {
|
|
649
697
|
return this.layoutCard(element, x, y, width, gap);
|
|
650
698
|
}
|
|
@@ -759,6 +807,9 @@ var DefaultLayoutEngine = class {
|
|
|
759
807
|
}
|
|
760
808
|
return 320;
|
|
761
809
|
}
|
|
810
|
+
estimateMetricHeight(metric) {
|
|
811
|
+
return metric.change ? 140 : 120;
|
|
812
|
+
}
|
|
762
813
|
};
|
|
763
814
|
|
|
764
815
|
// ../theme/dist/default-theme.js
|
|
@@ -773,7 +824,11 @@ var defaultTheme = {
|
|
|
773
824
|
text: "#0f172a",
|
|
774
825
|
muted: "#64748b",
|
|
775
826
|
accent: "#06b6d4",
|
|
776
|
-
border: "#e2e8f0"
|
|
827
|
+
border: "#e2e8f0",
|
|
828
|
+
success: "#10b981",
|
|
829
|
+
warning: "#f59e0b",
|
|
830
|
+
danger: "#ef4444",
|
|
831
|
+
info: "#3b82f6"
|
|
777
832
|
},
|
|
778
833
|
typography: {
|
|
779
834
|
headingFont: "Inter, system-ui, -apple-system, sans-serif",
|
|
@@ -830,29 +885,523 @@ var defaultTheme = {
|
|
|
830
885
|
}
|
|
831
886
|
}
|
|
832
887
|
};
|
|
833
|
-
|
|
888
|
+
var cyberpunkTheme = {
|
|
889
|
+
name: "cyberpunk",
|
|
890
|
+
description: "High-energy dark cyberpunk theme with neon pink and cyan accents",
|
|
891
|
+
colors: {
|
|
892
|
+
primary: "#FF2E88",
|
|
893
|
+
secondary: "#00F0FF",
|
|
894
|
+
background: "#0B0B12",
|
|
895
|
+
surface: "#151522",
|
|
896
|
+
text: "#FFFFFF",
|
|
897
|
+
muted: "#A7A7B5",
|
|
898
|
+
accent: "#7B61FF",
|
|
899
|
+
border: "#2E2E48",
|
|
900
|
+
success: "#00FF9F",
|
|
901
|
+
warning: "#FFE600",
|
|
902
|
+
danger: "#FF0055",
|
|
903
|
+
info: "#00F0FF"
|
|
904
|
+
},
|
|
905
|
+
typography: {
|
|
906
|
+
headingFont: "Outfit, Inter, sans-serif",
|
|
907
|
+
bodyFont: "Inter, sans-serif",
|
|
908
|
+
codeFont: "JetBrains Mono, monospace",
|
|
909
|
+
sizes: {
|
|
910
|
+
h1: 46,
|
|
911
|
+
h2: 38,
|
|
912
|
+
h3: 28,
|
|
913
|
+
h4: 22,
|
|
914
|
+
body: 18,
|
|
915
|
+
small: 14,
|
|
916
|
+
code: 16
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
spacing: {
|
|
920
|
+
unit: 8,
|
|
921
|
+
slidePadding: 48,
|
|
922
|
+
elementGap: 28
|
|
923
|
+
},
|
|
924
|
+
radius: {
|
|
925
|
+
default: 12,
|
|
926
|
+
sm: 6,
|
|
927
|
+
md: 12,
|
|
928
|
+
lg: 20,
|
|
929
|
+
full: 9999
|
|
930
|
+
},
|
|
931
|
+
components: {
|
|
932
|
+
card: {
|
|
933
|
+
background: "#151522",
|
|
934
|
+
borderColor: "#FF2E88",
|
|
935
|
+
borderRadius: 16,
|
|
936
|
+
padding: 28
|
|
937
|
+
},
|
|
938
|
+
code: {
|
|
939
|
+
background: "#07070D",
|
|
940
|
+
textColor: "#00F0FF",
|
|
941
|
+
borderRadius: 8
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
var minimalTheme = {
|
|
946
|
+
name: "minimal",
|
|
947
|
+
description: "Monochrome Swiss-style design with maximum clarity and contrast",
|
|
948
|
+
colors: {
|
|
949
|
+
primary: "#111111",
|
|
950
|
+
secondary: "#333333",
|
|
951
|
+
background: "#FFFFFF",
|
|
952
|
+
surface: "#F5F5F7",
|
|
953
|
+
text: "#111111",
|
|
954
|
+
muted: "#777777",
|
|
955
|
+
accent: "#000000",
|
|
956
|
+
border: "#E5E5E5",
|
|
957
|
+
success: "#10B981",
|
|
958
|
+
warning: "#F59E0B",
|
|
959
|
+
danger: "#EF4444",
|
|
960
|
+
info: "#3B82F6"
|
|
961
|
+
},
|
|
962
|
+
typography: {
|
|
963
|
+
headingFont: "Helvetica Neue, Arial, sans-serif",
|
|
964
|
+
bodyFont: "Helvetica Neue, Arial, sans-serif",
|
|
965
|
+
codeFont: "Menlo, Monaco, monospace",
|
|
966
|
+
sizes: {
|
|
967
|
+
h1: 44,
|
|
968
|
+
h2: 34,
|
|
969
|
+
h3: 26,
|
|
970
|
+
h4: 20,
|
|
971
|
+
body: 18,
|
|
972
|
+
small: 14,
|
|
973
|
+
code: 15
|
|
974
|
+
}
|
|
975
|
+
},
|
|
976
|
+
spacing: {
|
|
977
|
+
unit: 8,
|
|
978
|
+
slidePadding: 56,
|
|
979
|
+
elementGap: 24
|
|
980
|
+
},
|
|
981
|
+
radius: {
|
|
982
|
+
default: 4,
|
|
983
|
+
sm: 2,
|
|
984
|
+
md: 4,
|
|
985
|
+
lg: 8,
|
|
986
|
+
full: 9999
|
|
987
|
+
},
|
|
988
|
+
components: {
|
|
989
|
+
card: {
|
|
990
|
+
background: "#F5F5F7",
|
|
991
|
+
borderColor: "#E5E5E5",
|
|
992
|
+
borderRadius: 6,
|
|
993
|
+
padding: 24
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
var corporateTheme = {
|
|
998
|
+
name: "corporate",
|
|
999
|
+
description: "Executive navy blue palette tailored for business and enterprise decks",
|
|
1000
|
+
colors: {
|
|
1001
|
+
primary: "#0A2540",
|
|
1002
|
+
secondary: "#635BFF",
|
|
1003
|
+
background: "#FFFFFF",
|
|
1004
|
+
surface: "#F8FAFC",
|
|
1005
|
+
text: "#1A1F36",
|
|
1006
|
+
muted: "#4F566B",
|
|
1007
|
+
accent: "#00D4B2",
|
|
1008
|
+
border: "#E3E8EE",
|
|
1009
|
+
success: "#00D4B2",
|
|
1010
|
+
warning: "#FFC043",
|
|
1011
|
+
danger: "#DF1B41",
|
|
1012
|
+
info: "#635BFF"
|
|
1013
|
+
},
|
|
1014
|
+
typography: {
|
|
1015
|
+
headingFont: "Inter, Segoe UI, sans-serif",
|
|
1016
|
+
bodyFont: "Inter, Segoe UI, sans-serif",
|
|
1017
|
+
codeFont: "Consolas, monospace",
|
|
1018
|
+
sizes: {
|
|
1019
|
+
h1: 42,
|
|
1020
|
+
h2: 34,
|
|
1021
|
+
h3: 26,
|
|
1022
|
+
h4: 20,
|
|
1023
|
+
body: 18,
|
|
1024
|
+
small: 14,
|
|
1025
|
+
code: 15
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
spacing: {
|
|
1029
|
+
unit: 8,
|
|
1030
|
+
slidePadding: 48,
|
|
1031
|
+
elementGap: 24
|
|
1032
|
+
},
|
|
1033
|
+
radius: {
|
|
1034
|
+
default: 8,
|
|
1035
|
+
sm: 4,
|
|
1036
|
+
md: 8,
|
|
1037
|
+
lg: 12,
|
|
1038
|
+
full: 9999
|
|
1039
|
+
},
|
|
1040
|
+
components: {
|
|
1041
|
+
card: {
|
|
1042
|
+
background: "#F8FAFC",
|
|
1043
|
+
borderColor: "#0A2540",
|
|
1044
|
+
borderRadius: 8,
|
|
1045
|
+
padding: 24
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
var terminalTheme = {
|
|
1050
|
+
name: "terminal",
|
|
1051
|
+
description: "Retro hacker green-on-dark theme with pure monospace aesthetic",
|
|
1052
|
+
colors: {
|
|
1053
|
+
primary: "#00FF66",
|
|
1054
|
+
secondary: "#33FF88",
|
|
1055
|
+
background: "#0C100C",
|
|
1056
|
+
surface: "#141A14",
|
|
1057
|
+
text: "#E0FFE0",
|
|
1058
|
+
muted: "#4E7A4E",
|
|
1059
|
+
accent: "#FFB000",
|
|
1060
|
+
border: "#1F331F",
|
|
1061
|
+
success: "#00FF66",
|
|
1062
|
+
warning: "#FFB000",
|
|
1063
|
+
danger: "#FF3333",
|
|
1064
|
+
info: "#00E5FF"
|
|
1065
|
+
},
|
|
1066
|
+
typography: {
|
|
1067
|
+
headingFont: "JetBrains Mono, Courier New, monospace",
|
|
1068
|
+
bodyFont: "JetBrains Mono, Courier New, monospace",
|
|
1069
|
+
codeFont: "JetBrains Mono, Courier New, monospace",
|
|
1070
|
+
sizes: {
|
|
1071
|
+
h1: 40,
|
|
1072
|
+
h2: 32,
|
|
1073
|
+
h3: 26,
|
|
1074
|
+
h4: 20,
|
|
1075
|
+
body: 17,
|
|
1076
|
+
small: 13,
|
|
1077
|
+
code: 15
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
spacing: {
|
|
1081
|
+
unit: 8,
|
|
1082
|
+
slidePadding: 48,
|
|
1083
|
+
elementGap: 24
|
|
1084
|
+
},
|
|
1085
|
+
radius: {
|
|
1086
|
+
default: 0,
|
|
1087
|
+
sm: 0,
|
|
1088
|
+
md: 0,
|
|
1089
|
+
lg: 0,
|
|
1090
|
+
full: 0
|
|
1091
|
+
},
|
|
1092
|
+
components: {
|
|
1093
|
+
card: {
|
|
1094
|
+
background: "#141A14",
|
|
1095
|
+
borderColor: "#00FF66",
|
|
1096
|
+
borderRadius: 0,
|
|
1097
|
+
padding: 24
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
var academicTheme = {
|
|
1102
|
+
name: "academic",
|
|
1103
|
+
description: "Scholarly paper theme with serif typography and crimson accents",
|
|
1104
|
+
colors: {
|
|
1105
|
+
primary: "#8B0000",
|
|
1106
|
+
secondary: "#1C3F60",
|
|
1107
|
+
background: "#FCFBF7",
|
|
1108
|
+
surface: "#F5F2EB",
|
|
1109
|
+
text: "#2C2B29",
|
|
1110
|
+
muted: "#6B6862",
|
|
1111
|
+
accent: "#C29B38",
|
|
1112
|
+
border: "#E0DACD",
|
|
1113
|
+
success: "#2E7D32",
|
|
1114
|
+
warning: "#E65100",
|
|
1115
|
+
danger: "#C62828",
|
|
1116
|
+
info: "#1565C0"
|
|
1117
|
+
},
|
|
1118
|
+
typography: {
|
|
1119
|
+
headingFont: "Georgia, Times New Roman, serif",
|
|
1120
|
+
bodyFont: "Georgia, Times New Roman, serif",
|
|
1121
|
+
codeFont: "Courier New, monospace",
|
|
1122
|
+
sizes: {
|
|
1123
|
+
h1: 42,
|
|
1124
|
+
h2: 34,
|
|
1125
|
+
h3: 26,
|
|
1126
|
+
h4: 20,
|
|
1127
|
+
body: 18,
|
|
1128
|
+
small: 14,
|
|
1129
|
+
code: 15
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
spacing: {
|
|
1133
|
+
unit: 8,
|
|
1134
|
+
slidePadding: 52,
|
|
1135
|
+
elementGap: 24
|
|
1136
|
+
},
|
|
1137
|
+
radius: {
|
|
1138
|
+
default: 4,
|
|
1139
|
+
sm: 2,
|
|
1140
|
+
md: 4,
|
|
1141
|
+
lg: 6,
|
|
1142
|
+
full: 9999
|
|
1143
|
+
},
|
|
1144
|
+
components: {
|
|
1145
|
+
card: {
|
|
1146
|
+
background: "#F5F2EB",
|
|
1147
|
+
borderColor: "#8B0000",
|
|
1148
|
+
borderRadius: 4,
|
|
1149
|
+
padding: 24
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
var THEME_REGISTRY = {
|
|
1154
|
+
default: defaultTheme,
|
|
1155
|
+
cyberpunk: cyberpunkTheme,
|
|
1156
|
+
minimal: minimalTheme,
|
|
1157
|
+
corporate: corporateTheme,
|
|
1158
|
+
terminal: terminalTheme,
|
|
1159
|
+
academic: academicTheme
|
|
1160
|
+
};
|
|
1161
|
+
function resolveTheme(themeNameOrRef, explicitOverrides) {
|
|
1162
|
+
const name = typeof themeNameOrRef === "string" ? themeNameOrRef : themeNameOrRef?.name || "default";
|
|
1163
|
+
const baseTheme = THEME_REGISTRY[name.toLowerCase()] || defaultTheme;
|
|
1164
|
+
const refOverrides = typeof themeNameOrRef === "object" ? themeNameOrRef.overrides : void 0;
|
|
1165
|
+
const mergedOverrides = {
|
|
1166
|
+
...refOverrides,
|
|
1167
|
+
...explicitOverrides,
|
|
1168
|
+
colors: { ...baseTheme.colors, ...refOverrides?.colors, ...explicitOverrides?.colors },
|
|
1169
|
+
typography: {
|
|
1170
|
+
...baseTheme.typography,
|
|
1171
|
+
...refOverrides?.typography,
|
|
1172
|
+
...explicitOverrides?.typography
|
|
1173
|
+
},
|
|
1174
|
+
components: {
|
|
1175
|
+
...baseTheme.components,
|
|
1176
|
+
...refOverrides?.components,
|
|
1177
|
+
...explicitOverrides?.components
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
834
1180
|
return {
|
|
835
|
-
...
|
|
836
|
-
...
|
|
837
|
-
colors: { ...defaultTheme.colors, ...overrides.colors },
|
|
838
|
-
typography: { ...defaultTheme.typography, ...overrides.typography },
|
|
839
|
-
spacing: { ...defaultTheme.spacing, ...overrides.spacing },
|
|
840
|
-
radius: { ...defaultTheme.radius, ...overrides.radius },
|
|
841
|
-
shadows: { ...defaultTheme.shadows, ...overrides.shadows },
|
|
842
|
-
components: { ...defaultTheme.components, ...overrides.components }
|
|
1181
|
+
...baseTheme,
|
|
1182
|
+
...mergedOverrides
|
|
843
1183
|
};
|
|
844
1184
|
}
|
|
1185
|
+
function createTheme(overrides) {
|
|
1186
|
+
return resolveTheme(overrides.name, overrides);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// ../core/dist/linter.js
|
|
1190
|
+
var YumiaLinter = class {
|
|
1191
|
+
layoutEngine;
|
|
1192
|
+
constructor(layoutEngine) {
|
|
1193
|
+
this.layoutEngine = layoutEngine ?? new DefaultLayoutEngine();
|
|
1194
|
+
}
|
|
1195
|
+
lint(presentation, options = {}) {
|
|
1196
|
+
const issues = [];
|
|
1197
|
+
const layout = this.layoutEngine.computePresentation(presentation, options.viewport);
|
|
1198
|
+
if (presentation.diagnostics) {
|
|
1199
|
+
for (const diag of presentation.diagnostics) {
|
|
1200
|
+
issues.push({
|
|
1201
|
+
code: diag.code || "YUM002",
|
|
1202
|
+
slide: 1,
|
|
1203
|
+
message: diag.message,
|
|
1204
|
+
severity: diag.severity === "error" ? "error" : "warning",
|
|
1205
|
+
loc: diag.loc
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
presentation.slides.forEach((slide, index) => {
|
|
1210
|
+
const slideNum = index + 1;
|
|
1211
|
+
const slideLayout = layout.slides[index];
|
|
1212
|
+
if (slide.elements.length === 0) {
|
|
1213
|
+
issues.push({
|
|
1214
|
+
code: "YUM006",
|
|
1215
|
+
slide: slideNum,
|
|
1216
|
+
message: "Slide contains no content elements.",
|
|
1217
|
+
severity: "warning",
|
|
1218
|
+
loc: slide.loc
|
|
1219
|
+
});
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (slideLayout && slideLayout.overflow) {
|
|
1223
|
+
const overflowPx = Math.round(slideLayout.overflowAmount || 0);
|
|
1224
|
+
issues.push({
|
|
1225
|
+
code: "YUM001",
|
|
1226
|
+
slide: slideNum,
|
|
1227
|
+
message: `Content exceeds slide viewport bounds by ~${overflowPx}px. Consider reducing font size or splitting into multiple slides.`,
|
|
1228
|
+
severity: options.strict ? "error" : "warning",
|
|
1229
|
+
loc: slide.loc
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
const hasHeading = this.slideHasHeading(slide.elements);
|
|
1233
|
+
if (!hasHeading) {
|
|
1234
|
+
issues.push({
|
|
1235
|
+
code: "YUM003",
|
|
1236
|
+
slide: slideNum,
|
|
1237
|
+
message: "Slide has no heading (h1-h4). Consider adding a descriptive title for structure.",
|
|
1238
|
+
severity: "warning",
|
|
1239
|
+
loc: slide.loc
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
const { listCount, wordCount } = this.calculateSlideDensity(slide.elements);
|
|
1243
|
+
if (listCount > 7) {
|
|
1244
|
+
issues.push({
|
|
1245
|
+
code: "YUM004",
|
|
1246
|
+
slide: slideNum,
|
|
1247
|
+
message: `High information density: slide contains ${listCount} list items (recommended max: 7).`,
|
|
1248
|
+
severity: "warning",
|
|
1249
|
+
loc: slide.loc
|
|
1250
|
+
});
|
|
1251
|
+
} else if (wordCount > 120) {
|
|
1252
|
+
issues.push({
|
|
1253
|
+
code: "YUM004",
|
|
1254
|
+
slide: slideNum,
|
|
1255
|
+
message: `High information density: slide contains ~${wordCount} words (recommended max: 120 words).`,
|
|
1256
|
+
severity: "warning",
|
|
1257
|
+
loc: slide.loc
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
this.checkImages(slide.elements, slideNum, issues);
|
|
1261
|
+
const maxDepth = this.getMaxNestingDepth(slide.elements, 0);
|
|
1262
|
+
if (maxDepth > 2) {
|
|
1263
|
+
issues.push({
|
|
1264
|
+
code: "YUM008",
|
|
1265
|
+
slide: slideNum,
|
|
1266
|
+
message: `Excessive directive nesting depth (${maxDepth} levels). Maximum recommended depth is 2.`,
|
|
1267
|
+
severity: "warning",
|
|
1268
|
+
loc: slide.loc
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
if (options.includeOptionalNotesRule && (!slide.notes || slide.notes.trim() === "")) {
|
|
1272
|
+
issues.push({
|
|
1273
|
+
code: "YUM009",
|
|
1274
|
+
slide: slideNum,
|
|
1275
|
+
message: "Slide has no speaker notes (:::notes directive).",
|
|
1276
|
+
severity: "info",
|
|
1277
|
+
loc: slide.loc
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
});
|
|
1281
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
1282
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
1283
|
+
const infos = issues.filter((i) => i.severity === "info");
|
|
1284
|
+
return {
|
|
1285
|
+
passed: options.strict ? errors.length === 0 && warnings.length === 0 : errors.length === 0,
|
|
1286
|
+
totalSlides: presentation.slides.length,
|
|
1287
|
+
issueCount: issues.length,
|
|
1288
|
+
errors,
|
|
1289
|
+
warnings,
|
|
1290
|
+
infos
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
slideHasHeading(elements) {
|
|
1294
|
+
for (const el of elements) {
|
|
1295
|
+
if (el.type === "heading")
|
|
1296
|
+
return true;
|
|
1297
|
+
if (el.type === "card" && el.title)
|
|
1298
|
+
return true;
|
|
1299
|
+
if (el.type === "columns") {
|
|
1300
|
+
const cols = el.columns;
|
|
1301
|
+
for (const col of cols) {
|
|
1302
|
+
if (this.slideHasHeading(col.elements))
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
calculateSlideDensity(elements) {
|
|
1310
|
+
let listCount = 0;
|
|
1311
|
+
let wordCount = 0;
|
|
1312
|
+
const traverse = (els) => {
|
|
1313
|
+
for (const el of els) {
|
|
1314
|
+
if (el.type === "list") {
|
|
1315
|
+
const list = el;
|
|
1316
|
+
listCount += list.items.length;
|
|
1317
|
+
for (const item of list.items) {
|
|
1318
|
+
wordCount += item.text.split(/\s+/).filter(Boolean).length;
|
|
1319
|
+
}
|
|
1320
|
+
} else if (el.type === "paragraph") {
|
|
1321
|
+
const p = el;
|
|
1322
|
+
wordCount += p.text.split(/\s+/).filter(Boolean).length;
|
|
1323
|
+
} else if (el.type === "card") {
|
|
1324
|
+
const card = el;
|
|
1325
|
+
if (card.title)
|
|
1326
|
+
wordCount += card.title.split(/\s+/).filter(Boolean).length;
|
|
1327
|
+
if (card.elements)
|
|
1328
|
+
traverse(card.elements);
|
|
1329
|
+
} else if (el.type === "columns") {
|
|
1330
|
+
const cols = el;
|
|
1331
|
+
for (const col of cols.columns) {
|
|
1332
|
+
traverse(col.elements);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
traverse(elements);
|
|
1338
|
+
return { listCount, wordCount };
|
|
1339
|
+
}
|
|
1340
|
+
checkImages(elements, slideNum, issues) {
|
|
1341
|
+
const traverse = (els) => {
|
|
1342
|
+
for (const el of els) {
|
|
1343
|
+
if (el.type === "image") {
|
|
1344
|
+
const img = el;
|
|
1345
|
+
if (!img.alt || img.alt.trim() === "") {
|
|
1346
|
+
issues.push({
|
|
1347
|
+
code: "YUM007",
|
|
1348
|
+
slide: slideNum,
|
|
1349
|
+
message: `Image '${img.src}' is missing descriptive alt text for accessibility.`,
|
|
1350
|
+
severity: "warning",
|
|
1351
|
+
loc: img.loc
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
if (!img.src || img.src.trim() === "") {
|
|
1355
|
+
issues.push({
|
|
1356
|
+
code: "YUM005",
|
|
1357
|
+
slide: slideNum,
|
|
1358
|
+
message: "Image element has empty src attribute.",
|
|
1359
|
+
severity: "error",
|
|
1360
|
+
loc: img.loc
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
} else if (el.type === "card" && el.elements) {
|
|
1364
|
+
traverse(el.elements);
|
|
1365
|
+
} else if (el.type === "columns") {
|
|
1366
|
+
for (const col of el.columns) {
|
|
1367
|
+
traverse(col.elements);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
traverse(elements);
|
|
1373
|
+
}
|
|
1374
|
+
getMaxNestingDepth(elements, currentDepth) {
|
|
1375
|
+
let max = currentDepth;
|
|
1376
|
+
for (const el of elements) {
|
|
1377
|
+
if (el.type === "card" && el.elements) {
|
|
1378
|
+
const d = this.getMaxNestingDepth(el.elements, currentDepth + 1);
|
|
1379
|
+
if (d > max)
|
|
1380
|
+
max = d;
|
|
1381
|
+
} else if (el.type === "columns") {
|
|
1382
|
+
for (const col of el.columns) {
|
|
1383
|
+
const d = this.getMaxNestingDepth(col.elements, currentDepth + 1);
|
|
1384
|
+
if (d > max)
|
|
1385
|
+
max = d;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
return max;
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
845
1392
|
|
|
846
1393
|
// ../core/dist/compiler.js
|
|
847
1394
|
var YumiaCompiler = class {
|
|
848
1395
|
parser;
|
|
849
1396
|
layoutEngine;
|
|
850
1397
|
defaultTheme;
|
|
1398
|
+
linter;
|
|
851
1399
|
viewport;
|
|
852
1400
|
constructor(config = {}) {
|
|
853
1401
|
this.parser = config.parser ?? new DefaultYumiaParser();
|
|
854
1402
|
this.layoutEngine = config.layoutEngine ?? new DefaultLayoutEngine();
|
|
855
1403
|
this.defaultTheme = config.defaultTheme ?? defaultTheme;
|
|
1404
|
+
this.linter = new YumiaLinter(this.layoutEngine);
|
|
856
1405
|
if (config.viewport) {
|
|
857
1406
|
this.viewport = config.viewport;
|
|
858
1407
|
}
|
|
@@ -872,12 +1421,20 @@ var YumiaCompiler = class {
|
|
|
872
1421
|
warnings
|
|
873
1422
|
};
|
|
874
1423
|
}
|
|
1424
|
+
lint(sourceOrPresentation, options) {
|
|
1425
|
+
const presentation = typeof sourceOrPresentation === "string" ? this.parse(sourceOrPresentation) : sourceOrPresentation;
|
|
1426
|
+
return this.linter.lint(presentation, {
|
|
1427
|
+
...this.viewport ? { viewport: this.viewport } : {},
|
|
1428
|
+
...options
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
875
1431
|
layout(presentation, viewport) {
|
|
876
1432
|
return this.layoutEngine.computePresentation(presentation, viewport ?? this.viewport);
|
|
877
1433
|
}
|
|
878
1434
|
async render(presentation, renderer, contextOverrides = {}) {
|
|
879
1435
|
const layout = contextOverrides.layout ?? this.layout(presentation);
|
|
880
|
-
const
|
|
1436
|
+
const presentationTheme = presentation.metadata.theme ? resolveTheme(presentation.metadata.theme) : this.defaultTheme;
|
|
1437
|
+
const theme = contextOverrides.theme ?? presentationTheme;
|
|
881
1438
|
const context = {
|
|
882
1439
|
theme,
|
|
883
1440
|
layout,
|
|
@@ -903,7 +1460,10 @@ var YumiaCompiler = class {
|
|
|
903
1460
|
subtitle: { type: "string" },
|
|
904
1461
|
author: { type: "string" },
|
|
905
1462
|
date: { type: "string" },
|
|
906
|
-
theme: {
|
|
1463
|
+
theme: {
|
|
1464
|
+
type: "string",
|
|
1465
|
+
enum: ["default", "cyberpunk", "minimal", "corporate", "terminal", "academic"]
|
|
1466
|
+
},
|
|
907
1467
|
aspectRatio: { enum: ["16:9", "4:3", "16:10"] }
|
|
908
1468
|
}
|
|
909
1469
|
},
|
|
@@ -915,9 +1475,13 @@ var YumiaCompiler = class {
|
|
|
915
1475
|
description: "Multi-column grid layout"
|
|
916
1476
|
},
|
|
917
1477
|
card: {
|
|
918
|
-
syntax:
|
|
1478
|
+
syntax: ':::card [Title] [variant="primary|success|warning|danger|info"]\\n...\\n:::',
|
|
919
1479
|
description: "Visual container card with theme border and background"
|
|
920
1480
|
},
|
|
1481
|
+
metric: {
|
|
1482
|
+
syntax: ':::metric value="99.9%" label="Uptime" change="+0.4%" variant="success"',
|
|
1483
|
+
description: "Stat callout box with prominent value, label, and trend"
|
|
1484
|
+
},
|
|
921
1485
|
notes: {
|
|
922
1486
|
syntax: ":::notes\\nSpeaker notes text\\n:::",
|
|
923
1487
|
description: "Speaker notes attached to slide metadata"
|
|
@@ -992,7 +1556,8 @@ var PptxRenderer = class {
|
|
|
992
1556
|
async render(presentation, context = {}) {
|
|
993
1557
|
const PptxConstructor = pptxgen.default || pptxgen;
|
|
994
1558
|
const pptx = new PptxConstructor();
|
|
995
|
-
const
|
|
1559
|
+
const resolvedTheme = presentation.metadata.theme ? resolveTheme(presentation.metadata.theme) : defaultTheme;
|
|
1560
|
+
const theme = context.theme || resolvedTheme;
|
|
996
1561
|
const title = presentation.metadata.title || "Yumia Presentation";
|
|
997
1562
|
const author = presentation.metadata.author || "YumiaMD";
|
|
998
1563
|
pptx.title = title;
|
|
@@ -1052,6 +1617,9 @@ var PptxRenderer = class {
|
|
|
1052
1617
|
case "image":
|
|
1053
1618
|
this.renderImage(pptxSlide, element, rect);
|
|
1054
1619
|
break;
|
|
1620
|
+
case "metric":
|
|
1621
|
+
this.renderMetric(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
1622
|
+
break;
|
|
1055
1623
|
case "card":
|
|
1056
1624
|
this.renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme);
|
|
1057
1625
|
break;
|
|
@@ -1197,12 +1765,79 @@ var PptxRenderer = class {
|
|
|
1197
1765
|
});
|
|
1198
1766
|
}
|
|
1199
1767
|
}
|
|
1768
|
+
renderMetric(pptxSlide, pptx, node, scaleX, scaleY, theme) {
|
|
1769
|
+
const metric = node.element;
|
|
1770
|
+
const rect = this.toInches(node.bounds, scaleX, scaleY);
|
|
1771
|
+
const cardTheme = theme.components?.card;
|
|
1772
|
+
let accentColor = theme.colors.primary;
|
|
1773
|
+
if (metric.variant && theme.colors[metric.variant]) {
|
|
1774
|
+
accentColor = theme.colors[metric.variant];
|
|
1775
|
+
}
|
|
1776
|
+
const fillColor = this.cleanHexColor(cardTheme?.background || theme.colors.surface);
|
|
1777
|
+
const borderColor = this.cleanHexColor(metric.variant && theme.colors[metric.variant] ? theme.colors[metric.variant] : cardTheme?.borderColor || theme.colors.border || "#cbd5e1");
|
|
1778
|
+
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
1779
|
+
x: rect.x,
|
|
1780
|
+
y: rect.y,
|
|
1781
|
+
w: rect.w,
|
|
1782
|
+
h: rect.h,
|
|
1783
|
+
fill: { color: fillColor },
|
|
1784
|
+
line: { color: borderColor, width: 1.5 },
|
|
1785
|
+
rectRadius: 0.08
|
|
1786
|
+
});
|
|
1787
|
+
pptxSlide.addText(metric.label.toUpperCase(), {
|
|
1788
|
+
x: rect.x + 0.15,
|
|
1789
|
+
y: rect.y + 0.15,
|
|
1790
|
+
w: rect.w - 0.3,
|
|
1791
|
+
h: 0.25,
|
|
1792
|
+
fontSize: 11,
|
|
1793
|
+
bold: true,
|
|
1794
|
+
color: this.cleanHexColor(theme.colors.muted || "#64748b"),
|
|
1795
|
+
fontFace: theme.typography.headingFont.split(",")[0]?.trim() || "Arial",
|
|
1796
|
+
align: "center",
|
|
1797
|
+
valign: "middle"
|
|
1798
|
+
});
|
|
1799
|
+
const displayValue = metric.unit ? `${metric.value} ${metric.unit}` : metric.value;
|
|
1800
|
+
pptxSlide.addText(displayValue, {
|
|
1801
|
+
x: rect.x + 0.1,
|
|
1802
|
+
y: rect.y + 0.4,
|
|
1803
|
+
w: rect.w - 0.2,
|
|
1804
|
+
h: 0.55,
|
|
1805
|
+
fontSize: 30,
|
|
1806
|
+
bold: true,
|
|
1807
|
+
color: this.cleanHexColor(accentColor),
|
|
1808
|
+
fontFace: theme.typography.headingFont.split(",")[0]?.trim() || "Arial",
|
|
1809
|
+
align: "center",
|
|
1810
|
+
valign: "middle"
|
|
1811
|
+
});
|
|
1812
|
+
if (metric.change) {
|
|
1813
|
+
const isPositive = metric.change.startsWith("+");
|
|
1814
|
+
const changeColor = isPositive ? this.cleanHexColor(theme.colors.success || "#10b981") : this.cleanHexColor(theme.colors.danger || "#ef4444");
|
|
1815
|
+
pptxSlide.addText(metric.change, {
|
|
1816
|
+
x: rect.x + 0.1,
|
|
1817
|
+
y: rect.y + rect.h - 0.32,
|
|
1818
|
+
w: rect.w - 0.2,
|
|
1819
|
+
h: 0.22,
|
|
1820
|
+
fontSize: 12,
|
|
1821
|
+
bold: true,
|
|
1822
|
+
color: changeColor,
|
|
1823
|
+
fontFace: theme.typography.bodyFont.split(",")[0]?.trim() || "Arial",
|
|
1824
|
+
align: "center",
|
|
1825
|
+
valign: "middle"
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1200
1829
|
renderCard(pptxSlide, pptx, node, scaleX, scaleY, theme) {
|
|
1201
1830
|
const card = node.element;
|
|
1202
1831
|
const rect = this.toInches(node.bounds, scaleX, scaleY);
|
|
1203
1832
|
const cardTheme = theme.components?.card;
|
|
1204
1833
|
const fillColor = this.cleanHexColor(cardTheme?.background || theme.colors.surface);
|
|
1205
|
-
|
|
1834
|
+
let borderColor = this.cleanHexColor(cardTheme?.borderColor || theme.colors.border || "#cbd5e1");
|
|
1835
|
+
let titleColor = this.cleanHexColor(theme.colors.primary);
|
|
1836
|
+
if (card.variant && theme.colors[card.variant]) {
|
|
1837
|
+
const variantHex = this.cleanHexColor(theme.colors[card.variant]);
|
|
1838
|
+
borderColor = variantHex;
|
|
1839
|
+
titleColor = variantHex;
|
|
1840
|
+
}
|
|
1206
1841
|
pptxSlide.addShape(pptx.ShapeType.roundRect, {
|
|
1207
1842
|
x: rect.x,
|
|
1208
1843
|
y: rect.y,
|
|
@@ -1220,7 +1855,7 @@ var PptxRenderer = class {
|
|
|
1220
1855
|
h: 0.35,
|
|
1221
1856
|
fontSize: 20,
|
|
1222
1857
|
bold: true,
|
|
1223
|
-
color:
|
|
1858
|
+
color: titleColor,
|
|
1224
1859
|
fontFace: theme.typography.headingFont.split(",")[0]?.trim() || "Arial"
|
|
1225
1860
|
});
|
|
1226
1861
|
}
|
|
@@ -1331,7 +1966,7 @@ var PptxRenderer = class {
|
|
|
1331
1966
|
// src/cli.ts
|
|
1332
1967
|
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
1333
1968
|
import { basename, dirname, extname, join, resolve } from "path";
|
|
1334
|
-
var VERSION = "0.1.
|
|
1969
|
+
var VERSION = "0.1.8";
|
|
1335
1970
|
function printHelp() {
|
|
1336
1971
|
return `
|
|
1337
1972
|
YumiaMD \u2014 Markdown-based presentation compiler (v${VERSION})
|
|
@@ -1350,6 +1985,7 @@ Commands:
|
|
|
1350
1985
|
Options:
|
|
1351
1986
|
--out, -o <file> Specify output file path (default: dist/<name>.pptx)
|
|
1352
1987
|
--format, -f <fmt> Target output format: pptx (default)
|
|
1988
|
+
--strict Enforce zero warnings in 'lint' (exits with code 1 on warning)
|
|
1353
1989
|
--json Output results formatted as JSON for CI/CD and AI tools
|
|
1354
1990
|
--layout Show computed geometric bounding boxes in 'inspect'
|
|
1355
1991
|
-h, --help Show this help message
|
|
@@ -1365,6 +2001,7 @@ async function runCli(argv) {
|
|
|
1365
2001
|
return { exitCode: 0, output: `yumia v${VERSION}` };
|
|
1366
2002
|
}
|
|
1367
2003
|
const isJson = args.includes("--json");
|
|
2004
|
+
const isStrict = args.includes("--strict");
|
|
1368
2005
|
const nonFlagArgs = args.filter((a) => !a.startsWith("-"));
|
|
1369
2006
|
const command = nonFlagArgs[0];
|
|
1370
2007
|
const target = nonFlagArgs[1];
|
|
@@ -1501,57 +2138,46 @@ ${errorLines.join("\n")}`
|
|
|
1501
2138
|
}
|
|
1502
2139
|
try {
|
|
1503
2140
|
const source = readFileSync(target, "utf-8");
|
|
1504
|
-
const
|
|
1505
|
-
const
|
|
1506
|
-
const layout = engine.computePresentation(presentation);
|
|
1507
|
-
const issues = [];
|
|
1508
|
-
layout.slides.forEach((slideResult, index) => {
|
|
1509
|
-
const slideNum = index + 1;
|
|
1510
|
-
if (slideResult.overflow) {
|
|
1511
|
-
issues.push({
|
|
1512
|
-
slide: slideNum,
|
|
1513
|
-
type: "overflow",
|
|
1514
|
-
message: `Content exceeds slide height by ~${Math.round(slideResult.overflowAmount || 0)}px`
|
|
1515
|
-
});
|
|
1516
|
-
}
|
|
1517
|
-
const slide = presentation.slides[index];
|
|
1518
|
-
if (slide.elements.length === 0) {
|
|
1519
|
-
issues.push({
|
|
1520
|
-
slide: slideNum,
|
|
1521
|
-
type: "empty",
|
|
1522
|
-
message: "Slide has no content elements."
|
|
1523
|
-
});
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
2141
|
+
const compiler = new YumiaCompiler();
|
|
2142
|
+
const report = compiler.lint(source, { strict: isStrict });
|
|
1526
2143
|
if (isJson) {
|
|
1527
2144
|
return {
|
|
1528
|
-
exitCode: 0,
|
|
2145
|
+
exitCode: report.passed ? 0 : 1,
|
|
1529
2146
|
output: JSON.stringify(
|
|
1530
2147
|
{
|
|
1531
2148
|
target,
|
|
1532
|
-
|
|
1533
|
-
slideCount: presentation.slides.length,
|
|
1534
|
-
issues
|
|
2149
|
+
...report
|
|
1535
2150
|
},
|
|
1536
2151
|
null,
|
|
1537
2152
|
2
|
|
1538
2153
|
)
|
|
1539
2154
|
};
|
|
1540
2155
|
}
|
|
1541
|
-
if (
|
|
2156
|
+
if (report.issueCount === 0) {
|
|
1542
2157
|
return {
|
|
1543
2158
|
exitCode: 0,
|
|
1544
|
-
output: `\u2713 Yumia Lint: All ${
|
|
2159
|
+
output: `\u2713 Yumia Lint: All ${report.totalSlides} slide(s) passed with 0 issues.`
|
|
1545
2160
|
};
|
|
1546
2161
|
} else {
|
|
1547
|
-
const
|
|
2162
|
+
const issueLines = [];
|
|
2163
|
+
for (const e of report.errors) {
|
|
2164
|
+
issueLines.push(` \u2717 [${e.code}] Slide ${e.slide}: ${e.message}`);
|
|
2165
|
+
}
|
|
2166
|
+
for (const w of report.warnings) {
|
|
2167
|
+
issueLines.push(` \u26A0 [${w.code}] Slide ${w.slide}: ${w.message}`);
|
|
2168
|
+
}
|
|
2169
|
+
for (const info of report.infos) {
|
|
2170
|
+
issueLines.push(` \u2139 [${info.code}] Slide ${info.slide}: ${info.message}`);
|
|
2171
|
+
}
|
|
2172
|
+
const summary = `Found ${report.errors.length} error(s), ${report.warnings.length} warning(s).`;
|
|
2173
|
+
const exitCode = report.passed ? 0 : 1;
|
|
1548
2174
|
return {
|
|
1549
|
-
exitCode
|
|
2175
|
+
exitCode,
|
|
1550
2176
|
output: `Yumia Lint Report for '${target}':
|
|
1551
2177
|
|
|
1552
|
-
${
|
|
2178
|
+
${issueLines.join("\n")}
|
|
1553
2179
|
|
|
1554
|
-
|
|
2180
|
+
${summary}${isStrict && report.warnings.length > 0 ? " (failed due to --strict)" : ""}`
|
|
1555
2181
|
};
|
|
1556
2182
|
}
|
|
1557
2183
|
} catch (err) {
|
|
@@ -1663,6 +2289,7 @@ export {
|
|
|
1663
2289
|
createList,
|
|
1664
2290
|
createImage,
|
|
1665
2291
|
createCard,
|
|
2292
|
+
createMetric,
|
|
1666
2293
|
createCode,
|
|
1667
2294
|
createQuote,
|
|
1668
2295
|
createTable,
|
|
@@ -1676,7 +2303,15 @@ export {
|
|
|
1676
2303
|
VIEWPORT_PRESETS,
|
|
1677
2304
|
DefaultLayoutEngine,
|
|
1678
2305
|
defaultTheme,
|
|
2306
|
+
cyberpunkTheme,
|
|
2307
|
+
minimalTheme,
|
|
2308
|
+
corporateTheme,
|
|
2309
|
+
terminalTheme,
|
|
2310
|
+
academicTheme,
|
|
2311
|
+
THEME_REGISTRY,
|
|
2312
|
+
resolveTheme,
|
|
1679
2313
|
createTheme,
|
|
2314
|
+
YumiaLinter,
|
|
1680
2315
|
YumiaCompiler,
|
|
1681
2316
|
parseInlineMarkdown,
|
|
1682
2317
|
PptxRenderer,
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export * from '@yumiamd/layout';
|
|
|
6
6
|
export * from '@yumiamd/renderer';
|
|
7
7
|
export * from '@yumiamd/renderer-pptx';
|
|
8
8
|
|
|
9
|
-
declare const VERSION = "0.1.
|
|
9
|
+
declare const VERSION = "0.1.8";
|
|
10
10
|
declare function printHelp(): string;
|
|
11
11
|
declare function runCli(argv: string[]): Promise<{
|
|
12
12
|
exitCode: number;
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,13 @@ import {
|
|
|
3
3
|
DefaultLayoutEngine,
|
|
4
4
|
DefaultYumiaParser,
|
|
5
5
|
PptxRenderer,
|
|
6
|
+
THEME_REGISTRY,
|
|
6
7
|
VERSION,
|
|
7
8
|
VIEWPORT_PRESETS,
|
|
8
9
|
YumiaCompiler,
|
|
10
|
+
YumiaLinter,
|
|
11
|
+
academicTheme,
|
|
12
|
+
corporateTheme,
|
|
9
13
|
createCard,
|
|
10
14
|
createCode,
|
|
11
15
|
createColumn,
|
|
@@ -15,26 +19,35 @@ import {
|
|
|
15
19
|
createImage,
|
|
16
20
|
createLayoutDirective,
|
|
17
21
|
createList,
|
|
22
|
+
createMetric,
|
|
18
23
|
createParagraph,
|
|
19
24
|
createPresentation,
|
|
20
25
|
createQuote,
|
|
21
26
|
createSlide,
|
|
22
27
|
createTable,
|
|
23
28
|
createTheme,
|
|
29
|
+
cyberpunkTheme,
|
|
24
30
|
defaultTheme,
|
|
31
|
+
minimalTheme,
|
|
25
32
|
parseInlineMarkdown,
|
|
26
33
|
parseYumia,
|
|
27
34
|
printHelp,
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
resolveTheme,
|
|
36
|
+
runCli,
|
|
37
|
+
terminalTheme
|
|
38
|
+
} from "./chunk-WUJKHJJU.js";
|
|
30
39
|
export {
|
|
31
40
|
DEFAULT_VIEWPORT,
|
|
32
41
|
DefaultLayoutEngine,
|
|
33
42
|
DefaultYumiaParser,
|
|
34
43
|
PptxRenderer,
|
|
44
|
+
THEME_REGISTRY,
|
|
35
45
|
VERSION,
|
|
36
46
|
VIEWPORT_PRESETS,
|
|
37
47
|
YumiaCompiler,
|
|
48
|
+
YumiaLinter,
|
|
49
|
+
academicTheme,
|
|
50
|
+
corporateTheme,
|
|
38
51
|
createCard,
|
|
39
52
|
createCode,
|
|
40
53
|
createColumn,
|
|
@@ -44,15 +57,20 @@ export {
|
|
|
44
57
|
createImage,
|
|
45
58
|
createLayoutDirective,
|
|
46
59
|
createList,
|
|
60
|
+
createMetric,
|
|
47
61
|
createParagraph,
|
|
48
62
|
createPresentation,
|
|
49
63
|
createQuote,
|
|
50
64
|
createSlide,
|
|
51
65
|
createTable,
|
|
52
66
|
createTheme,
|
|
67
|
+
cyberpunkTheme,
|
|
53
68
|
defaultTheme,
|
|
69
|
+
minimalTheme,
|
|
54
70
|
parseInlineMarkdown,
|
|
55
71
|
parseYumia,
|
|
56
72
|
printHelp,
|
|
57
|
-
|
|
73
|
+
resolveTheme,
|
|
74
|
+
runCli,
|
|
75
|
+
terminalTheme
|
|
58
76
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yumiamd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Command line interface and compiler for YumiaMD presentations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsup": "^8.5.1",
|
|
23
|
-
"@yumiamd/ast": "0.1.
|
|
24
|
-
"@yumiamd/parser": "0.1.
|
|
25
|
-
"@yumiamd/
|
|
26
|
-
"@yumiamd/
|
|
27
|
-
"@yumiamd/
|
|
28
|
-
"@yumiamd/
|
|
29
|
-
"@yumiamd/theme": "0.1.
|
|
23
|
+
"@yumiamd/ast": "0.1.8",
|
|
24
|
+
"@yumiamd/parser": "0.1.8",
|
|
25
|
+
"@yumiamd/core": "0.1.8",
|
|
26
|
+
"@yumiamd/renderer": "0.1.8",
|
|
27
|
+
"@yumiamd/layout": "0.1.8",
|
|
28
|
+
"@yumiamd/renderer-pptx": "0.1.8",
|
|
29
|
+
"@yumiamd/theme": "0.1.8"
|
|
30
30
|
},
|
|
31
31
|
"keywords": [
|
|
32
32
|
"yumia",
|