@wireweave/core 1.1.0-beta.0 → 1.2.0-beta.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/dist/index.cjs +3966 -3278
- package/dist/index.d.cts +616 -2
- package/dist/index.d.ts +616 -2
- package/dist/index.js +3948 -3275
- package/dist/parser.cjs +675 -476
- package/dist/parser.js +675 -476
- package/dist/renderer.cjs +1099 -2759
- package/dist/renderer.d.cts +37 -175
- package/dist/renderer.d.ts +37 -175
- package/dist/renderer.js +1099 -2756
- package/package.json +1 -1
package/dist/renderer.cjs
CHANGED
|
@@ -21,9 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var renderer_exports = {};
|
|
22
22
|
__export(renderer_exports, {
|
|
23
23
|
HtmlRenderer: () => HtmlRenderer,
|
|
24
|
-
SvgRenderer: () => SvgRenderer,
|
|
25
24
|
createHtmlRenderer: () => createHtmlRenderer,
|
|
26
|
-
createSvgRenderer: () => createSvgRenderer,
|
|
27
25
|
darkTheme: () => darkTheme,
|
|
28
26
|
defaultTheme: () => defaultTheme,
|
|
29
27
|
generateComponentStyles: () => generateComponentStyles,
|
|
@@ -34,8 +32,7 @@ __export(renderer_exports, {
|
|
|
34
32
|
render: () => render,
|
|
35
33
|
renderIconSvg: () => renderIconSvg,
|
|
36
34
|
renderToHtml: () => renderToHtml,
|
|
37
|
-
|
|
38
|
-
renderToSvg: () => renderToSvg2
|
|
35
|
+
renderToSvg: () => renderToSvg
|
|
39
36
|
});
|
|
40
37
|
module.exports = __toCommonJS(renderer_exports);
|
|
41
38
|
|
|
@@ -92,23 +89,7 @@ function getTheme(name) {
|
|
|
92
89
|
return name === "dark" ? darkTheme : defaultTheme;
|
|
93
90
|
}
|
|
94
91
|
|
|
95
|
-
// src/renderer/styles
|
|
96
|
-
function generateComponentStyles(_theme, prefix = "wf") {
|
|
97
|
-
const parts = [
|
|
98
|
-
generateContainerStyles(prefix),
|
|
99
|
-
generateTextStyles(prefix),
|
|
100
|
-
generateInputStyles(_theme, prefix),
|
|
101
|
-
generateButtonStyles(_theme, prefix),
|
|
102
|
-
generateDisplayStyles(_theme, prefix),
|
|
103
|
-
generateDataStyles(_theme, prefix),
|
|
104
|
-
generateFeedbackStyles(_theme, prefix),
|
|
105
|
-
generateOverlayStyles(_theme, prefix),
|
|
106
|
-
generateNavigationStyles(_theme, prefix),
|
|
107
|
-
generateSemanticMarkerStyles(_theme, prefix),
|
|
108
|
-
generateAccessibilityStyles(prefix)
|
|
109
|
-
];
|
|
110
|
-
return parts.join("\n\n");
|
|
111
|
-
}
|
|
92
|
+
// src/renderer/styles/container.ts
|
|
112
93
|
function generateContainerStyles(prefix) {
|
|
113
94
|
return `/* Container Components */
|
|
114
95
|
.${prefix}-card {
|
|
@@ -248,6 +229,8 @@ function generateContainerStyles(prefix) {
|
|
|
248
229
|
padding: 16px;
|
|
249
230
|
}`;
|
|
250
231
|
}
|
|
232
|
+
|
|
233
|
+
// src/renderer/styles/text.ts
|
|
251
234
|
function generateTextStyles(prefix) {
|
|
252
235
|
return `/* Text Components */
|
|
253
236
|
.${prefix}-text {
|
|
@@ -304,6 +287,8 @@ h6.${prefix}-title { font-size: 16px; }
|
|
|
304
287
|
opacity: 0.7;
|
|
305
288
|
}`;
|
|
306
289
|
}
|
|
290
|
+
|
|
291
|
+
// src/renderer/styles/input.ts
|
|
307
292
|
function generateInputStyles(_theme, prefix) {
|
|
308
293
|
return `/* Input Components */
|
|
309
294
|
.${prefix}-form-field {
|
|
@@ -503,6 +488,8 @@ function generateInputStyles(_theme, prefix) {
|
|
|
503
488
|
cursor: pointer;
|
|
504
489
|
}`;
|
|
505
490
|
}
|
|
491
|
+
|
|
492
|
+
// src/renderer/styles/button.ts
|
|
506
493
|
function generateButtonStyles(_theme, prefix) {
|
|
507
494
|
return `/* Button Components */
|
|
508
495
|
.${prefix}-button {
|
|
@@ -630,6 +617,8 @@ function generateButtonStyles(_theme, prefix) {
|
|
|
630
617
|
.${prefix}-button.${prefix}-justify-end { justify-content: flex-end; }
|
|
631
618
|
.${prefix}-button.${prefix}-justify-between { justify-content: space-between; }`;
|
|
632
619
|
}
|
|
620
|
+
|
|
621
|
+
// src/renderer/styles/display.ts
|
|
633
622
|
function generateDisplayStyles(_theme, prefix) {
|
|
634
623
|
return `/* Display Components */
|
|
635
624
|
.${prefix}-image {
|
|
@@ -837,6 +826,8 @@ svg.${prefix}-icon-xl { width: 32px; height: 32px; }
|
|
|
837
826
|
justify-content: center;
|
|
838
827
|
}`;
|
|
839
828
|
}
|
|
829
|
+
|
|
830
|
+
// src/renderer/styles/data.ts
|
|
840
831
|
function generateDataStyles(_theme, prefix) {
|
|
841
832
|
return `/* Data Components */
|
|
842
833
|
.${prefix}-table {
|
|
@@ -895,6 +886,8 @@ function generateDataStyles(_theme, prefix) {
|
|
|
895
886
|
border-bottom: none;
|
|
896
887
|
}`;
|
|
897
888
|
}
|
|
889
|
+
|
|
890
|
+
// src/renderer/styles/feedback.ts
|
|
898
891
|
function generateFeedbackStyles(_theme, prefix) {
|
|
899
892
|
return `/* Feedback Components */
|
|
900
893
|
.${prefix}-alert {
|
|
@@ -986,6 +979,8 @@ function generateFeedbackStyles(_theme, prefix) {
|
|
|
986
979
|
to { transform: rotate(360deg); }
|
|
987
980
|
}`;
|
|
988
981
|
}
|
|
982
|
+
|
|
983
|
+
// src/renderer/styles/overlay.ts
|
|
989
984
|
function generateOverlayStyles(_theme, prefix) {
|
|
990
985
|
return `/* Overlay Components */
|
|
991
986
|
.${prefix}-tooltip-wrapper {
|
|
@@ -1084,6 +1079,8 @@ function generateOverlayStyles(_theme, prefix) {
|
|
|
1084
1079
|
cursor: not-allowed;
|
|
1085
1080
|
}`;
|
|
1086
1081
|
}
|
|
1082
|
+
|
|
1083
|
+
// src/renderer/styles/navigation.ts
|
|
1087
1084
|
function generateNavigationStyles(_theme, prefix) {
|
|
1088
1085
|
return `/* Navigation Components */
|
|
1089
1086
|
.${prefix}-nav {
|
|
@@ -1196,6 +1193,8 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1196
1193
|
color: var(--${prefix}-muted);
|
|
1197
1194
|
}`;
|
|
1198
1195
|
}
|
|
1196
|
+
|
|
1197
|
+
// src/renderer/styles/semantic.ts
|
|
1199
1198
|
function generateSemanticMarkerStyles(_theme, prefix) {
|
|
1200
1199
|
return `/* Semantic Markers */
|
|
1201
1200
|
|
|
@@ -1282,6 +1281,8 @@ function generateSemanticMarkerStyles(_theme, prefix) {
|
|
|
1282
1281
|
color: var(--${prefix}-muted);
|
|
1283
1282
|
}`;
|
|
1284
1283
|
}
|
|
1284
|
+
|
|
1285
|
+
// src/renderer/styles/accessibility.ts
|
|
1285
1286
|
function generateAccessibilityStyles(prefix) {
|
|
1286
1287
|
return `/* Accessibility Utilities */
|
|
1287
1288
|
.sr-only {
|
|
@@ -1319,6 +1320,24 @@ function generateAccessibilityStyles(prefix) {
|
|
|
1319
1320
|
}`;
|
|
1320
1321
|
}
|
|
1321
1322
|
|
|
1323
|
+
// src/renderer/styles-components.ts
|
|
1324
|
+
function generateComponentStyles(_theme, prefix = "wf") {
|
|
1325
|
+
const parts = [
|
|
1326
|
+
generateContainerStyles(prefix),
|
|
1327
|
+
generateTextStyles(prefix),
|
|
1328
|
+
generateInputStyles(_theme, prefix),
|
|
1329
|
+
generateButtonStyles(_theme, prefix),
|
|
1330
|
+
generateDisplayStyles(_theme, prefix),
|
|
1331
|
+
generateDataStyles(_theme, prefix),
|
|
1332
|
+
generateFeedbackStyles(_theme, prefix),
|
|
1333
|
+
generateOverlayStyles(_theme, prefix),
|
|
1334
|
+
generateNavigationStyles(_theme, prefix),
|
|
1335
|
+
generateSemanticMarkerStyles(_theme, prefix),
|
|
1336
|
+
generateAccessibilityStyles(prefix)
|
|
1337
|
+
];
|
|
1338
|
+
return parts.join("\n\n");
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1322
1341
|
// src/renderer/styles.ts
|
|
1323
1342
|
function generateStyles(theme, prefix = "wf") {
|
|
1324
1343
|
const parts = [
|
|
@@ -1602,6 +1621,7 @@ function generateLayoutClasses(prefix) {
|
|
|
1602
1621
|
padding: 16px;
|
|
1603
1622
|
display: flex;
|
|
1604
1623
|
flex-direction: column;
|
|
1624
|
+
min-height: 0;
|
|
1605
1625
|
}
|
|
1606
1626
|
|
|
1607
1627
|
/* Scrollable main content */
|
|
@@ -1610,6 +1630,11 @@ function generateLayoutClasses(prefix) {
|
|
|
1610
1630
|
overflow-x: hidden;
|
|
1611
1631
|
}
|
|
1612
1632
|
|
|
1633
|
+
/* Col containing scrollable main needs min-height: 0 for scroll to work */
|
|
1634
|
+
.${prefix}-col:has(> .${prefix}-main.${prefix}-scroll) {
|
|
1635
|
+
min-height: 0;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1613
1638
|
/* Main content should align to top, not stretch to fill */
|
|
1614
1639
|
/* But allow explicit flex=1 to override */
|
|
1615
1640
|
.${prefix}-main > .${prefix}-col:not(.${prefix}-flex-1) {
|
|
@@ -1844,6 +1869,248 @@ function resolveViewport(viewport, device) {
|
|
|
1844
1869
|
return DEFAULT_VIEWPORT;
|
|
1845
1870
|
}
|
|
1846
1871
|
|
|
1872
|
+
// src/renderer/html/components.ts
|
|
1873
|
+
function buildClassString(classes) {
|
|
1874
|
+
return classes.filter(Boolean).join(" ");
|
|
1875
|
+
}
|
|
1876
|
+
var SIZE_TOKENS = {
|
|
1877
|
+
icon: { xs: 12, sm: 14, md: 16, lg: 20, xl: 24 },
|
|
1878
|
+
avatar: { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 },
|
|
1879
|
+
spinner: { xs: 12, sm: 16, md: 24, lg: 32, xl: 48 }
|
|
1880
|
+
};
|
|
1881
|
+
function resolveSizeValue(size, componentType, prefix) {
|
|
1882
|
+
if (size === void 0) {
|
|
1883
|
+
return {};
|
|
1884
|
+
}
|
|
1885
|
+
if (typeof size === "string") {
|
|
1886
|
+
const tokens = SIZE_TOKENS[componentType];
|
|
1887
|
+
if (size in tokens) {
|
|
1888
|
+
return { className: `${prefix}-${componentType}-${size}` };
|
|
1889
|
+
}
|
|
1890
|
+
const parsed = parseInt(size, 10);
|
|
1891
|
+
if (!isNaN(parsed)) {
|
|
1892
|
+
return { style: `width: ${parsed}px; height: ${parsed}px;` };
|
|
1893
|
+
}
|
|
1894
|
+
return {};
|
|
1895
|
+
}
|
|
1896
|
+
if (typeof size === "number") {
|
|
1897
|
+
return { style: `width: ${size}px; height: ${size}px;` };
|
|
1898
|
+
}
|
|
1899
|
+
return {};
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
// src/renderer/html/renderers/layout.ts
|
|
1903
|
+
function renderHeader(node, ctx) {
|
|
1904
|
+
const classes = ctx.buildClassString([
|
|
1905
|
+
`${ctx.prefix}-header`,
|
|
1906
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1907
|
+
...ctx.getCommonClasses(node)
|
|
1908
|
+
]);
|
|
1909
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1910
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1911
|
+
const children = ctx.renderChildren(node.children);
|
|
1912
|
+
return `<header class="${classes}"${styleAttr}>
|
|
1913
|
+
${children}
|
|
1914
|
+
</header>`;
|
|
1915
|
+
}
|
|
1916
|
+
function renderMain(node, ctx) {
|
|
1917
|
+
const classes = ctx.buildClassString([
|
|
1918
|
+
`${ctx.prefix}-main`,
|
|
1919
|
+
node.scroll ? `${ctx.prefix}-scroll` : void 0,
|
|
1920
|
+
...ctx.getCommonClasses(node)
|
|
1921
|
+
]);
|
|
1922
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1923
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1924
|
+
const children = ctx.renderChildren(node.children);
|
|
1925
|
+
return `<main class="${classes}"${styleAttr}>
|
|
1926
|
+
${children}
|
|
1927
|
+
</main>`;
|
|
1928
|
+
}
|
|
1929
|
+
function renderFooter(node, ctx) {
|
|
1930
|
+
const classes = ctx.buildClassString([
|
|
1931
|
+
`${ctx.prefix}-footer`,
|
|
1932
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1933
|
+
...ctx.getCommonClasses(node)
|
|
1934
|
+
]);
|
|
1935
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1936
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1937
|
+
const children = ctx.renderChildren(node.children);
|
|
1938
|
+
return `<footer class="${classes}"${styleAttr}>
|
|
1939
|
+
${children}
|
|
1940
|
+
</footer>`;
|
|
1941
|
+
}
|
|
1942
|
+
function renderSidebar(node, ctx) {
|
|
1943
|
+
const classes = ctx.buildClassString([
|
|
1944
|
+
`${ctx.prefix}-sidebar`,
|
|
1945
|
+
node.position === "right" ? `${ctx.prefix}-sidebar-right` : void 0,
|
|
1946
|
+
...ctx.getCommonClasses(node)
|
|
1947
|
+
]);
|
|
1948
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1949
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1950
|
+
const children = ctx.renderChildren(node.children);
|
|
1951
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
1952
|
+
${children}
|
|
1953
|
+
</aside>`;
|
|
1954
|
+
}
|
|
1955
|
+
function renderSection(node, ctx) {
|
|
1956
|
+
const classes = ctx.buildClassString([
|
|
1957
|
+
`${ctx.prefix}-section`,
|
|
1958
|
+
...ctx.getCommonClasses(node)
|
|
1959
|
+
]);
|
|
1960
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1961
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1962
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1963
|
+
` : "";
|
|
1964
|
+
const children = ctx.renderChildren(node.children);
|
|
1965
|
+
return `<section class="${classes}"${styleAttr}>
|
|
1966
|
+
${title}${children}
|
|
1967
|
+
</section>`;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// src/renderer/html/renderers/grid.ts
|
|
1971
|
+
function renderRow(node, ctx) {
|
|
1972
|
+
const classes = ctx.buildClassString([
|
|
1973
|
+
`${ctx.prefix}-row`,
|
|
1974
|
+
...ctx.getCommonClasses(node)
|
|
1975
|
+
]);
|
|
1976
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1977
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1978
|
+
const children = ctx.renderChildren(node.children);
|
|
1979
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1980
|
+
${children}
|
|
1981
|
+
</div>`;
|
|
1982
|
+
}
|
|
1983
|
+
function renderCol(node, ctx) {
|
|
1984
|
+
const classes = ctx.buildClassString([
|
|
1985
|
+
`${ctx.prefix}-col`,
|
|
1986
|
+
node.span ? `${ctx.prefix}-col-${node.span}` : void 0,
|
|
1987
|
+
// Responsive breakpoint classes
|
|
1988
|
+
node.sm ? `${ctx.prefix}-col-sm-${node.sm}` : void 0,
|
|
1989
|
+
node.md ? `${ctx.prefix}-col-md-${node.md}` : void 0,
|
|
1990
|
+
node.lg ? `${ctx.prefix}-col-lg-${node.lg}` : void 0,
|
|
1991
|
+
node.xl ? `${ctx.prefix}-col-xl-${node.xl}` : void 0,
|
|
1992
|
+
...ctx.getCommonClasses(node)
|
|
1993
|
+
]);
|
|
1994
|
+
const styles = ctx.buildColStyles(node);
|
|
1995
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1996
|
+
const children = ctx.renderChildren(node.children);
|
|
1997
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1998
|
+
${children}
|
|
1999
|
+
</div>`;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// src/renderer/html/renderers/container.ts
|
|
2003
|
+
function renderCard(node, ctx) {
|
|
2004
|
+
const hasExplicitWidth = node.w !== void 0;
|
|
2005
|
+
const classes = ctx.buildClassString([
|
|
2006
|
+
`${ctx.prefix}-card`,
|
|
2007
|
+
!hasExplicitWidth ? `${ctx.prefix}-card-flex` : void 0,
|
|
2008
|
+
node.shadow ? `${ctx.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
2009
|
+
...ctx.getCommonClasses(node)
|
|
2010
|
+
]);
|
|
2011
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2012
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2013
|
+
const title = node.title ? `<h3 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h3>
|
|
2014
|
+
` : "";
|
|
2015
|
+
const children = ctx.renderChildren(node.children);
|
|
2016
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2017
|
+
${title}${children}
|
|
2018
|
+
</div>`;
|
|
2019
|
+
}
|
|
2020
|
+
function renderModal(node, ctx) {
|
|
2021
|
+
const classes = ctx.buildClassString([
|
|
2022
|
+
`${ctx.prefix}-modal`,
|
|
2023
|
+
...ctx.getCommonClasses(node)
|
|
2024
|
+
]);
|
|
2025
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2026
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2027
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2028
|
+
` : "";
|
|
2029
|
+
const children = ctx.renderChildren(node.children);
|
|
2030
|
+
return `<div class="${ctx.prefix}-modal-backdrop">
|
|
2031
|
+
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
2032
|
+
${title}${children}
|
|
2033
|
+
</div>
|
|
2034
|
+
</div>`;
|
|
2035
|
+
}
|
|
2036
|
+
function renderDrawer(node, ctx) {
|
|
2037
|
+
const position = node.position || "left";
|
|
2038
|
+
const classes = ctx.buildClassString([
|
|
2039
|
+
`${ctx.prefix}-drawer`,
|
|
2040
|
+
`${ctx.prefix}-drawer-${position}`,
|
|
2041
|
+
...ctx.getCommonClasses(node)
|
|
2042
|
+
]);
|
|
2043
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2044
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2045
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2046
|
+
` : "";
|
|
2047
|
+
const children = ctx.renderChildren(node.children);
|
|
2048
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
2049
|
+
${title}${children}
|
|
2050
|
+
</aside>`;
|
|
2051
|
+
}
|
|
2052
|
+
function renderAccordion(node, ctx) {
|
|
2053
|
+
const classes = ctx.buildClassString([
|
|
2054
|
+
`${ctx.prefix}-accordion`,
|
|
2055
|
+
...ctx.getCommonClasses(node)
|
|
2056
|
+
]);
|
|
2057
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2058
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2059
|
+
const title = node.title ? `<button class="${ctx.prefix}-accordion-header">${ctx.escapeHtml(node.title)}</button>
|
|
2060
|
+
` : "";
|
|
2061
|
+
const children = ctx.renderChildren(node.children);
|
|
2062
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2063
|
+
${title}<div class="${ctx.prefix}-accordion-content">
|
|
2064
|
+
${children}
|
|
2065
|
+
</div>
|
|
2066
|
+
</div>`;
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/renderer/html/renderers/text.ts
|
|
2070
|
+
function renderText(node, ctx) {
|
|
2071
|
+
const classes = ctx.buildClassString([
|
|
2072
|
+
`${ctx.prefix}-text`,
|
|
2073
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2074
|
+
node.weight ? `${ctx.prefix}-text-${node.weight}` : void 0,
|
|
2075
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2076
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
2077
|
+
...ctx.getCommonClasses(node)
|
|
2078
|
+
]);
|
|
2079
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2080
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2081
|
+
return `<p class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</p>`;
|
|
2082
|
+
}
|
|
2083
|
+
function renderTitle(node, ctx) {
|
|
2084
|
+
const level = node.level || 1;
|
|
2085
|
+
const tag = `h${level}`;
|
|
2086
|
+
const classes = ctx.buildClassString([
|
|
2087
|
+
`${ctx.prefix}-title`,
|
|
2088
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2089
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2090
|
+
...ctx.getCommonClasses(node)
|
|
2091
|
+
]);
|
|
2092
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2093
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2094
|
+
return `<${tag} class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</${tag}>`;
|
|
2095
|
+
}
|
|
2096
|
+
function renderLink(node, ctx) {
|
|
2097
|
+
const classes = ctx.buildClassString([
|
|
2098
|
+
`${ctx.prefix}-link`,
|
|
2099
|
+
...ctx.getCommonClasses(node)
|
|
2100
|
+
]);
|
|
2101
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2102
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2103
|
+
const attrs = {
|
|
2104
|
+
class: classes,
|
|
2105
|
+
href: node.href || "#"
|
|
2106
|
+
};
|
|
2107
|
+
if (node.external) {
|
|
2108
|
+
attrs.target = "_blank";
|
|
2109
|
+
attrs.rel = "noopener noreferrer";
|
|
2110
|
+
}
|
|
2111
|
+
return `<a${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.content)}</a>`;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
1847
2114
|
// src/icons/lucide-icons.ts
|
|
1848
2115
|
var lucideIcons = {
|
|
1849
2116
|
"a-arrow-down": [
|
|
@@ -48243,34 +48510,658 @@ function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleA
|
|
|
48243
48510
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${strokeWidth}" stroke-linecap="round" stroke-linejoin="round" class="${className}"${styleAttr}>${elements}</svg>`;
|
|
48244
48511
|
}
|
|
48245
48512
|
|
|
48246
|
-
// src/renderer/html/
|
|
48247
|
-
function
|
|
48248
|
-
|
|
48513
|
+
// src/renderer/html/renderers/button.ts
|
|
48514
|
+
function renderButton(node, ctx) {
|
|
48515
|
+
const isIconOnly = node.icon && (!node.content.trim() || node.content === "Button");
|
|
48516
|
+
const classes = ctx.buildClassString([
|
|
48517
|
+
`${ctx.prefix}-button`,
|
|
48518
|
+
node.primary ? `${ctx.prefix}-button-primary` : void 0,
|
|
48519
|
+
node.secondary ? `${ctx.prefix}-button-secondary` : void 0,
|
|
48520
|
+
node.outline ? `${ctx.prefix}-button-outline` : void 0,
|
|
48521
|
+
node.ghost ? `${ctx.prefix}-button-ghost` : void 0,
|
|
48522
|
+
node.danger ? `${ctx.prefix}-button-danger` : void 0,
|
|
48523
|
+
node.size ? `${ctx.prefix}-button-${node.size}` : void 0,
|
|
48524
|
+
node.disabled ? `${ctx.prefix}-button-disabled` : void 0,
|
|
48525
|
+
node.loading ? `${ctx.prefix}-button-loading` : void 0,
|
|
48526
|
+
isIconOnly ? `${ctx.prefix}-button-icon-only` : void 0,
|
|
48527
|
+
...ctx.getCommonClasses(node)
|
|
48528
|
+
]);
|
|
48529
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48530
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48531
|
+
const attrs = {
|
|
48532
|
+
class: classes,
|
|
48533
|
+
disabled: node.disabled
|
|
48534
|
+
};
|
|
48535
|
+
let icon = "";
|
|
48536
|
+
if (node.icon) {
|
|
48537
|
+
const iconData = getIconData(node.icon);
|
|
48538
|
+
if (iconData) {
|
|
48539
|
+
icon = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-icon`);
|
|
48540
|
+
} else {
|
|
48541
|
+
icon = `<span class="${ctx.prefix}-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48542
|
+
}
|
|
48543
|
+
}
|
|
48544
|
+
const loading = node.loading ? `<span class="${ctx.prefix}-spinner ${ctx.prefix}-spinner-sm"></span>` : "";
|
|
48545
|
+
const content = isIconOnly ? "" : ctx.escapeHtml(node.content);
|
|
48546
|
+
return `<button${ctx.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
48249
48547
|
}
|
|
48250
|
-
|
|
48251
|
-
|
|
48252
|
-
|
|
48253
|
-
|
|
48254
|
-
}
|
|
48255
|
-
|
|
48256
|
-
|
|
48257
|
-
|
|
48548
|
+
|
|
48549
|
+
// src/renderer/html/renderers/feedback.ts
|
|
48550
|
+
function renderAlert(node, ctx) {
|
|
48551
|
+
const classes = ctx.buildClassString([
|
|
48552
|
+
`${ctx.prefix}-alert`,
|
|
48553
|
+
node.variant ? `${ctx.prefix}-alert-${node.variant}` : void 0,
|
|
48554
|
+
...ctx.getCommonClasses(node)
|
|
48555
|
+
]);
|
|
48556
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48557
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48558
|
+
const dismissBtn = node.dismissible ? ` <button class="${ctx.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
48559
|
+
return `<div class="${classes}"${styleAttr} role="alert">${ctx.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
48560
|
+
}
|
|
48561
|
+
function renderToast(node, ctx) {
|
|
48562
|
+
const classes = ctx.buildClassString([
|
|
48563
|
+
`${ctx.prefix}-toast`,
|
|
48564
|
+
node.position ? `${ctx.prefix}-toast-${node.position}` : void 0,
|
|
48565
|
+
node.variant ? `${ctx.prefix}-toast-${node.variant}` : void 0,
|
|
48566
|
+
...ctx.getCommonClasses(node)
|
|
48567
|
+
]);
|
|
48568
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48569
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48570
|
+
return `<div class="${classes}"${styleAttr} role="status">${ctx.escapeHtml(node.content)}</div>`;
|
|
48571
|
+
}
|
|
48572
|
+
function renderProgress(node, ctx) {
|
|
48573
|
+
const classes = ctx.buildClassString([
|
|
48574
|
+
`${ctx.prefix}-progress`,
|
|
48575
|
+
...ctx.getCommonClasses(node)
|
|
48576
|
+
]);
|
|
48577
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48578
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48579
|
+
const value = node.value || 0;
|
|
48580
|
+
const max = node.max || 100;
|
|
48581
|
+
const percentage = Math.round(value / max * 100);
|
|
48582
|
+
const label = node.label ? `<span class="${ctx.prefix}-progress-label">${ctx.escapeHtml(node.label)}</span>` : "";
|
|
48583
|
+
if (node.indeterminate) {
|
|
48584
|
+
return `<div class="${classes} ${ctx.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
48258
48585
|
}
|
|
48259
|
-
|
|
48260
|
-
|
|
48261
|
-
|
|
48262
|
-
|
|
48586
|
+
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
48587
|
+
${label}
|
|
48588
|
+
<div class="${ctx.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
48589
|
+
</div>`;
|
|
48590
|
+
}
|
|
48591
|
+
function renderSpinner(node, ctx) {
|
|
48592
|
+
const sizeResolved = resolveSizeValue(node.size, "spinner", ctx.prefix);
|
|
48593
|
+
const classes = ctx.buildClassString([
|
|
48594
|
+
`${ctx.prefix}-spinner`,
|
|
48595
|
+
sizeResolved.className,
|
|
48596
|
+
...ctx.getCommonClasses(node)
|
|
48597
|
+
]);
|
|
48598
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48599
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48600
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48601
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48602
|
+
const label = node.label || "Loading...";
|
|
48603
|
+
return `<span class="${classes}"${styleAttr} role="status" aria-label="${ctx.escapeHtml(label)}"></span>`;
|
|
48604
|
+
}
|
|
48605
|
+
|
|
48606
|
+
// src/renderer/html/renderers/input.ts
|
|
48607
|
+
function renderInput(node, ctx) {
|
|
48608
|
+
const inputClasses = ctx.buildClassString([
|
|
48609
|
+
`${ctx.prefix}-input`,
|
|
48610
|
+
node.icon ? `${ctx.prefix}-input-with-icon` : void 0,
|
|
48611
|
+
...ctx.getCommonClasses(node)
|
|
48612
|
+
]);
|
|
48613
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48614
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48615
|
+
const attrs = {
|
|
48616
|
+
class: inputClasses,
|
|
48617
|
+
type: node.inputType || "text",
|
|
48618
|
+
placeholder: node.placeholder,
|
|
48619
|
+
value: node.value,
|
|
48620
|
+
disabled: node.disabled,
|
|
48621
|
+
required: node.required,
|
|
48622
|
+
readonly: node.readonly
|
|
48623
|
+
};
|
|
48624
|
+
const inputElement = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48625
|
+
if (node.icon) {
|
|
48626
|
+
const iconData = getIconData(node.icon);
|
|
48627
|
+
let iconHtml;
|
|
48628
|
+
if (iconData) {
|
|
48629
|
+
iconHtml = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-input-icon`);
|
|
48630
|
+
} else {
|
|
48631
|
+
iconHtml = `<span class="${ctx.prefix}-input-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48263
48632
|
}
|
|
48264
|
-
const
|
|
48265
|
-
|
|
48266
|
-
|
|
48633
|
+
const wrapperClasses = ctx.buildClassString([`${ctx.prefix}-input-wrapper`]);
|
|
48634
|
+
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48635
|
+
const shouldShowLabel = node.label && !(node.label === "Label" && node.placeholder);
|
|
48636
|
+
if (shouldShowLabel) {
|
|
48637
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48638
|
+
${wrapper}`;
|
|
48267
48639
|
}
|
|
48268
|
-
return
|
|
48640
|
+
return wrapper;
|
|
48269
48641
|
}
|
|
48270
|
-
|
|
48271
|
-
|
|
48642
|
+
const input = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48643
|
+
const shouldShowLabel2 = node.label && !(node.label === "Label" && node.placeholder);
|
|
48644
|
+
if (shouldShowLabel2) {
|
|
48645
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48646
|
+
${input}`;
|
|
48272
48647
|
}
|
|
48273
|
-
return
|
|
48648
|
+
return input;
|
|
48649
|
+
}
|
|
48650
|
+
function renderTextarea(node, ctx) {
|
|
48651
|
+
const classes = ctx.buildClassString([
|
|
48652
|
+
`${ctx.prefix}-input`,
|
|
48653
|
+
...ctx.getCommonClasses(node)
|
|
48654
|
+
]);
|
|
48655
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48656
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48657
|
+
const attrs = {
|
|
48658
|
+
class: classes,
|
|
48659
|
+
placeholder: node.placeholder,
|
|
48660
|
+
disabled: node.disabled,
|
|
48661
|
+
required: node.required,
|
|
48662
|
+
rows: node.rows?.toString()
|
|
48663
|
+
};
|
|
48664
|
+
const textarea = `<textarea${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.value || "")}</textarea>`;
|
|
48665
|
+
if (node.label) {
|
|
48666
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48667
|
+
${textarea}`;
|
|
48668
|
+
}
|
|
48669
|
+
return textarea;
|
|
48670
|
+
}
|
|
48671
|
+
function renderSelect(node, ctx) {
|
|
48672
|
+
const classes = ctx.buildClassString([
|
|
48673
|
+
`${ctx.prefix}-input`,
|
|
48674
|
+
...ctx.getCommonClasses(node)
|
|
48675
|
+
]);
|
|
48676
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48677
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48678
|
+
const attrs = {
|
|
48679
|
+
class: classes,
|
|
48680
|
+
disabled: node.disabled,
|
|
48681
|
+
required: node.required
|
|
48682
|
+
};
|
|
48683
|
+
const options = node.options.map((opt) => {
|
|
48684
|
+
if (typeof opt === "string") {
|
|
48685
|
+
const selected2 = opt === node.value ? " selected" : "";
|
|
48686
|
+
return `<option value="${ctx.escapeHtml(opt)}"${selected2}>${ctx.escapeHtml(opt)}</option>`;
|
|
48687
|
+
}
|
|
48688
|
+
const selected = opt.value === node.value ? " selected" : "";
|
|
48689
|
+
return `<option value="${ctx.escapeHtml(opt.value)}"${selected}>${ctx.escapeHtml(opt.label)}</option>`;
|
|
48690
|
+
}).join("\n");
|
|
48691
|
+
const placeholder = node.placeholder ? `<option value="" disabled selected>${ctx.escapeHtml(node.placeholder)}</option>
|
|
48692
|
+
` : "";
|
|
48693
|
+
const select = `<select${ctx.buildAttrsString(attrs)}${styleAttr}>
|
|
48694
|
+
${placeholder}${options}
|
|
48695
|
+
</select>`;
|
|
48696
|
+
if (node.label) {
|
|
48697
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48698
|
+
${select}`;
|
|
48699
|
+
}
|
|
48700
|
+
return select;
|
|
48701
|
+
}
|
|
48702
|
+
function renderCheckbox(node, ctx) {
|
|
48703
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48704
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48705
|
+
const attrs = {
|
|
48706
|
+
type: "checkbox",
|
|
48707
|
+
checked: node.checked,
|
|
48708
|
+
disabled: node.disabled
|
|
48709
|
+
};
|
|
48710
|
+
const checkbox = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48711
|
+
if (node.label) {
|
|
48712
|
+
return `<label class="${ctx.prefix}-checkbox"${styleAttr}>${checkbox}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48713
|
+
}
|
|
48714
|
+
return checkbox;
|
|
48715
|
+
}
|
|
48716
|
+
function renderRadio(node, ctx) {
|
|
48717
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48718
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48719
|
+
const attrs = {
|
|
48720
|
+
type: "radio",
|
|
48721
|
+
name: node.name,
|
|
48722
|
+
checked: node.checked,
|
|
48723
|
+
disabled: node.disabled
|
|
48724
|
+
};
|
|
48725
|
+
const radio = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48726
|
+
if (node.label) {
|
|
48727
|
+
return `<label class="${ctx.prefix}-radio"${styleAttr}>${radio}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48728
|
+
}
|
|
48729
|
+
return radio;
|
|
48730
|
+
}
|
|
48731
|
+
function renderSwitch(node, ctx) {
|
|
48732
|
+
const classes = ctx.buildClassString([
|
|
48733
|
+
`${ctx.prefix}-switch`,
|
|
48734
|
+
...ctx.getCommonClasses(node)
|
|
48735
|
+
]);
|
|
48736
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48737
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48738
|
+
const attrs = {
|
|
48739
|
+
type: "checkbox",
|
|
48740
|
+
role: "switch",
|
|
48741
|
+
checked: node.checked,
|
|
48742
|
+
disabled: node.disabled
|
|
48743
|
+
};
|
|
48744
|
+
const switchEl = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48745
|
+
if (node.label) {
|
|
48746
|
+
return `<label class="${classes}"${styleAttr}>${switchEl} ${ctx.escapeHtml(node.label)}</label>`;
|
|
48747
|
+
}
|
|
48748
|
+
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
48749
|
+
}
|
|
48750
|
+
function renderSlider(node, ctx) {
|
|
48751
|
+
const classes = ctx.buildClassString([
|
|
48752
|
+
`${ctx.prefix}-slider`,
|
|
48753
|
+
...ctx.getCommonClasses(node)
|
|
48754
|
+
]);
|
|
48755
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48756
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48757
|
+
const attrs = {
|
|
48758
|
+
class: classes,
|
|
48759
|
+
type: "range",
|
|
48760
|
+
min: node.min?.toString(),
|
|
48761
|
+
max: node.max?.toString(),
|
|
48762
|
+
step: node.step?.toString(),
|
|
48763
|
+
value: node.value?.toString(),
|
|
48764
|
+
disabled: node.disabled
|
|
48765
|
+
};
|
|
48766
|
+
const slider = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48767
|
+
if (node.label) {
|
|
48768
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48769
|
+
${slider}`;
|
|
48770
|
+
}
|
|
48771
|
+
return slider;
|
|
48772
|
+
}
|
|
48773
|
+
|
|
48774
|
+
// src/renderer/html/renderers/display.ts
|
|
48775
|
+
function renderImage(node, ctx) {
|
|
48776
|
+
const classes = ctx.buildClassString([
|
|
48777
|
+
`${ctx.prefix}-image`,
|
|
48778
|
+
...ctx.getCommonClasses(node)
|
|
48779
|
+
]);
|
|
48780
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48781
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48782
|
+
if (node.src) {
|
|
48783
|
+
const attrs = {
|
|
48784
|
+
class: classes,
|
|
48785
|
+
src: node.src,
|
|
48786
|
+
alt: node.alt || "Image"
|
|
48787
|
+
};
|
|
48788
|
+
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48789
|
+
return `<img${ctx.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48790
|
+
}
|
|
48791
|
+
const label = node.alt || "Image";
|
|
48792
|
+
const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
48793
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(label)}">${icon}<span>${ctx.escapeHtml(label)}</span></div>`;
|
|
48794
|
+
}
|
|
48795
|
+
function renderPlaceholder(node, ctx) {
|
|
48796
|
+
const classes = ctx.buildClassString([
|
|
48797
|
+
`${ctx.prefix}-placeholder`,
|
|
48798
|
+
node.children && node.children.length > 0 ? `${ctx.prefix}-placeholder-with-children` : void 0,
|
|
48799
|
+
...ctx.getCommonClasses(node)
|
|
48800
|
+
]);
|
|
48801
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48802
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48803
|
+
const label = node.label ? ctx.escapeHtml(node.label) : "Placeholder";
|
|
48804
|
+
if (node.children && node.children.length > 0) {
|
|
48805
|
+
const childrenHtml = ctx.renderChildren(node.children);
|
|
48806
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48807
|
+
<span class="${ctx.prefix}-placeholder-label">${label}</span>
|
|
48808
|
+
<div class="${ctx.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
48809
|
+
</div>`;
|
|
48810
|
+
}
|
|
48811
|
+
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
48812
|
+
}
|
|
48813
|
+
function renderAvatar(node, ctx) {
|
|
48814
|
+
const sizeResolved = resolveSizeValue(node.size, "avatar", ctx.prefix);
|
|
48815
|
+
const classes = ctx.buildClassString([
|
|
48816
|
+
`${ctx.prefix}-avatar`,
|
|
48817
|
+
sizeResolved.className,
|
|
48818
|
+
...ctx.getCommonClasses(node)
|
|
48819
|
+
]);
|
|
48820
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48821
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48822
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48823
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48824
|
+
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48825
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
48826
|
+
}
|
|
48827
|
+
function renderBadge(node, ctx) {
|
|
48828
|
+
if (node.icon) {
|
|
48829
|
+
const iconData = getIconData(node.icon);
|
|
48830
|
+
const classes2 = ctx.buildClassString([
|
|
48831
|
+
`${ctx.prefix}-badge-icon`,
|
|
48832
|
+
node.size ? `${ctx.prefix}-badge-icon-${node.size}` : void 0,
|
|
48833
|
+
node.variant ? `${ctx.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48834
|
+
...ctx.getCommonClasses(node)
|
|
48835
|
+
]);
|
|
48836
|
+
const styles2 = ctx.buildCommonStyles(node);
|
|
48837
|
+
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48838
|
+
if (iconData) {
|
|
48839
|
+
const svg = renderIconSvg(iconData, 24, 2, `${ctx.prefix}-icon`);
|
|
48840
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="${ctx.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48841
|
+
}
|
|
48842
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48843
|
+
}
|
|
48844
|
+
const isDot = !node.content || node.content.trim() === "";
|
|
48845
|
+
const classes = ctx.buildClassString([
|
|
48846
|
+
`${ctx.prefix}-badge`,
|
|
48847
|
+
isDot ? `${ctx.prefix}-badge-dot` : void 0,
|
|
48848
|
+
node.variant ? `${ctx.prefix}-badge-${node.variant}` : void 0,
|
|
48849
|
+
node.pill ? `${ctx.prefix}-badge-pill` : void 0,
|
|
48850
|
+
...ctx.getCommonClasses(node)
|
|
48851
|
+
]);
|
|
48852
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48853
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48854
|
+
return `<span class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</span>`;
|
|
48855
|
+
}
|
|
48856
|
+
function renderIcon(node, ctx) {
|
|
48857
|
+
const iconData = getIconData(node.name);
|
|
48858
|
+
const sizeResolved = resolveSizeValue(node.size, "icon", ctx.prefix);
|
|
48859
|
+
const wrapperClasses = ctx.buildClassString([
|
|
48860
|
+
`${ctx.prefix}-icon-wrapper`,
|
|
48861
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
48862
|
+
...ctx.getCommonClasses(node)
|
|
48863
|
+
]);
|
|
48864
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48865
|
+
if (iconData) {
|
|
48866
|
+
const iconClasses = buildClassString([
|
|
48867
|
+
`${ctx.prefix}-icon`,
|
|
48868
|
+
sizeResolved.className
|
|
48869
|
+
]);
|
|
48870
|
+
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
48871
|
+
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
48872
|
+
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48873
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
48874
|
+
}
|
|
48875
|
+
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
48876
|
+
const sizeNum = parseInt(size, 10);
|
|
48877
|
+
const placeholderSvg = `<svg class="${ctx.prefix}-icon ${sizeResolved.className || ""}" width="${sizeNum}" height="${sizeNum}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
48878
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
48879
|
+
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
48880
|
+
</svg>`;
|
|
48881
|
+
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48882
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${ctx.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
48883
|
+
}
|
|
48884
|
+
|
|
48885
|
+
// src/renderer/html/renderers/overlay.ts
|
|
48886
|
+
function renderTooltip(node, ctx) {
|
|
48887
|
+
const classes = ctx.buildClassString([
|
|
48888
|
+
`${ctx.prefix}-tooltip-wrapper`,
|
|
48889
|
+
...ctx.getCommonClasses(node)
|
|
48890
|
+
]);
|
|
48891
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48892
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48893
|
+
const position = node.position || "top";
|
|
48894
|
+
const children = ctx.renderChildren(node.children);
|
|
48895
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48896
|
+
${children}
|
|
48897
|
+
<div class="${ctx.prefix}-tooltip ${ctx.prefix}-tooltip-${position}" role="tooltip">${ctx.escapeHtml(node.content)}</div>
|
|
48898
|
+
</div>`;
|
|
48899
|
+
}
|
|
48900
|
+
function renderPopover(node, ctx) {
|
|
48901
|
+
const classes = ctx.buildClassString([
|
|
48902
|
+
`${ctx.prefix}-popover`,
|
|
48903
|
+
...ctx.getCommonClasses(node)
|
|
48904
|
+
]);
|
|
48905
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48906
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48907
|
+
const title = node.title ? `<div class="${ctx.prefix}-popover-header">${ctx.escapeHtml(node.title)}</div>
|
|
48908
|
+
` : "";
|
|
48909
|
+
const children = ctx.renderChildren(node.children);
|
|
48910
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48911
|
+
${title}<div class="${ctx.prefix}-popover-body">
|
|
48912
|
+
${children}
|
|
48913
|
+
</div>
|
|
48914
|
+
</div>`;
|
|
48915
|
+
}
|
|
48916
|
+
function renderDropdown(node, ctx) {
|
|
48917
|
+
const classes = ctx.buildClassString([
|
|
48918
|
+
`${ctx.prefix}-dropdown`,
|
|
48919
|
+
...ctx.getCommonClasses(node)
|
|
48920
|
+
]);
|
|
48921
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48922
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48923
|
+
const items = node.items.map((item) => {
|
|
48924
|
+
if ("type" in item && item.type === "divider") {
|
|
48925
|
+
return `<hr class="${ctx.prefix}-divider" />`;
|
|
48926
|
+
}
|
|
48927
|
+
const dropdownItem = item;
|
|
48928
|
+
const itemClasses = ctx.buildClassString([
|
|
48929
|
+
`${ctx.prefix}-dropdown-item`,
|
|
48930
|
+
dropdownItem.danger ? `${ctx.prefix}-dropdown-item-danger` : void 0,
|
|
48931
|
+
dropdownItem.disabled ? `${ctx.prefix}-dropdown-item-disabled` : void 0
|
|
48932
|
+
]);
|
|
48933
|
+
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${ctx.escapeHtml(dropdownItem.label)}</button>`;
|
|
48934
|
+
}).join("\n");
|
|
48935
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48936
|
+
${items}
|
|
48937
|
+
</div>`;
|
|
48938
|
+
}
|
|
48939
|
+
|
|
48940
|
+
// src/renderer/html/renderers/navigation.ts
|
|
48941
|
+
function renderIconHtml(iconName, prefix) {
|
|
48942
|
+
return `<span class="${prefix}-icon" data-icon="${iconName}"></span>`;
|
|
48943
|
+
}
|
|
48944
|
+
function renderNavItem(item, ctx) {
|
|
48945
|
+
const linkClasses = ctx.buildClassString([
|
|
48946
|
+
`${ctx.prefix}-nav-link`,
|
|
48947
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48948
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48949
|
+
]);
|
|
48950
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48951
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48952
|
+
}
|
|
48953
|
+
function renderNavChildren(children, ctx) {
|
|
48954
|
+
return children.map((child) => {
|
|
48955
|
+
if (child.type === "divider") {
|
|
48956
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48957
|
+
}
|
|
48958
|
+
if (child.type === "group") {
|
|
48959
|
+
const groupItems = child.items.map((item) => {
|
|
48960
|
+
if (item.type === "divider") {
|
|
48961
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48962
|
+
}
|
|
48963
|
+
return renderNavItem(item, ctx);
|
|
48964
|
+
}).join("\n");
|
|
48965
|
+
return `<div class="${ctx.prefix}-nav-group">
|
|
48966
|
+
<div class="${ctx.prefix}-nav-group-label">${ctx.escapeHtml(child.label)}</div>
|
|
48967
|
+
${groupItems}
|
|
48968
|
+
</div>`;
|
|
48969
|
+
}
|
|
48970
|
+
if (child.type === "item") {
|
|
48971
|
+
return renderNavItem(child, ctx);
|
|
48972
|
+
}
|
|
48973
|
+
return "";
|
|
48974
|
+
}).join("\n");
|
|
48975
|
+
}
|
|
48976
|
+
function renderNav(node, ctx) {
|
|
48977
|
+
const classes = ctx.buildClassString([
|
|
48978
|
+
`${ctx.prefix}-nav`,
|
|
48979
|
+
node.vertical ? `${ctx.prefix}-nav-vertical` : void 0,
|
|
48980
|
+
...ctx.getCommonClasses(node)
|
|
48981
|
+
]);
|
|
48982
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48983
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48984
|
+
if (node.children && node.children.length > 0) {
|
|
48985
|
+
const content = renderNavChildren(node.children, ctx);
|
|
48986
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48987
|
+
${content}
|
|
48988
|
+
</nav>`;
|
|
48989
|
+
}
|
|
48990
|
+
const items = node.items.map((item) => {
|
|
48991
|
+
if (typeof item === "string") {
|
|
48992
|
+
return `<a class="${ctx.prefix}-nav-link" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48993
|
+
}
|
|
48994
|
+
const linkClasses = ctx.buildClassString([
|
|
48995
|
+
`${ctx.prefix}-nav-link`,
|
|
48996
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48997
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48998
|
+
]);
|
|
48999
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
49000
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
49001
|
+
}).join("\n");
|
|
49002
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
49003
|
+
${items}
|
|
49004
|
+
</nav>`;
|
|
49005
|
+
}
|
|
49006
|
+
function renderTabs(node, ctx) {
|
|
49007
|
+
const classes = ctx.buildClassString([
|
|
49008
|
+
`${ctx.prefix}-tabs`,
|
|
49009
|
+
...ctx.getCommonClasses(node)
|
|
49010
|
+
]);
|
|
49011
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49012
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49013
|
+
const tabList = node.items.map((label, idx) => {
|
|
49014
|
+
const isActive = idx === (node.active || 0);
|
|
49015
|
+
const tabClasses = `${ctx.prefix}-tab${isActive ? ` ${ctx.prefix}-tab-active` : ""}`;
|
|
49016
|
+
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${ctx.escapeHtml(label)}</button>`;
|
|
49017
|
+
}).join("\n");
|
|
49018
|
+
return `<div class="${classes}"${styleAttr}>
|
|
49019
|
+
<div class="${ctx.prefix}-tab-list" role="tablist">
|
|
49020
|
+
${tabList}
|
|
49021
|
+
</div>
|
|
49022
|
+
</div>`;
|
|
49023
|
+
}
|
|
49024
|
+
function renderBreadcrumb(node, ctx) {
|
|
49025
|
+
const classes = ctx.buildClassString([
|
|
49026
|
+
`${ctx.prefix}-breadcrumb`,
|
|
49027
|
+
...ctx.getCommonClasses(node)
|
|
49028
|
+
]);
|
|
49029
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49030
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49031
|
+
const items = node.items.map((item, idx) => {
|
|
49032
|
+
const isLast = idx === node.items.length - 1;
|
|
49033
|
+
if (typeof item === "string") {
|
|
49034
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
49035
|
+
}
|
|
49036
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item.label)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="${item.href || "#"}">${ctx.escapeHtml(item.label)}</a>`;
|
|
49037
|
+
}).join(" / ");
|
|
49038
|
+
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49039
|
+
}
|
|
49040
|
+
|
|
49041
|
+
// src/renderer/html/semantic.ts
|
|
49042
|
+
function renderSemanticMarker(component, variant, prefix) {
|
|
49043
|
+
switch (component) {
|
|
49044
|
+
case "avatar":
|
|
49045
|
+
const avatarSize = variant || "sm";
|
|
49046
|
+
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49047
|
+
case "dot":
|
|
49048
|
+
const dotVariant = variant || "default";
|
|
49049
|
+
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49050
|
+
case "icon":
|
|
49051
|
+
const iconName = variant || "default";
|
|
49052
|
+
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49053
|
+
default:
|
|
49054
|
+
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49055
|
+
}
|
|
49056
|
+
}
|
|
49057
|
+
function renderSemanticMarkerWithContent(component, variant, content, prefix, escapeHtml) {
|
|
49058
|
+
switch (component) {
|
|
49059
|
+
case "badge":
|
|
49060
|
+
const badgeVariant = variant || "default";
|
|
49061
|
+
const escapedContent = escapeHtml(content);
|
|
49062
|
+
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49063
|
+
default:
|
|
49064
|
+
return renderSemanticMarker(component, variant, prefix) + escapeHtml(content);
|
|
49065
|
+
}
|
|
49066
|
+
}
|
|
49067
|
+
function renderSemanticMarkers(text, prefix, escapeHtml) {
|
|
49068
|
+
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49069
|
+
let result = "";
|
|
49070
|
+
let lastIndex = 0;
|
|
49071
|
+
let match;
|
|
49072
|
+
while ((match = markerPattern.exec(text)) !== null) {
|
|
49073
|
+
if (match.index > lastIndex) {
|
|
49074
|
+
result += escapeHtml(text.substring(lastIndex, match.index));
|
|
49075
|
+
}
|
|
49076
|
+
const [fullMatch, component, variant] = match;
|
|
49077
|
+
const comp = component.toLowerCase();
|
|
49078
|
+
const varnt = variant?.toLowerCase();
|
|
49079
|
+
if (comp === "badge") {
|
|
49080
|
+
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49081
|
+
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49082
|
+
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49083
|
+
result += renderSemanticMarkerWithContent(comp, varnt, badgeContent, prefix, escapeHtml);
|
|
49084
|
+
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49085
|
+
markerPattern.lastIndex = lastIndex;
|
|
49086
|
+
} else {
|
|
49087
|
+
result += renderSemanticMarker(comp, varnt, prefix);
|
|
49088
|
+
lastIndex = match.index + fullMatch.length;
|
|
49089
|
+
}
|
|
49090
|
+
}
|
|
49091
|
+
if (lastIndex < text.length) {
|
|
49092
|
+
result += escapeHtml(text.substring(lastIndex));
|
|
49093
|
+
}
|
|
49094
|
+
if (lastIndex === 0) {
|
|
49095
|
+
return escapeHtml(text);
|
|
49096
|
+
}
|
|
49097
|
+
return result;
|
|
49098
|
+
}
|
|
49099
|
+
function renderTableCellContent(content, prefix, escapeHtml) {
|
|
49100
|
+
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49101
|
+
if (avatarMatch) {
|
|
49102
|
+
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49103
|
+
const avatarHtml = renderSemanticMarker("avatar", avatarVariant, prefix);
|
|
49104
|
+
const restContent = content.slice(avatarMatch[0].length);
|
|
49105
|
+
const restHtml = renderSemanticMarkers(restContent, prefix, escapeHtml);
|
|
49106
|
+
const lines = restHtml.split("\n");
|
|
49107
|
+
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49108
|
+
return `<div class="${prefix}-cell-avatar-layout">${avatarHtml}<div class="${prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49109
|
+
}
|
|
49110
|
+
const withMarkers = renderSemanticMarkers(content, prefix, escapeHtml);
|
|
49111
|
+
return withMarkers.replace(/\n/g, "<br>");
|
|
49112
|
+
}
|
|
49113
|
+
|
|
49114
|
+
// src/renderer/html/renderers/data.ts
|
|
49115
|
+
function renderTable(node, ctx) {
|
|
49116
|
+
const classes = ctx.buildClassString([
|
|
49117
|
+
`${ctx.prefix}-table`,
|
|
49118
|
+
node.striped ? `${ctx.prefix}-table-striped` : void 0,
|
|
49119
|
+
node.bordered ? `${ctx.prefix}-table-bordered` : void 0,
|
|
49120
|
+
node.hover ? `${ctx.prefix}-table-hover` : void 0,
|
|
49121
|
+
...ctx.getCommonClasses(node)
|
|
49122
|
+
]);
|
|
49123
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49124
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49125
|
+
const thead = `<thead><tr>${node.columns.map((col) => `<th>${ctx.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49126
|
+
const tbody = `<tbody>${node.rows.map(
|
|
49127
|
+
(row) => `<tr>${row.map((cell) => {
|
|
49128
|
+
if (typeof cell === "string") {
|
|
49129
|
+
return `<td>${renderTableCellContent(cell, ctx.prefix, ctx.escapeHtml)}</td>`;
|
|
49130
|
+
}
|
|
49131
|
+
return `<td>${ctx.renderNode(cell)}</td>`;
|
|
49132
|
+
}).join("")}</tr>`
|
|
49133
|
+
).join("")}</tbody>`;
|
|
49134
|
+
return `<table class="${classes}"${styleAttr}>
|
|
49135
|
+
${thead}
|
|
49136
|
+
${tbody}
|
|
49137
|
+
</table>`;
|
|
49138
|
+
}
|
|
49139
|
+
function renderList(node, ctx) {
|
|
49140
|
+
const tag = node.ordered ? "ol" : "ul";
|
|
49141
|
+
const classes = ctx.buildClassString([
|
|
49142
|
+
`${ctx.prefix}-list`,
|
|
49143
|
+
node.ordered ? `${ctx.prefix}-list-ordered` : void 0,
|
|
49144
|
+
node.none ? `${ctx.prefix}-list-none` : void 0,
|
|
49145
|
+
...ctx.getCommonClasses(node)
|
|
49146
|
+
]);
|
|
49147
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49148
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49149
|
+
const items = node.items.map((item) => {
|
|
49150
|
+
if (typeof item === "string") {
|
|
49151
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item)}</li>`;
|
|
49152
|
+
}
|
|
49153
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item.content)}</li>`;
|
|
49154
|
+
}).join("\n");
|
|
49155
|
+
return `<${tag} class="${classes}"${styleAttr}>
|
|
49156
|
+
${items}
|
|
49157
|
+
</${tag}>`;
|
|
49158
|
+
}
|
|
49159
|
+
|
|
49160
|
+
// src/renderer/html/renderers/divider.ts
|
|
49161
|
+
function renderDivider(node, ctx) {
|
|
49162
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49163
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49164
|
+
return `<hr class="${ctx.prefix}-divider"${styleAttr} />`;
|
|
48274
49165
|
}
|
|
48275
49166
|
|
|
48276
49167
|
// src/renderer/html/index.ts
|
|
@@ -48312,8 +49203,97 @@ function resolveSizeValueToCss(value) {
|
|
|
48312
49203
|
return void 0;
|
|
48313
49204
|
}
|
|
48314
49205
|
var HtmlRenderer = class extends BaseRenderer {
|
|
49206
|
+
/**
|
|
49207
|
+
* Node type to renderer method mapping
|
|
49208
|
+
*/
|
|
49209
|
+
nodeRenderers;
|
|
48315
49210
|
constructor(options = {}) {
|
|
48316
49211
|
super(options);
|
|
49212
|
+
this.nodeRenderers = this.createNodeRenderers();
|
|
49213
|
+
}
|
|
49214
|
+
/**
|
|
49215
|
+
* Get render context for external renderer functions
|
|
49216
|
+
*/
|
|
49217
|
+
getRenderContext() {
|
|
49218
|
+
return {
|
|
49219
|
+
prefix: this.prefix,
|
|
49220
|
+
escapeHtml: this.escapeHtml.bind(this),
|
|
49221
|
+
buildClassString: this.buildClassString.bind(this),
|
|
49222
|
+
buildAttrsString: this.buildAttrsString.bind(this),
|
|
49223
|
+
buildCommonStyles: this.buildCommonStyles.bind(this),
|
|
49224
|
+
getCommonClasses: this.getCommonClasses.bind(this),
|
|
49225
|
+
renderChildren: this.renderChildren.bind(this),
|
|
49226
|
+
renderNode: this.renderNode.bind(this)
|
|
49227
|
+
};
|
|
49228
|
+
}
|
|
49229
|
+
/**
|
|
49230
|
+
* Get grid render context (extends RenderContext with buildColStyles)
|
|
49231
|
+
*/
|
|
49232
|
+
getGridRenderContext() {
|
|
49233
|
+
return {
|
|
49234
|
+
...this.getRenderContext(),
|
|
49235
|
+
buildColStyles: this.buildColStyles.bind(this)
|
|
49236
|
+
};
|
|
49237
|
+
}
|
|
49238
|
+
/**
|
|
49239
|
+
* Create the node renderer mapping
|
|
49240
|
+
*/
|
|
49241
|
+
createNodeRenderers() {
|
|
49242
|
+
return {
|
|
49243
|
+
// Layout nodes
|
|
49244
|
+
Page: (node) => this.renderPage(node),
|
|
49245
|
+
Header: (node) => this.renderHeader(node),
|
|
49246
|
+
Main: (node) => this.renderMain(node),
|
|
49247
|
+
Footer: (node) => this.renderFooter(node),
|
|
49248
|
+
Sidebar: (node) => this.renderSidebar(node),
|
|
49249
|
+
Section: (node) => this.renderSection(node),
|
|
49250
|
+
// Grid nodes
|
|
49251
|
+
Row: (node) => this.renderRow(node),
|
|
49252
|
+
Col: (node) => this.renderCol(node),
|
|
49253
|
+
// Container nodes
|
|
49254
|
+
Card: (node) => this.renderCard(node),
|
|
49255
|
+
Modal: (node) => this.renderModal(node),
|
|
49256
|
+
Drawer: (node) => this.renderDrawer(node),
|
|
49257
|
+
Accordion: (node) => this.renderAccordion(node),
|
|
49258
|
+
// Text nodes
|
|
49259
|
+
Text: (node) => this.renderText(node),
|
|
49260
|
+
Title: (node) => this.renderTitle(node),
|
|
49261
|
+
Link: (node) => this.renderLink(node),
|
|
49262
|
+
// Input nodes
|
|
49263
|
+
Input: (node) => this.renderInput(node),
|
|
49264
|
+
Textarea: (node) => this.renderTextarea(node),
|
|
49265
|
+
Select: (node) => this.renderSelect(node),
|
|
49266
|
+
Checkbox: (node) => this.renderCheckbox(node),
|
|
49267
|
+
Radio: (node) => this.renderRadio(node),
|
|
49268
|
+
Switch: (node) => this.renderSwitch(node),
|
|
49269
|
+
Slider: (node) => this.renderSlider(node),
|
|
49270
|
+
// Button
|
|
49271
|
+
Button: (node) => this.renderButton(node),
|
|
49272
|
+
// Display nodes
|
|
49273
|
+
Image: (node) => this.renderImage(node),
|
|
49274
|
+
Placeholder: (node) => this.renderPlaceholder(node),
|
|
49275
|
+
Avatar: (node) => this.renderAvatar(node),
|
|
49276
|
+
Badge: (node) => this.renderBadge(node),
|
|
49277
|
+
Icon: (node) => this.renderIcon(node),
|
|
49278
|
+
// Data nodes
|
|
49279
|
+
Table: (node) => this.renderTable(node),
|
|
49280
|
+
List: (node) => this.renderList(node),
|
|
49281
|
+
// Feedback nodes
|
|
49282
|
+
Alert: (node) => this.renderAlert(node),
|
|
49283
|
+
Toast: (node) => this.renderToast(node),
|
|
49284
|
+
Progress: (node) => this.renderProgress(node),
|
|
49285
|
+
Spinner: (node) => this.renderSpinner(node),
|
|
49286
|
+
// Overlay nodes
|
|
49287
|
+
Tooltip: (node) => this.renderTooltip(node),
|
|
49288
|
+
Popover: (node) => this.renderPopover(node),
|
|
49289
|
+
Dropdown: (node) => this.renderDropdown(node),
|
|
49290
|
+
// Navigation nodes
|
|
49291
|
+
Nav: (node) => this.renderNav(node),
|
|
49292
|
+
Tabs: (node) => this.renderTabs(node),
|
|
49293
|
+
Breadcrumb: (node) => this.renderBreadcrumb(node),
|
|
49294
|
+
// Other
|
|
49295
|
+
Divider: (node) => this.renderDivider(node)
|
|
49296
|
+
};
|
|
48317
49297
|
}
|
|
48318
49298
|
/**
|
|
48319
49299
|
* Render a page node
|
|
@@ -48353,104 +49333,11 @@ ${title}${children}
|
|
|
48353
49333
|
* Render any AST node
|
|
48354
49334
|
*/
|
|
48355
49335
|
renderNode(node) {
|
|
48356
|
-
|
|
48357
|
-
|
|
48358
|
-
|
|
48359
|
-
return this.renderPage(node);
|
|
48360
|
-
case "Header":
|
|
48361
|
-
return this.renderHeader(node);
|
|
48362
|
-
case "Main":
|
|
48363
|
-
return this.renderMain(node);
|
|
48364
|
-
case "Footer":
|
|
48365
|
-
return this.renderFooter(node);
|
|
48366
|
-
case "Sidebar":
|
|
48367
|
-
return this.renderSidebar(node);
|
|
48368
|
-
case "Section":
|
|
48369
|
-
return this.renderSection(node);
|
|
48370
|
-
// Grid nodes
|
|
48371
|
-
case "Row":
|
|
48372
|
-
return this.renderRow(node);
|
|
48373
|
-
case "Col":
|
|
48374
|
-
return this.renderCol(node);
|
|
48375
|
-
// Container nodes
|
|
48376
|
-
case "Card":
|
|
48377
|
-
return this.renderCard(node);
|
|
48378
|
-
case "Modal":
|
|
48379
|
-
return this.renderModal(node);
|
|
48380
|
-
case "Drawer":
|
|
48381
|
-
return this.renderDrawer(node);
|
|
48382
|
-
case "Accordion":
|
|
48383
|
-
return this.renderAccordion(node);
|
|
48384
|
-
// Text nodes
|
|
48385
|
-
case "Text":
|
|
48386
|
-
return this.renderText(node);
|
|
48387
|
-
case "Title":
|
|
48388
|
-
return this.renderTitle(node);
|
|
48389
|
-
case "Link":
|
|
48390
|
-
return this.renderLink(node);
|
|
48391
|
-
// Input nodes
|
|
48392
|
-
case "Input":
|
|
48393
|
-
return this.renderInput(node);
|
|
48394
|
-
case "Textarea":
|
|
48395
|
-
return this.renderTextarea(node);
|
|
48396
|
-
case "Select":
|
|
48397
|
-
return this.renderSelect(node);
|
|
48398
|
-
case "Checkbox":
|
|
48399
|
-
return this.renderCheckbox(node);
|
|
48400
|
-
case "Radio":
|
|
48401
|
-
return this.renderRadio(node);
|
|
48402
|
-
case "Switch":
|
|
48403
|
-
return this.renderSwitch(node);
|
|
48404
|
-
case "Slider":
|
|
48405
|
-
return this.renderSlider(node);
|
|
48406
|
-
// Button
|
|
48407
|
-
case "Button":
|
|
48408
|
-
return this.renderButton(node);
|
|
48409
|
-
// Display nodes
|
|
48410
|
-
case "Image":
|
|
48411
|
-
return this.renderImage(node);
|
|
48412
|
-
case "Placeholder":
|
|
48413
|
-
return this.renderPlaceholder(node);
|
|
48414
|
-
case "Avatar":
|
|
48415
|
-
return this.renderAvatar(node);
|
|
48416
|
-
case "Badge":
|
|
48417
|
-
return this.renderBadge(node);
|
|
48418
|
-
case "Icon":
|
|
48419
|
-
return this.renderIcon(node);
|
|
48420
|
-
// Data nodes
|
|
48421
|
-
case "Table":
|
|
48422
|
-
return this.renderTable(node);
|
|
48423
|
-
case "List":
|
|
48424
|
-
return this.renderList(node);
|
|
48425
|
-
// Feedback nodes
|
|
48426
|
-
case "Alert":
|
|
48427
|
-
return this.renderAlert(node);
|
|
48428
|
-
case "Toast":
|
|
48429
|
-
return this.renderToast(node);
|
|
48430
|
-
case "Progress":
|
|
48431
|
-
return this.renderProgress(node);
|
|
48432
|
-
case "Spinner":
|
|
48433
|
-
return this.renderSpinner(node);
|
|
48434
|
-
// Overlay nodes
|
|
48435
|
-
case "Tooltip":
|
|
48436
|
-
return this.renderTooltip(node);
|
|
48437
|
-
case "Popover":
|
|
48438
|
-
return this.renderPopover(node);
|
|
48439
|
-
case "Dropdown":
|
|
48440
|
-
return this.renderDropdown(node);
|
|
48441
|
-
// Navigation nodes
|
|
48442
|
-
case "Nav":
|
|
48443
|
-
return this.renderNav(node);
|
|
48444
|
-
case "Tabs":
|
|
48445
|
-
return this.renderTabs(node);
|
|
48446
|
-
case "Breadcrumb":
|
|
48447
|
-
return this.renderBreadcrumb(node);
|
|
48448
|
-
// Other
|
|
48449
|
-
case "Divider":
|
|
48450
|
-
return this.renderDivider(node);
|
|
48451
|
-
default:
|
|
48452
|
-
return `<!-- Unknown node type: ${node.type} -->`;
|
|
49336
|
+
const renderer = this.nodeRenderers[node.type];
|
|
49337
|
+
if (renderer) {
|
|
49338
|
+
return renderer(node);
|
|
48453
49339
|
}
|
|
49340
|
+
return `<!-- Unknown node type: ${node.type} -->`;
|
|
48454
49341
|
}
|
|
48455
49342
|
/**
|
|
48456
49343
|
* Render children nodes
|
|
@@ -48493,103 +49380,28 @@ ${title}${children}
|
|
|
48493
49380
|
// Layout Node Renderers
|
|
48494
49381
|
// ===========================================
|
|
48495
49382
|
renderHeader(node) {
|
|
48496
|
-
|
|
48497
|
-
`${this.prefix}-header`,
|
|
48498
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48499
|
-
...this.getCommonClasses(node)
|
|
48500
|
-
]);
|
|
48501
|
-
const styles = this.buildCommonStyles(node);
|
|
48502
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48503
|
-
const children = this.renderChildren(node.children);
|
|
48504
|
-
return `<header class="${classes}"${styleAttr}>
|
|
48505
|
-
${children}
|
|
48506
|
-
</header>`;
|
|
49383
|
+
return renderHeader(node, this.getRenderContext());
|
|
48507
49384
|
}
|
|
48508
49385
|
renderMain(node) {
|
|
48509
|
-
|
|
48510
|
-
`${this.prefix}-main`,
|
|
48511
|
-
node.scroll ? `${this.prefix}-scroll` : void 0,
|
|
48512
|
-
...this.getCommonClasses(node)
|
|
48513
|
-
]);
|
|
48514
|
-
const styles = this.buildCommonStyles(node);
|
|
48515
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48516
|
-
const children = this.renderChildren(node.children);
|
|
48517
|
-
return `<main class="${classes}"${styleAttr}>
|
|
48518
|
-
${children}
|
|
48519
|
-
</main>`;
|
|
49386
|
+
return renderMain(node, this.getRenderContext());
|
|
48520
49387
|
}
|
|
48521
49388
|
renderFooter(node) {
|
|
48522
|
-
|
|
48523
|
-
`${this.prefix}-footer`,
|
|
48524
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48525
|
-
...this.getCommonClasses(node)
|
|
48526
|
-
]);
|
|
48527
|
-
const styles = this.buildCommonStyles(node);
|
|
48528
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48529
|
-
const children = this.renderChildren(node.children);
|
|
48530
|
-
return `<footer class="${classes}"${styleAttr}>
|
|
48531
|
-
${children}
|
|
48532
|
-
</footer>`;
|
|
49389
|
+
return renderFooter(node, this.getRenderContext());
|
|
48533
49390
|
}
|
|
48534
49391
|
renderSidebar(node) {
|
|
48535
|
-
|
|
48536
|
-
`${this.prefix}-sidebar`,
|
|
48537
|
-
node.position === "right" ? `${this.prefix}-sidebar-right` : void 0,
|
|
48538
|
-
...this.getCommonClasses(node)
|
|
48539
|
-
]);
|
|
48540
|
-
const styles = this.buildCommonStyles(node);
|
|
48541
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48542
|
-
const children = this.renderChildren(node.children);
|
|
48543
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48544
|
-
${children}
|
|
48545
|
-
</aside>`;
|
|
49392
|
+
return renderSidebar(node, this.getRenderContext());
|
|
48546
49393
|
}
|
|
48547
49394
|
renderSection(node) {
|
|
48548
|
-
|
|
48549
|
-
`${this.prefix}-section`,
|
|
48550
|
-
...this.getCommonClasses(node)
|
|
48551
|
-
]);
|
|
48552
|
-
const styles = this.buildCommonStyles(node);
|
|
48553
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48554
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48555
|
-
` : "";
|
|
48556
|
-
const children = this.renderChildren(node.children);
|
|
48557
|
-
return `<section class="${classes}"${styleAttr}>
|
|
48558
|
-
${title}${children}
|
|
48559
|
-
</section>`;
|
|
49395
|
+
return renderSection(node, this.getRenderContext());
|
|
48560
49396
|
}
|
|
48561
49397
|
// ===========================================
|
|
48562
49398
|
// Grid Node Renderers
|
|
48563
49399
|
// ===========================================
|
|
48564
49400
|
renderRow(node) {
|
|
48565
|
-
|
|
48566
|
-
`${this.prefix}-row`,
|
|
48567
|
-
...this.getCommonClasses(node)
|
|
48568
|
-
]);
|
|
48569
|
-
const styles = this.buildCommonStyles(node);
|
|
48570
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48571
|
-
const children = this.renderChildren(node.children);
|
|
48572
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48573
|
-
${children}
|
|
48574
|
-
</div>`;
|
|
49401
|
+
return renderRow(node, this.getRenderContext());
|
|
48575
49402
|
}
|
|
48576
49403
|
renderCol(node) {
|
|
48577
|
-
|
|
48578
|
-
`${this.prefix}-col`,
|
|
48579
|
-
node.span ? `${this.prefix}-col-${node.span}` : void 0,
|
|
48580
|
-
// Responsive breakpoint classes
|
|
48581
|
-
node.sm ? `${this.prefix}-col-sm-${node.sm}` : void 0,
|
|
48582
|
-
node.md ? `${this.prefix}-col-md-${node.md}` : void 0,
|
|
48583
|
-
node.lg ? `${this.prefix}-col-lg-${node.lg}` : void 0,
|
|
48584
|
-
node.xl ? `${this.prefix}-col-xl-${node.xl}` : void 0,
|
|
48585
|
-
...this.getCommonClasses(node)
|
|
48586
|
-
]);
|
|
48587
|
-
const styles = this.buildColStyles(node);
|
|
48588
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48589
|
-
const children = this.renderChildren(node.children);
|
|
48590
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48591
|
-
${children}
|
|
48592
|
-
</div>`;
|
|
49404
|
+
return renderCol(node, this.getGridRenderContext());
|
|
48593
49405
|
}
|
|
48594
49406
|
/**
|
|
48595
49407
|
* Build common inline styles for all values
|
|
@@ -48612,6 +49424,17 @@ ${children}
|
|
|
48612
49424
|
*/
|
|
48613
49425
|
buildCommonStyles(props) {
|
|
48614
49426
|
const styles = [];
|
|
49427
|
+
this.buildPositionStyles(props, styles);
|
|
49428
|
+
this.buildSizeStyles(props, styles);
|
|
49429
|
+
this.buildPaddingStyles(props, styles);
|
|
49430
|
+
this.buildMarginStyles(props, styles);
|
|
49431
|
+
this.buildGapStyles(props, styles);
|
|
49432
|
+
return styles.join("; ");
|
|
49433
|
+
}
|
|
49434
|
+
/**
|
|
49435
|
+
* Build position styles (absolute positioning)
|
|
49436
|
+
*/
|
|
49437
|
+
buildPositionStyles(props, styles) {
|
|
48615
49438
|
if (props.x !== void 0 || props.y !== void 0) {
|
|
48616
49439
|
styles.push("position: absolute");
|
|
48617
49440
|
if (props.x !== void 0) {
|
|
@@ -48623,6 +49446,11 @@ ${children}
|
|
|
48623
49446
|
if (yValue) styles.push(`top: ${yValue}`);
|
|
48624
49447
|
}
|
|
48625
49448
|
}
|
|
49449
|
+
}
|
|
49450
|
+
/**
|
|
49451
|
+
* Build size styles (width, height, min/max)
|
|
49452
|
+
*/
|
|
49453
|
+
buildSizeStyles(props, styles) {
|
|
48626
49454
|
const wValue = resolveSizeValueToCss(props.w);
|
|
48627
49455
|
if (wValue) {
|
|
48628
49456
|
styles.push(`width: ${wValue}`);
|
|
@@ -48648,6 +49476,11 @@ ${children}
|
|
|
48648
49476
|
if (maxHValue) {
|
|
48649
49477
|
styles.push(`max-height: ${maxHValue}`);
|
|
48650
49478
|
}
|
|
49479
|
+
}
|
|
49480
|
+
/**
|
|
49481
|
+
* Build padding styles (p, px, py, pt, pr, pb, pl)
|
|
49482
|
+
*/
|
|
49483
|
+
buildPaddingStyles(props, styles) {
|
|
48651
49484
|
const pValue = resolveSpacingValue(props.p);
|
|
48652
49485
|
if (pValue) {
|
|
48653
49486
|
styles.push(`padding: ${pValue}`);
|
|
@@ -48678,6 +49511,11 @@ ${children}
|
|
|
48678
49511
|
if (plValue) {
|
|
48679
49512
|
styles.push(`padding-left: ${plValue}`);
|
|
48680
49513
|
}
|
|
49514
|
+
}
|
|
49515
|
+
/**
|
|
49516
|
+
* Build margin styles (m, mx, my, mt, mr, mb, ml)
|
|
49517
|
+
*/
|
|
49518
|
+
buildMarginStyles(props, styles) {
|
|
48681
49519
|
const mValue = resolveSpacingValue(props.m);
|
|
48682
49520
|
if (mValue) {
|
|
48683
49521
|
styles.push(`margin: ${mValue}`);
|
|
@@ -48708,11 +49546,15 @@ ${children}
|
|
|
48708
49546
|
if (mlValue) {
|
|
48709
49547
|
styles.push(`margin-left: ${mlValue}`);
|
|
48710
49548
|
}
|
|
49549
|
+
}
|
|
49550
|
+
/**
|
|
49551
|
+
* Build gap styles
|
|
49552
|
+
*/
|
|
49553
|
+
buildGapStyles(props, styles) {
|
|
48711
49554
|
const gapValue = resolveSpacingValue(props.gap);
|
|
48712
49555
|
if (gapValue) {
|
|
48713
49556
|
styles.push(`gap: ${gapValue}`);
|
|
48714
49557
|
}
|
|
48715
|
-
return styles.join("; ");
|
|
48716
49558
|
}
|
|
48717
49559
|
/**
|
|
48718
49560
|
* Build inline styles for Col node (extends common styles with order)
|
|
@@ -48732,2632 +49574,136 @@ ${children}
|
|
|
48732
49574
|
// Container Node Renderers
|
|
48733
49575
|
// ===========================================
|
|
48734
49576
|
renderCard(node) {
|
|
48735
|
-
|
|
48736
|
-
const classes = this.buildClassString([
|
|
48737
|
-
`${this.prefix}-card`,
|
|
48738
|
-
!hasExplicitWidth ? `${this.prefix}-card-flex` : void 0,
|
|
48739
|
-
node.shadow ? `${this.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
48740
|
-
...this.getCommonClasses(node)
|
|
48741
|
-
]);
|
|
48742
|
-
const styles = this.buildCommonStyles(node);
|
|
48743
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48744
|
-
const title = node.title ? `<h3 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h3>
|
|
48745
|
-
` : "";
|
|
48746
|
-
const children = this.renderChildren(node.children);
|
|
48747
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48748
|
-
${title}${children}
|
|
48749
|
-
</div>`;
|
|
49577
|
+
return renderCard(node, this.getRenderContext());
|
|
48750
49578
|
}
|
|
48751
49579
|
renderModal(node) {
|
|
48752
|
-
|
|
48753
|
-
`${this.prefix}-modal`,
|
|
48754
|
-
...this.getCommonClasses(node)
|
|
48755
|
-
]);
|
|
48756
|
-
const styles = this.buildCommonStyles(node);
|
|
48757
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48758
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48759
|
-
` : "";
|
|
48760
|
-
const children = this.renderChildren(node.children);
|
|
48761
|
-
return `<div class="${this.prefix}-modal-backdrop">
|
|
48762
|
-
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
48763
|
-
${title}${children}
|
|
48764
|
-
</div>
|
|
48765
|
-
</div>`;
|
|
49580
|
+
return renderModal(node, this.getRenderContext());
|
|
48766
49581
|
}
|
|
48767
49582
|
renderDrawer(node) {
|
|
48768
|
-
|
|
48769
|
-
const classes = this.buildClassString([
|
|
48770
|
-
`${this.prefix}-drawer`,
|
|
48771
|
-
`${this.prefix}-drawer-${position}`,
|
|
48772
|
-
...this.getCommonClasses(node)
|
|
48773
|
-
]);
|
|
48774
|
-
const styles = this.buildCommonStyles(node);
|
|
48775
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48776
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48777
|
-
` : "";
|
|
48778
|
-
const children = this.renderChildren(node.children);
|
|
48779
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48780
|
-
${title}${children}
|
|
48781
|
-
</aside>`;
|
|
49583
|
+
return renderDrawer(node, this.getRenderContext());
|
|
48782
49584
|
}
|
|
48783
49585
|
renderAccordion(node) {
|
|
48784
|
-
|
|
48785
|
-
`${this.prefix}-accordion`,
|
|
48786
|
-
...this.getCommonClasses(node)
|
|
48787
|
-
]);
|
|
48788
|
-
const styles = this.buildCommonStyles(node);
|
|
48789
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48790
|
-
const title = node.title ? `<button class="${this.prefix}-accordion-header">${this.escapeHtml(node.title)}</button>
|
|
48791
|
-
` : "";
|
|
48792
|
-
const children = this.renderChildren(node.children);
|
|
48793
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48794
|
-
${title}<div class="${this.prefix}-accordion-content">
|
|
48795
|
-
${children}
|
|
48796
|
-
</div>
|
|
48797
|
-
</div>`;
|
|
49586
|
+
return renderAccordion(node, this.getRenderContext());
|
|
48798
49587
|
}
|
|
48799
49588
|
// ===========================================
|
|
48800
49589
|
// Text Node Renderers
|
|
48801
49590
|
// ===========================================
|
|
48802
49591
|
renderText(node) {
|
|
48803
|
-
|
|
48804
|
-
`${this.prefix}-text`,
|
|
48805
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48806
|
-
node.weight ? `${this.prefix}-text-${node.weight}` : void 0,
|
|
48807
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48808
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
48809
|
-
...this.getCommonClasses(node)
|
|
48810
|
-
]);
|
|
48811
|
-
const styles = this.buildCommonStyles(node);
|
|
48812
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48813
|
-
return `<p class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</p>`;
|
|
49592
|
+
return renderText(node, this.getRenderContext());
|
|
48814
49593
|
}
|
|
48815
49594
|
renderTitle(node) {
|
|
48816
|
-
|
|
48817
|
-
const tag = `h${level}`;
|
|
48818
|
-
const classes = this.buildClassString([
|
|
48819
|
-
`${this.prefix}-title`,
|
|
48820
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48821
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48822
|
-
...this.getCommonClasses(node)
|
|
48823
|
-
]);
|
|
48824
|
-
const styles = this.buildCommonStyles(node);
|
|
48825
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48826
|
-
return `<${tag} class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</${tag}>`;
|
|
49595
|
+
return renderTitle(node, this.getRenderContext());
|
|
48827
49596
|
}
|
|
48828
49597
|
renderLink(node) {
|
|
48829
|
-
|
|
48830
|
-
`${this.prefix}-link`,
|
|
48831
|
-
...this.getCommonClasses(node)
|
|
48832
|
-
]);
|
|
48833
|
-
const styles = this.buildCommonStyles(node);
|
|
48834
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48835
|
-
const attrs = {
|
|
48836
|
-
class: classes,
|
|
48837
|
-
href: node.href || "#"
|
|
48838
|
-
};
|
|
48839
|
-
if (node.external) {
|
|
48840
|
-
attrs.target = "_blank";
|
|
48841
|
-
attrs.rel = "noopener noreferrer";
|
|
48842
|
-
}
|
|
48843
|
-
return `<a${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.content)}</a>`;
|
|
49598
|
+
return renderLink(node, this.getRenderContext());
|
|
48844
49599
|
}
|
|
48845
49600
|
// ===========================================
|
|
48846
49601
|
// Input Node Renderers
|
|
48847
49602
|
// ===========================================
|
|
48848
49603
|
renderInput(node) {
|
|
48849
|
-
|
|
48850
|
-
`${this.prefix}-input`,
|
|
48851
|
-
node.icon ? `${this.prefix}-input-with-icon` : void 0,
|
|
48852
|
-
...this.getCommonClasses(node)
|
|
48853
|
-
]);
|
|
48854
|
-
const styles = this.buildCommonStyles(node);
|
|
48855
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48856
|
-
const attrs = {
|
|
48857
|
-
class: inputClasses,
|
|
48858
|
-
type: node.inputType || "text",
|
|
48859
|
-
placeholder: node.placeholder,
|
|
48860
|
-
value: node.value,
|
|
48861
|
-
disabled: node.disabled,
|
|
48862
|
-
required: node.required,
|
|
48863
|
-
readonly: node.readonly
|
|
48864
|
-
};
|
|
48865
|
-
const inputElement = `<input${this.buildAttrsString(attrs)} />`;
|
|
48866
|
-
if (node.icon) {
|
|
48867
|
-
const iconData = getIconData(node.icon);
|
|
48868
|
-
let iconHtml;
|
|
48869
|
-
if (iconData) {
|
|
48870
|
-
iconHtml = renderIconSvg(iconData, 16, 2, `${this.prefix}-input-icon`);
|
|
48871
|
-
} else {
|
|
48872
|
-
iconHtml = `<span class="${this.prefix}-input-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48873
|
-
}
|
|
48874
|
-
const wrapperClasses = this.buildClassString([`${this.prefix}-input-wrapper`]);
|
|
48875
|
-
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48876
|
-
if (node.label) {
|
|
48877
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48878
|
-
${wrapper}`;
|
|
48879
|
-
}
|
|
48880
|
-
return wrapper;
|
|
48881
|
-
}
|
|
48882
|
-
const input = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48883
|
-
if (node.label) {
|
|
48884
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48885
|
-
${input}`;
|
|
48886
|
-
}
|
|
48887
|
-
return input;
|
|
49604
|
+
return renderInput(node, this.getRenderContext());
|
|
48888
49605
|
}
|
|
48889
49606
|
renderTextarea(node) {
|
|
48890
|
-
|
|
48891
|
-
`${this.prefix}-input`,
|
|
48892
|
-
...this.getCommonClasses(node)
|
|
48893
|
-
]);
|
|
48894
|
-
const styles = this.buildCommonStyles(node);
|
|
48895
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48896
|
-
const attrs = {
|
|
48897
|
-
class: classes,
|
|
48898
|
-
placeholder: node.placeholder,
|
|
48899
|
-
disabled: node.disabled,
|
|
48900
|
-
required: node.required,
|
|
48901
|
-
rows: node.rows?.toString()
|
|
48902
|
-
};
|
|
48903
|
-
const textarea = `<textarea${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.value || "")}</textarea>`;
|
|
48904
|
-
if (node.label) {
|
|
48905
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48906
|
-
${textarea}`;
|
|
48907
|
-
}
|
|
48908
|
-
return textarea;
|
|
49607
|
+
return renderTextarea(node, this.getRenderContext());
|
|
48909
49608
|
}
|
|
48910
49609
|
renderSelect(node) {
|
|
48911
|
-
|
|
48912
|
-
`${this.prefix}-input`,
|
|
48913
|
-
...this.getCommonClasses(node)
|
|
48914
|
-
]);
|
|
48915
|
-
const styles = this.buildCommonStyles(node);
|
|
48916
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48917
|
-
const attrs = {
|
|
48918
|
-
class: classes,
|
|
48919
|
-
disabled: node.disabled,
|
|
48920
|
-
required: node.required
|
|
48921
|
-
};
|
|
48922
|
-
const options = node.options.map((opt) => {
|
|
48923
|
-
if (typeof opt === "string") {
|
|
48924
|
-
const selected2 = opt === node.value ? " selected" : "";
|
|
48925
|
-
return `<option value="${this.escapeHtml(opt)}"${selected2}>${this.escapeHtml(opt)}</option>`;
|
|
48926
|
-
}
|
|
48927
|
-
const selected = opt.value === node.value ? " selected" : "";
|
|
48928
|
-
return `<option value="${this.escapeHtml(opt.value)}"${selected}>${this.escapeHtml(opt.label)}</option>`;
|
|
48929
|
-
}).join("\n");
|
|
48930
|
-
const placeholder = node.placeholder ? `<option value="" disabled selected>${this.escapeHtml(node.placeholder)}</option>
|
|
48931
|
-
` : "";
|
|
48932
|
-
const select = `<select${this.buildAttrsString(attrs)}${styleAttr}>
|
|
48933
|
-
${placeholder}${options}
|
|
48934
|
-
</select>`;
|
|
48935
|
-
if (node.label) {
|
|
48936
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48937
|
-
${select}`;
|
|
48938
|
-
}
|
|
48939
|
-
return select;
|
|
49610
|
+
return renderSelect(node, this.getRenderContext());
|
|
48940
49611
|
}
|
|
48941
49612
|
renderCheckbox(node) {
|
|
48942
|
-
|
|
48943
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48944
|
-
const attrs = {
|
|
48945
|
-
type: "checkbox",
|
|
48946
|
-
checked: node.checked,
|
|
48947
|
-
disabled: node.disabled
|
|
48948
|
-
};
|
|
48949
|
-
const checkbox = `<input${this.buildAttrsString(attrs)} />`;
|
|
48950
|
-
if (node.label) {
|
|
48951
|
-
return `<label class="${this.prefix}-checkbox"${styleAttr}>${checkbox}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48952
|
-
}
|
|
48953
|
-
return checkbox;
|
|
49613
|
+
return renderCheckbox(node, this.getRenderContext());
|
|
48954
49614
|
}
|
|
48955
49615
|
renderRadio(node) {
|
|
48956
|
-
|
|
48957
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48958
|
-
const attrs = {
|
|
48959
|
-
type: "radio",
|
|
48960
|
-
name: node.name,
|
|
48961
|
-
checked: node.checked,
|
|
48962
|
-
disabled: node.disabled
|
|
48963
|
-
};
|
|
48964
|
-
const radio = `<input${this.buildAttrsString(attrs)} />`;
|
|
48965
|
-
if (node.label) {
|
|
48966
|
-
return `<label class="${this.prefix}-radio"${styleAttr}>${radio}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48967
|
-
}
|
|
48968
|
-
return radio;
|
|
49616
|
+
return renderRadio(node, this.getRenderContext());
|
|
48969
49617
|
}
|
|
48970
49618
|
renderSwitch(node) {
|
|
48971
|
-
|
|
48972
|
-
`${this.prefix}-switch`,
|
|
48973
|
-
...this.getCommonClasses(node)
|
|
48974
|
-
]);
|
|
48975
|
-
const styles = this.buildCommonStyles(node);
|
|
48976
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48977
|
-
const attrs = {
|
|
48978
|
-
type: "checkbox",
|
|
48979
|
-
role: "switch",
|
|
48980
|
-
checked: node.checked,
|
|
48981
|
-
disabled: node.disabled
|
|
48982
|
-
};
|
|
48983
|
-
const switchEl = `<input${this.buildAttrsString(attrs)} />`;
|
|
48984
|
-
if (node.label) {
|
|
48985
|
-
return `<label class="${classes}"${styleAttr}>${switchEl} ${this.escapeHtml(node.label)}</label>`;
|
|
48986
|
-
}
|
|
48987
|
-
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
49619
|
+
return renderSwitch(node, this.getRenderContext());
|
|
48988
49620
|
}
|
|
48989
49621
|
renderSlider(node) {
|
|
48990
|
-
|
|
48991
|
-
`${this.prefix}-slider`,
|
|
48992
|
-
...this.getCommonClasses(node)
|
|
48993
|
-
]);
|
|
48994
|
-
const styles = this.buildCommonStyles(node);
|
|
48995
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48996
|
-
const attrs = {
|
|
48997
|
-
class: classes,
|
|
48998
|
-
type: "range",
|
|
48999
|
-
min: node.min?.toString(),
|
|
49000
|
-
max: node.max?.toString(),
|
|
49001
|
-
step: node.step?.toString(),
|
|
49002
|
-
value: node.value?.toString(),
|
|
49003
|
-
disabled: node.disabled
|
|
49004
|
-
};
|
|
49005
|
-
const slider = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
49006
|
-
if (node.label) {
|
|
49007
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
49008
|
-
${slider}`;
|
|
49009
|
-
}
|
|
49010
|
-
return slider;
|
|
49622
|
+
return renderSlider(node, this.getRenderContext());
|
|
49011
49623
|
}
|
|
49012
49624
|
// ===========================================
|
|
49013
49625
|
// Button Renderer
|
|
49014
49626
|
// ===========================================
|
|
49015
49627
|
renderButton(node) {
|
|
49016
|
-
|
|
49017
|
-
const classes = this.buildClassString([
|
|
49018
|
-
`${this.prefix}-button`,
|
|
49019
|
-
node.primary ? `${this.prefix}-button-primary` : void 0,
|
|
49020
|
-
node.secondary ? `${this.prefix}-button-secondary` : void 0,
|
|
49021
|
-
node.outline ? `${this.prefix}-button-outline` : void 0,
|
|
49022
|
-
node.ghost ? `${this.prefix}-button-ghost` : void 0,
|
|
49023
|
-
node.danger ? `${this.prefix}-button-danger` : void 0,
|
|
49024
|
-
node.size ? `${this.prefix}-button-${node.size}` : void 0,
|
|
49025
|
-
node.disabled ? `${this.prefix}-button-disabled` : void 0,
|
|
49026
|
-
node.loading ? `${this.prefix}-button-loading` : void 0,
|
|
49027
|
-
isIconOnly ? `${this.prefix}-button-icon-only` : void 0,
|
|
49028
|
-
...this.getCommonClasses(node)
|
|
49029
|
-
]);
|
|
49030
|
-
const styles = this.buildCommonStyles(node);
|
|
49031
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49032
|
-
const attrs = {
|
|
49033
|
-
class: classes,
|
|
49034
|
-
disabled: node.disabled
|
|
49035
|
-
};
|
|
49036
|
-
let icon = "";
|
|
49037
|
-
if (node.icon) {
|
|
49038
|
-
const iconData = getIconData(node.icon);
|
|
49039
|
-
if (iconData) {
|
|
49040
|
-
icon = renderIconSvg(iconData, 16, 2, `${this.prefix}-icon`);
|
|
49041
|
-
} else {
|
|
49042
|
-
icon = `<span class="${this.prefix}-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
49043
|
-
}
|
|
49044
|
-
}
|
|
49045
|
-
const loading = node.loading ? `<span class="${this.prefix}-spinner ${this.prefix}-spinner-sm"></span>` : "";
|
|
49046
|
-
const content = this.escapeHtml(node.content);
|
|
49047
|
-
return `<button${this.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
49628
|
+
return renderButton(node, this.getRenderContext());
|
|
49048
49629
|
}
|
|
49049
49630
|
// ===========================================
|
|
49050
49631
|
// Display Node Renderers
|
|
49051
49632
|
// ===========================================
|
|
49052
49633
|
renderImage(node) {
|
|
49053
|
-
|
|
49054
|
-
`${this.prefix}-image`,
|
|
49055
|
-
...this.getCommonClasses(node)
|
|
49056
|
-
]);
|
|
49057
|
-
const styles = this.buildCommonStyles(node);
|
|
49058
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49059
|
-
if (node.src) {
|
|
49060
|
-
const attrs = {
|
|
49061
|
-
class: classes,
|
|
49062
|
-
src: node.src,
|
|
49063
|
-
alt: node.alt || "Image"
|
|
49064
|
-
};
|
|
49065
|
-
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
49066
|
-
return `<img${this.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
49067
|
-
}
|
|
49068
|
-
const label = node.alt || "Image";
|
|
49069
|
-
const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
49070
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(label)}">${icon}<span>${this.escapeHtml(label)}</span></div>`;
|
|
49634
|
+
return renderImage(node, this.getRenderContext());
|
|
49071
49635
|
}
|
|
49072
49636
|
renderPlaceholder(node) {
|
|
49073
|
-
|
|
49074
|
-
`${this.prefix}-placeholder`,
|
|
49075
|
-
node.children && node.children.length > 0 ? `${this.prefix}-placeholder-with-children` : void 0,
|
|
49076
|
-
...this.getCommonClasses(node)
|
|
49077
|
-
]);
|
|
49078
|
-
const styles = this.buildCommonStyles(node);
|
|
49079
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49080
|
-
const label = node.label ? this.escapeHtml(node.label) : "Placeholder";
|
|
49081
|
-
if (node.children && node.children.length > 0) {
|
|
49082
|
-
const childrenHtml = this.renderChildren(node.children);
|
|
49083
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49084
|
-
<span class="${this.prefix}-placeholder-label">${label}</span>
|
|
49085
|
-
<div class="${this.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
49086
|
-
</div>`;
|
|
49087
|
-
}
|
|
49088
|
-
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
49637
|
+
return renderPlaceholder(node, this.getRenderContext());
|
|
49089
49638
|
}
|
|
49090
49639
|
renderAvatar(node) {
|
|
49091
|
-
|
|
49092
|
-
const classes = this.buildClassString([
|
|
49093
|
-
`${this.prefix}-avatar`,
|
|
49094
|
-
sizeResolved.className,
|
|
49095
|
-
...this.getCommonClasses(node)
|
|
49096
|
-
]);
|
|
49097
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49098
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49099
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49100
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49101
|
-
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
49102
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
49640
|
+
return renderAvatar(node, this.getRenderContext());
|
|
49103
49641
|
}
|
|
49104
49642
|
renderBadge(node) {
|
|
49105
|
-
|
|
49106
|
-
const iconData = getIconData(node.icon);
|
|
49107
|
-
const classes2 = this.buildClassString([
|
|
49108
|
-
`${this.prefix}-badge-icon`,
|
|
49109
|
-
node.size ? `${this.prefix}-badge-icon-${node.size}` : void 0,
|
|
49110
|
-
node.variant ? `${this.prefix}-badge-icon-${node.variant}` : void 0,
|
|
49111
|
-
...this.getCommonClasses(node)
|
|
49112
|
-
]);
|
|
49113
|
-
const styles2 = this.buildCommonStyles(node);
|
|
49114
|
-
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
49115
|
-
if (iconData) {
|
|
49116
|
-
const svg = renderIconSvg(iconData, 24, 2, `${this.prefix}-icon`);
|
|
49117
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="${this.escapeHtml(node.icon)}">${svg}</span>`;
|
|
49118
|
-
}
|
|
49119
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
49120
|
-
}
|
|
49121
|
-
const isDot = !node.content || node.content.trim() === "";
|
|
49122
|
-
const classes = this.buildClassString([
|
|
49123
|
-
`${this.prefix}-badge`,
|
|
49124
|
-
isDot ? `${this.prefix}-badge-dot` : void 0,
|
|
49125
|
-
node.variant ? `${this.prefix}-badge-${node.variant}` : void 0,
|
|
49126
|
-
node.pill ? `${this.prefix}-badge-pill` : void 0,
|
|
49127
|
-
...this.getCommonClasses(node)
|
|
49128
|
-
]);
|
|
49129
|
-
const styles = this.buildCommonStyles(node);
|
|
49130
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49131
|
-
return `<span class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</span>`;
|
|
49643
|
+
return renderBadge(node, this.getRenderContext());
|
|
49132
49644
|
}
|
|
49133
49645
|
renderIcon(node) {
|
|
49134
|
-
|
|
49135
|
-
const sizeResolved = resolveSizeValue(node.size, "icon", this.prefix);
|
|
49136
|
-
const wrapperClasses = this.buildClassString([
|
|
49137
|
-
`${this.prefix}-icon-wrapper`,
|
|
49138
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
49139
|
-
...this.getCommonClasses(node)
|
|
49140
|
-
]);
|
|
49141
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49142
|
-
if (iconData) {
|
|
49143
|
-
const iconClasses = buildClassString([
|
|
49144
|
-
`${this.prefix}-icon`,
|
|
49145
|
-
sizeResolved.className
|
|
49146
|
-
]);
|
|
49147
|
-
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
49148
|
-
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
49149
|
-
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49150
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
49151
|
-
}
|
|
49152
|
-
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
49153
|
-
const sizeNum = parseInt(size, 10);
|
|
49154
|
-
const placeholderSvg = `<svg class="${this.prefix}-icon ${sizeResolved.className || ""}" width="${sizeNum}" height="${sizeNum}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
49155
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
49156
|
-
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
49157
|
-
</svg>`;
|
|
49158
|
-
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49159
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${this.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
49646
|
+
return renderIcon(node, this.getRenderContext());
|
|
49160
49647
|
}
|
|
49161
49648
|
// ===========================================
|
|
49162
49649
|
// Data Node Renderers
|
|
49163
49650
|
// ===========================================
|
|
49164
49651
|
renderTable(node) {
|
|
49165
|
-
|
|
49166
|
-
`${this.prefix}-table`,
|
|
49167
|
-
node.striped ? `${this.prefix}-table-striped` : void 0,
|
|
49168
|
-
node.bordered ? `${this.prefix}-table-bordered` : void 0,
|
|
49169
|
-
node.hover ? `${this.prefix}-table-hover` : void 0,
|
|
49170
|
-
...this.getCommonClasses(node)
|
|
49171
|
-
]);
|
|
49172
|
-
const styles = this.buildCommonStyles(node);
|
|
49173
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49174
|
-
const thead = `<thead><tr>${node.columns.map((col) => `<th>${this.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49175
|
-
const tbody = `<tbody>${node.rows.map(
|
|
49176
|
-
(row) => `<tr>${row.map((cell) => {
|
|
49177
|
-
if (typeof cell === "string") {
|
|
49178
|
-
return `<td>${this.renderTableCellContent(cell)}</td>`;
|
|
49179
|
-
}
|
|
49180
|
-
return `<td>${this.renderNode(cell)}</td>`;
|
|
49181
|
-
}).join("")}</tr>`
|
|
49182
|
-
).join("")}</tbody>`;
|
|
49183
|
-
return `<table class="${classes}"${styleAttr}>
|
|
49184
|
-
${thead}
|
|
49185
|
-
${tbody}
|
|
49186
|
-
</table>`;
|
|
49652
|
+
return renderTable(node, this.getRenderContext());
|
|
49187
49653
|
}
|
|
49188
49654
|
renderList(node) {
|
|
49189
|
-
|
|
49190
|
-
const classes = this.buildClassString([
|
|
49191
|
-
`${this.prefix}-list`,
|
|
49192
|
-
node.ordered ? `${this.prefix}-list-ordered` : void 0,
|
|
49193
|
-
node.none ? `${this.prefix}-list-none` : void 0,
|
|
49194
|
-
...this.getCommonClasses(node)
|
|
49195
|
-
]);
|
|
49196
|
-
const styles = this.buildCommonStyles(node);
|
|
49197
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49198
|
-
const items = node.items.map((item) => {
|
|
49199
|
-
if (typeof item === "string") {
|
|
49200
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item)}</li>`;
|
|
49201
|
-
}
|
|
49202
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item.content)}</li>`;
|
|
49203
|
-
}).join("\n");
|
|
49204
|
-
return `<${tag} class="${classes}"${styleAttr}>
|
|
49205
|
-
${items}
|
|
49206
|
-
</${tag}>`;
|
|
49655
|
+
return renderList(node, this.getRenderContext());
|
|
49207
49656
|
}
|
|
49208
49657
|
// ===========================================
|
|
49209
49658
|
// Feedback Node Renderers
|
|
49210
49659
|
// ===========================================
|
|
49211
49660
|
renderAlert(node) {
|
|
49212
|
-
|
|
49213
|
-
`${this.prefix}-alert`,
|
|
49214
|
-
node.variant ? `${this.prefix}-alert-${node.variant}` : void 0,
|
|
49215
|
-
...this.getCommonClasses(node)
|
|
49216
|
-
]);
|
|
49217
|
-
const styles = this.buildCommonStyles(node);
|
|
49218
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49219
|
-
const dismissBtn = node.dismissible ? ` <button class="${this.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
49220
|
-
return `<div class="${classes}"${styleAttr} role="alert">${this.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
49661
|
+
return renderAlert(node, this.getRenderContext());
|
|
49221
49662
|
}
|
|
49222
49663
|
renderToast(node) {
|
|
49223
|
-
|
|
49224
|
-
`${this.prefix}-toast`,
|
|
49225
|
-
node.position ? `${this.prefix}-toast-${node.position}` : void 0,
|
|
49226
|
-
node.variant ? `${this.prefix}-toast-${node.variant}` : void 0,
|
|
49227
|
-
...this.getCommonClasses(node)
|
|
49228
|
-
]);
|
|
49229
|
-
const styles = this.buildCommonStyles(node);
|
|
49230
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49231
|
-
return `<div class="${classes}"${styleAttr} role="status">${this.escapeHtml(node.content)}</div>`;
|
|
49664
|
+
return renderToast(node, this.getRenderContext());
|
|
49232
49665
|
}
|
|
49233
49666
|
renderProgress(node) {
|
|
49234
|
-
|
|
49235
|
-
`${this.prefix}-progress`,
|
|
49236
|
-
...this.getCommonClasses(node)
|
|
49237
|
-
]);
|
|
49238
|
-
const styles = this.buildCommonStyles(node);
|
|
49239
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49240
|
-
const value = node.value || 0;
|
|
49241
|
-
const max = node.max || 100;
|
|
49242
|
-
const percentage = Math.round(value / max * 100);
|
|
49243
|
-
const label = node.label ? `<span class="${this.prefix}-progress-label">${this.escapeHtml(node.label)}</span>` : "";
|
|
49244
|
-
if (node.indeterminate) {
|
|
49245
|
-
return `<div class="${classes} ${this.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
49246
|
-
}
|
|
49247
|
-
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
49248
|
-
${label}
|
|
49249
|
-
<div class="${this.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
49250
|
-
</div>`;
|
|
49667
|
+
return renderProgress(node, this.getRenderContext());
|
|
49251
49668
|
}
|
|
49252
49669
|
renderSpinner(node) {
|
|
49253
|
-
|
|
49254
|
-
const classes = this.buildClassString([
|
|
49255
|
-
`${this.prefix}-spinner`,
|
|
49256
|
-
sizeResolved.className,
|
|
49257
|
-
...this.getCommonClasses(node)
|
|
49258
|
-
]);
|
|
49259
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49260
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49261
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49262
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49263
|
-
const label = node.label || "Loading...";
|
|
49264
|
-
return `<span class="${classes}"${styleAttr} role="status" aria-label="${this.escapeHtml(label)}"></span>`;
|
|
49670
|
+
return renderSpinner(node, this.getRenderContext());
|
|
49265
49671
|
}
|
|
49266
49672
|
// ===========================================
|
|
49267
49673
|
// Overlay Node Renderers
|
|
49268
49674
|
// ===========================================
|
|
49269
49675
|
renderTooltip(node) {
|
|
49270
|
-
|
|
49271
|
-
`${this.prefix}-tooltip-wrapper`,
|
|
49272
|
-
...this.getCommonClasses(node)
|
|
49273
|
-
]);
|
|
49274
|
-
const styles = this.buildCommonStyles(node);
|
|
49275
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49276
|
-
const position = node.position || "top";
|
|
49277
|
-
const children = this.renderChildren(node.children);
|
|
49278
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49279
|
-
${children}
|
|
49280
|
-
<div class="${this.prefix}-tooltip ${this.prefix}-tooltip-${position}" role="tooltip">${this.escapeHtml(node.content)}</div>
|
|
49281
|
-
</div>`;
|
|
49676
|
+
return renderTooltip(node, this.getRenderContext());
|
|
49282
49677
|
}
|
|
49283
49678
|
renderPopover(node) {
|
|
49284
|
-
|
|
49285
|
-
`${this.prefix}-popover`,
|
|
49286
|
-
...this.getCommonClasses(node)
|
|
49287
|
-
]);
|
|
49288
|
-
const styles = this.buildCommonStyles(node);
|
|
49289
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49290
|
-
const title = node.title ? `<div class="${this.prefix}-popover-header">${this.escapeHtml(node.title)}</div>
|
|
49291
|
-
` : "";
|
|
49292
|
-
const children = this.renderChildren(node.children);
|
|
49293
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49294
|
-
${title}<div class="${this.prefix}-popover-body">
|
|
49295
|
-
${children}
|
|
49296
|
-
</div>
|
|
49297
|
-
</div>`;
|
|
49679
|
+
return renderPopover(node, this.getRenderContext());
|
|
49298
49680
|
}
|
|
49299
49681
|
renderDropdown(node) {
|
|
49300
|
-
|
|
49301
|
-
`${this.prefix}-dropdown`,
|
|
49302
|
-
...this.getCommonClasses(node)
|
|
49303
|
-
]);
|
|
49304
|
-
const styles = this.buildCommonStyles(node);
|
|
49305
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49306
|
-
const items = node.items.map((item) => {
|
|
49307
|
-
if ("type" in item && item.type === "divider") {
|
|
49308
|
-
return `<hr class="${this.prefix}-divider" />`;
|
|
49309
|
-
}
|
|
49310
|
-
const dropdownItem = item;
|
|
49311
|
-
const itemClasses = this.buildClassString([
|
|
49312
|
-
`${this.prefix}-dropdown-item`,
|
|
49313
|
-
dropdownItem.danger ? `${this.prefix}-dropdown-item-danger` : void 0,
|
|
49314
|
-
dropdownItem.disabled ? `${this.prefix}-dropdown-item-disabled` : void 0
|
|
49315
|
-
]);
|
|
49316
|
-
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${this.escapeHtml(dropdownItem.label)}</button>`;
|
|
49317
|
-
}).join("\n");
|
|
49318
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49319
|
-
${items}
|
|
49320
|
-
</div>`;
|
|
49682
|
+
return renderDropdown(node, this.getRenderContext());
|
|
49321
49683
|
}
|
|
49322
49684
|
// ===========================================
|
|
49323
49685
|
// Navigation Node Renderers
|
|
49324
49686
|
// ===========================================
|
|
49325
49687
|
renderNav(node) {
|
|
49326
|
-
|
|
49327
|
-
`${this.prefix}-nav`,
|
|
49328
|
-
node.vertical ? `${this.prefix}-nav-vertical` : void 0,
|
|
49329
|
-
...this.getCommonClasses(node)
|
|
49330
|
-
]);
|
|
49331
|
-
const styles = this.buildCommonStyles(node);
|
|
49332
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49333
|
-
if (node.children && node.children.length > 0) {
|
|
49334
|
-
const content = this.renderNavChildren(node.children);
|
|
49335
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49336
|
-
${content}
|
|
49337
|
-
</nav>`;
|
|
49338
|
-
}
|
|
49339
|
-
const items = node.items.map((item) => {
|
|
49340
|
-
if (typeof item === "string") {
|
|
49341
|
-
return `<a class="${this.prefix}-nav-link" href="#">${this.escapeHtml(item)}</a>`;
|
|
49342
|
-
}
|
|
49343
|
-
const linkClasses = this.buildClassString([
|
|
49344
|
-
`${this.prefix}-nav-link`,
|
|
49345
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49346
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49347
|
-
]);
|
|
49348
|
-
const iconHtml = item.icon ? this.renderIconHtml(item.icon) + " " : "";
|
|
49349
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${this.escapeHtml(item.label)}</a>`;
|
|
49350
|
-
}).join("\n");
|
|
49351
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49352
|
-
${items}
|
|
49353
|
-
</nav>`;
|
|
49354
|
-
}
|
|
49355
|
-
renderNavChildren(children) {
|
|
49356
|
-
return children.map((child) => {
|
|
49357
|
-
if (child.type === "divider") {
|
|
49358
|
-
return `<hr class="${this.prefix}-nav-divider" />`;
|
|
49359
|
-
}
|
|
49360
|
-
if (child.type === "group") {
|
|
49361
|
-
const groupItems = child.items.map((item) => {
|
|
49362
|
-
if (item.type === "divider") {
|
|
49363
|
-
return `<hr class="${this.prefix}-nav-divider" />`;
|
|
49364
|
-
}
|
|
49365
|
-
return this.renderNavItem(item);
|
|
49366
|
-
}).join("\n");
|
|
49367
|
-
return `<div class="${this.prefix}-nav-group">
|
|
49368
|
-
<div class="${this.prefix}-nav-group-label">${this.escapeHtml(child.label)}</div>
|
|
49369
|
-
${groupItems}
|
|
49370
|
-
</div>`;
|
|
49371
|
-
}
|
|
49372
|
-
if (child.type === "item") {
|
|
49373
|
-
return this.renderNavItem(child);
|
|
49374
|
-
}
|
|
49375
|
-
return "";
|
|
49376
|
-
}).join("\n");
|
|
49377
|
-
}
|
|
49378
|
-
renderNavItem(item) {
|
|
49379
|
-
const linkClasses = this.buildClassString([
|
|
49380
|
-
`${this.prefix}-nav-link`,
|
|
49381
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49382
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49383
|
-
]);
|
|
49384
|
-
const iconHtml = item.icon ? this.renderIconHtml(item.icon) + " " : "";
|
|
49385
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${this.escapeHtml(item.label)}</a>`;
|
|
49386
|
-
}
|
|
49387
|
-
renderIconHtml(iconName) {
|
|
49388
|
-
return `<span class="${this.prefix}-icon" data-icon="${iconName}"></span>`;
|
|
49688
|
+
return renderNav(node, this.getRenderContext());
|
|
49389
49689
|
}
|
|
49390
49690
|
renderTabs(node) {
|
|
49391
|
-
|
|
49392
|
-
`${this.prefix}-tabs`,
|
|
49393
|
-
...this.getCommonClasses(node)
|
|
49394
|
-
]);
|
|
49395
|
-
const styles = this.buildCommonStyles(node);
|
|
49396
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49397
|
-
const tabList = node.items.map((label, idx) => {
|
|
49398
|
-
const isActive = idx === (node.active || 0);
|
|
49399
|
-
const tabClasses = `${this.prefix}-tab${isActive ? ` ${this.prefix}-tab-active` : ""}`;
|
|
49400
|
-
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${this.escapeHtml(label)}</button>`;
|
|
49401
|
-
}).join("\n");
|
|
49402
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49403
|
-
<div class="${this.prefix}-tab-list" role="tablist">
|
|
49404
|
-
${tabList}
|
|
49405
|
-
</div>
|
|
49406
|
-
</div>`;
|
|
49691
|
+
return renderTabs(node, this.getRenderContext());
|
|
49407
49692
|
}
|
|
49408
49693
|
renderBreadcrumb(node) {
|
|
49409
|
-
|
|
49410
|
-
`${this.prefix}-breadcrumb`,
|
|
49411
|
-
...this.getCommonClasses(node)
|
|
49412
|
-
]);
|
|
49413
|
-
const styles = this.buildCommonStyles(node);
|
|
49414
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49415
|
-
const items = node.items.map((item, idx) => {
|
|
49416
|
-
const isLast = idx === node.items.length - 1;
|
|
49417
|
-
if (typeof item === "string") {
|
|
49418
|
-
return isLast ? `<span class="${this.prefix}-breadcrumb-item" aria-current="page">${this.escapeHtml(item)}</span>` : `<a class="${this.prefix}-breadcrumb-item" href="#">${this.escapeHtml(item)}</a>`;
|
|
49419
|
-
}
|
|
49420
|
-
return isLast ? `<span class="${this.prefix}-breadcrumb-item" aria-current="page">${this.escapeHtml(item.label)}</span>` : `<a class="${this.prefix}-breadcrumb-item" href="${item.href || "#"}">${this.escapeHtml(item.label)}</a>`;
|
|
49421
|
-
}).join(" / ");
|
|
49422
|
-
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49694
|
+
return renderBreadcrumb(node, this.getRenderContext());
|
|
49423
49695
|
}
|
|
49424
49696
|
// ===========================================
|
|
49425
49697
|
// Divider Renderer
|
|
49426
49698
|
// ===========================================
|
|
49427
49699
|
renderDivider(node) {
|
|
49428
|
-
|
|
49429
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49430
|
-
return `<hr class="${this.prefix}-divider"${styleAttr} />`;
|
|
49431
|
-
}
|
|
49432
|
-
// ===========================================
|
|
49433
|
-
// Semantic Marker Rendering
|
|
49434
|
-
// ===========================================
|
|
49435
|
-
/**
|
|
49436
|
-
* Parse and render semantic markers in text content
|
|
49437
|
-
*
|
|
49438
|
-
* Semantic markers use the syntax [component:variant] to indicate
|
|
49439
|
-
* what a visual element represents. This helps LLMs understand
|
|
49440
|
-
* the meaning of placeholder content.
|
|
49441
|
-
*
|
|
49442
|
-
* Supported markers:
|
|
49443
|
-
* - [avatar] or [avatar:size] - User avatar (renders as circle placeholder)
|
|
49444
|
-
* - [badge:variant] TEXT - Status badge (TEXT is displayed inside the badge)
|
|
49445
|
-
* - [dot:variant] - Status dot (renders as small circle before text)
|
|
49446
|
-
* - [icon:name] - Icon placeholder
|
|
49447
|
-
*
|
|
49448
|
-
* Examples:
|
|
49449
|
-
* - "[avatar] John Doe" → renders avatar circle + "John Doe"
|
|
49450
|
-
* - "[badge:primary] PRO" → renders badge containing "PRO"
|
|
49451
|
-
* - "[dot:success] Active" → renders green dot + "Active"
|
|
49452
|
-
*/
|
|
49453
|
-
renderSemanticMarkers(text) {
|
|
49454
|
-
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49455
|
-
let result = "";
|
|
49456
|
-
let lastIndex = 0;
|
|
49457
|
-
let match;
|
|
49458
|
-
while ((match = markerPattern.exec(text)) !== null) {
|
|
49459
|
-
if (match.index > lastIndex) {
|
|
49460
|
-
result += this.escapeHtml(text.substring(lastIndex, match.index));
|
|
49461
|
-
}
|
|
49462
|
-
const [fullMatch, component, variant] = match;
|
|
49463
|
-
const comp = component.toLowerCase();
|
|
49464
|
-
const varnt = variant?.toLowerCase();
|
|
49465
|
-
if (comp === "badge") {
|
|
49466
|
-
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49467
|
-
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49468
|
-
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49469
|
-
result += this.renderSemanticMarkerWithContent(comp, varnt, badgeContent);
|
|
49470
|
-
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49471
|
-
markerPattern.lastIndex = lastIndex;
|
|
49472
|
-
} else {
|
|
49473
|
-
result += this.renderSemanticMarker(comp, varnt);
|
|
49474
|
-
lastIndex = match.index + fullMatch.length;
|
|
49475
|
-
}
|
|
49476
|
-
}
|
|
49477
|
-
if (lastIndex < text.length) {
|
|
49478
|
-
result += this.escapeHtml(text.substring(lastIndex));
|
|
49479
|
-
}
|
|
49480
|
-
if (lastIndex === 0) {
|
|
49481
|
-
return this.escapeHtml(text);
|
|
49482
|
-
}
|
|
49483
|
-
return result;
|
|
49484
|
-
}
|
|
49485
|
-
/**
|
|
49486
|
-
* Render a single semantic marker to HTML (without content)
|
|
49487
|
-
*/
|
|
49488
|
-
renderSemanticMarker(component, variant) {
|
|
49489
|
-
const prefix = this.prefix;
|
|
49490
|
-
switch (component) {
|
|
49491
|
-
case "avatar":
|
|
49492
|
-
const avatarSize = variant || "sm";
|
|
49493
|
-
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49494
|
-
case "dot":
|
|
49495
|
-
const dotVariant = variant || "default";
|
|
49496
|
-
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49497
|
-
case "icon":
|
|
49498
|
-
const iconName = variant || "default";
|
|
49499
|
-
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49500
|
-
default:
|
|
49501
|
-
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49502
|
-
}
|
|
49503
|
-
}
|
|
49504
|
-
/**
|
|
49505
|
-
* Render a semantic marker with text content (for badge)
|
|
49506
|
-
*/
|
|
49507
|
-
renderSemanticMarkerWithContent(component, variant, content) {
|
|
49508
|
-
const prefix = this.prefix;
|
|
49509
|
-
switch (component) {
|
|
49510
|
-
case "badge":
|
|
49511
|
-
const badgeVariant = variant || "default";
|
|
49512
|
-
const escapedContent = this.escapeHtml(content);
|
|
49513
|
-
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49514
|
-
default:
|
|
49515
|
-
return this.renderSemanticMarker(component, variant) + this.escapeHtml(content);
|
|
49516
|
-
}
|
|
49517
|
-
}
|
|
49518
|
-
/**
|
|
49519
|
-
* Process table cell content with semantic markers and newlines
|
|
49520
|
-
*
|
|
49521
|
-
* Special handling for avatar + text layout:
|
|
49522
|
-
* When content starts with [avatar], wraps in flex container
|
|
49523
|
-
* so avatar and text align horizontally, with text stacking vertically
|
|
49524
|
-
*/
|
|
49525
|
-
renderTableCellContent(content) {
|
|
49526
|
-
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49527
|
-
if (avatarMatch) {
|
|
49528
|
-
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49529
|
-
const avatarHtml = this.renderSemanticMarker("avatar", avatarVariant);
|
|
49530
|
-
const restContent = content.slice(avatarMatch[0].length);
|
|
49531
|
-
const restHtml = this.renderSemanticMarkers(restContent);
|
|
49532
|
-
const lines = restHtml.split("\n");
|
|
49533
|
-
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49534
|
-
return `<div class="${this.prefix}-cell-avatar-layout">${avatarHtml}<div class="${this.prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49535
|
-
}
|
|
49536
|
-
const withMarkers = this.renderSemanticMarkers(content);
|
|
49537
|
-
return withMarkers.replace(/\n/g, "<br>");
|
|
49700
|
+
return renderDivider(node, this.getRenderContext());
|
|
49538
49701
|
}
|
|
49539
49702
|
};
|
|
49540
49703
|
function createHtmlRenderer(options) {
|
|
49541
49704
|
return new HtmlRenderer(options);
|
|
49542
49705
|
}
|
|
49543
49706
|
|
|
49544
|
-
// src/renderer/svg/flex-layout.ts
|
|
49545
|
-
function computeFlexLayout(items, config) {
|
|
49546
|
-
const { mainSize, crossSize, justifyContent, alignItems, gap } = config;
|
|
49547
|
-
const computed = items.map((props, index) => {
|
|
49548
|
-
let flexBasis;
|
|
49549
|
-
if (props.basis === "auto" || props.basis === "content") {
|
|
49550
|
-
flexBasis = props.contentSize;
|
|
49551
|
-
} else {
|
|
49552
|
-
flexBasis = props.basis;
|
|
49553
|
-
}
|
|
49554
|
-
flexBasis = clamp(flexBasis, props.minSize, props.maxSize);
|
|
49555
|
-
return {
|
|
49556
|
-
index,
|
|
49557
|
-
props,
|
|
49558
|
-
flexBasis,
|
|
49559
|
-
mainSize: flexBasis,
|
|
49560
|
-
crossSize: 0,
|
|
49561
|
-
mainPosition: 0,
|
|
49562
|
-
crossPosition: 0,
|
|
49563
|
-
frozen: false,
|
|
49564
|
-
scaledShrinkFactor: props.shrink * flexBasis
|
|
49565
|
-
};
|
|
49566
|
-
});
|
|
49567
|
-
const totalGap = Math.max(0, (items.length - 1) * gap);
|
|
49568
|
-
const totalFlexBasis = computed.reduce((sum, item) => sum + item.flexBasis, 0);
|
|
49569
|
-
let freeSpace = mainSize - totalFlexBasis - totalGap;
|
|
49570
|
-
if (freeSpace !== 0) {
|
|
49571
|
-
resolveFlexibleLengths(computed, freeSpace);
|
|
49572
|
-
}
|
|
49573
|
-
distributeMainAxis(computed, mainSize, totalGap, gap, justifyContent);
|
|
49574
|
-
const crossSizeMax = crossSize ?? Math.max(...computed.map((item) => item.props.contentSize), 0);
|
|
49575
|
-
alignCrossAxis(computed, crossSizeMax, alignItems);
|
|
49576
|
-
const mainSizeUsed = computed.reduce((sum, item) => sum + item.mainSize, 0) + totalGap;
|
|
49577
|
-
return {
|
|
49578
|
-
items: computed,
|
|
49579
|
-
mainSizeUsed,
|
|
49580
|
-
crossSizeMax
|
|
49581
|
-
};
|
|
49582
|
-
}
|
|
49583
|
-
function resolveFlexibleLengths(items, initialFreeSpace) {
|
|
49584
|
-
items.forEach((item) => {
|
|
49585
|
-
item.frozen = false;
|
|
49586
|
-
item.mainSize = item.flexBasis;
|
|
49587
|
-
});
|
|
49588
|
-
let freeSpace = initialFreeSpace;
|
|
49589
|
-
const isGrowing = freeSpace > 0;
|
|
49590
|
-
let iteration = 0;
|
|
49591
|
-
const maxIterations = items.length + 1;
|
|
49592
|
-
while (iteration < maxIterations) {
|
|
49593
|
-
iteration++;
|
|
49594
|
-
const unfrozen = items.filter((item) => !item.frozen);
|
|
49595
|
-
if (unfrozen.length === 0) break;
|
|
49596
|
-
let flexFactorSum;
|
|
49597
|
-
if (isGrowing) {
|
|
49598
|
-
flexFactorSum = unfrozen.reduce((sum, item) => sum + item.props.grow, 0);
|
|
49599
|
-
} else {
|
|
49600
|
-
flexFactorSum = unfrozen.reduce((sum, item) => sum + item.scaledShrinkFactor, 0);
|
|
49601
|
-
}
|
|
49602
|
-
if (flexFactorSum === 0) {
|
|
49603
|
-
unfrozen.forEach((item) => item.frozen = true);
|
|
49604
|
-
break;
|
|
49605
|
-
}
|
|
49606
|
-
const usedSpace = items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49607
|
-
const containerMainSize = usedSpace + freeSpace;
|
|
49608
|
-
freeSpace = containerMainSize - usedSpace;
|
|
49609
|
-
let totalViolation = 0;
|
|
49610
|
-
for (const item of unfrozen) {
|
|
49611
|
-
let flexFraction;
|
|
49612
|
-
if (isGrowing) {
|
|
49613
|
-
flexFraction = item.props.grow / flexFactorSum;
|
|
49614
|
-
} else {
|
|
49615
|
-
flexFraction = item.scaledShrinkFactor / flexFactorSum;
|
|
49616
|
-
}
|
|
49617
|
-
const deltaSize = freeSpace * flexFraction;
|
|
49618
|
-
const targetSize = item.flexBasis + deltaSize;
|
|
49619
|
-
const clampedSize = clamp(targetSize, item.props.minSize, item.props.maxSize);
|
|
49620
|
-
const violation = clampedSize - targetSize;
|
|
49621
|
-
item.mainSize = clampedSize;
|
|
49622
|
-
totalViolation += violation;
|
|
49623
|
-
if (violation !== 0) {
|
|
49624
|
-
item.frozen = true;
|
|
49625
|
-
}
|
|
49626
|
-
}
|
|
49627
|
-
if (Math.abs(totalViolation) < 0.01) {
|
|
49628
|
-
unfrozen.forEach((item) => item.frozen = true);
|
|
49629
|
-
break;
|
|
49630
|
-
}
|
|
49631
|
-
freeSpace = containerMainSize - items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49632
|
-
}
|
|
49633
|
-
}
|
|
49634
|
-
function distributeMainAxis(items, containerSize, totalGap, gap, justifyContent) {
|
|
49635
|
-
if (items.length === 0) return;
|
|
49636
|
-
const totalItemSize = items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49637
|
-
const freeSpace = containerSize - totalItemSize - totalGap;
|
|
49638
|
-
let position = 0;
|
|
49639
|
-
let itemGap = gap;
|
|
49640
|
-
let leadingSpace = 0;
|
|
49641
|
-
switch (justifyContent) {
|
|
49642
|
-
case "flex-start":
|
|
49643
|
-
leadingSpace = 0;
|
|
49644
|
-
break;
|
|
49645
|
-
case "flex-end":
|
|
49646
|
-
leadingSpace = freeSpace;
|
|
49647
|
-
break;
|
|
49648
|
-
case "center":
|
|
49649
|
-
leadingSpace = freeSpace / 2;
|
|
49650
|
-
break;
|
|
49651
|
-
case "space-between":
|
|
49652
|
-
leadingSpace = 0;
|
|
49653
|
-
if (items.length > 1) {
|
|
49654
|
-
itemGap = gap + freeSpace / (items.length - 1);
|
|
49655
|
-
}
|
|
49656
|
-
break;
|
|
49657
|
-
case "space-around":
|
|
49658
|
-
if (items.length > 0) {
|
|
49659
|
-
const spacePerItem = freeSpace / items.length;
|
|
49660
|
-
leadingSpace = spacePerItem / 2;
|
|
49661
|
-
itemGap = gap + spacePerItem;
|
|
49662
|
-
}
|
|
49663
|
-
break;
|
|
49664
|
-
case "space-evenly":
|
|
49665
|
-
if (items.length > 0) {
|
|
49666
|
-
const totalSpaces = items.length + 1;
|
|
49667
|
-
const spaceSize = freeSpace / totalSpaces;
|
|
49668
|
-
leadingSpace = spaceSize;
|
|
49669
|
-
itemGap = gap + spaceSize;
|
|
49670
|
-
}
|
|
49671
|
-
break;
|
|
49672
|
-
}
|
|
49673
|
-
position = leadingSpace;
|
|
49674
|
-
for (let i = 0; i < items.length; i++) {
|
|
49675
|
-
items[i].mainPosition = position;
|
|
49676
|
-
position += items[i].mainSize;
|
|
49677
|
-
if (i < items.length - 1) {
|
|
49678
|
-
position += itemGap;
|
|
49679
|
-
}
|
|
49680
|
-
}
|
|
49681
|
-
}
|
|
49682
|
-
function alignCrossAxis(items, containerCrossSize, alignItems) {
|
|
49683
|
-
for (const item of items) {
|
|
49684
|
-
const align = item.props.alignSelf ?? alignItems;
|
|
49685
|
-
const itemCrossSize = item.props.contentSize;
|
|
49686
|
-
item.crossSize = align === "stretch" ? containerCrossSize : itemCrossSize;
|
|
49687
|
-
switch (align) {
|
|
49688
|
-
case "flex-start":
|
|
49689
|
-
item.crossPosition = 0;
|
|
49690
|
-
break;
|
|
49691
|
-
case "flex-end":
|
|
49692
|
-
item.crossPosition = containerCrossSize - item.crossSize;
|
|
49693
|
-
break;
|
|
49694
|
-
case "center":
|
|
49695
|
-
item.crossPosition = (containerCrossSize - item.crossSize) / 2;
|
|
49696
|
-
break;
|
|
49697
|
-
case "stretch":
|
|
49698
|
-
item.crossPosition = 0;
|
|
49699
|
-
item.crossSize = containerCrossSize;
|
|
49700
|
-
break;
|
|
49701
|
-
case "baseline":
|
|
49702
|
-
item.crossPosition = 0;
|
|
49703
|
-
break;
|
|
49704
|
-
}
|
|
49705
|
-
}
|
|
49706
|
-
}
|
|
49707
|
-
function clamp(value, min, max) {
|
|
49708
|
-
return Math.max(min, Math.min(max, value));
|
|
49709
|
-
}
|
|
49710
|
-
function toJustifyContent(justify) {
|
|
49711
|
-
switch (justify) {
|
|
49712
|
-
case "start":
|
|
49713
|
-
return "flex-start";
|
|
49714
|
-
case "end":
|
|
49715
|
-
return "flex-end";
|
|
49716
|
-
case "center":
|
|
49717
|
-
return "center";
|
|
49718
|
-
case "between":
|
|
49719
|
-
return "space-between";
|
|
49720
|
-
case "around":
|
|
49721
|
-
return "space-around";
|
|
49722
|
-
case "evenly":
|
|
49723
|
-
return "space-evenly";
|
|
49724
|
-
default:
|
|
49725
|
-
return "flex-start";
|
|
49726
|
-
}
|
|
49727
|
-
}
|
|
49728
|
-
function toAlignItems(align) {
|
|
49729
|
-
switch (align) {
|
|
49730
|
-
case "start":
|
|
49731
|
-
return "flex-start";
|
|
49732
|
-
case "end":
|
|
49733
|
-
return "flex-end";
|
|
49734
|
-
case "center":
|
|
49735
|
-
return "center";
|
|
49736
|
-
case "stretch":
|
|
49737
|
-
return "stretch";
|
|
49738
|
-
case "baseline":
|
|
49739
|
-
return "baseline";
|
|
49740
|
-
default:
|
|
49741
|
-
return "stretch";
|
|
49742
|
-
}
|
|
49743
|
-
}
|
|
49744
|
-
function createFlexItemProps(contentSize, options = {}) {
|
|
49745
|
-
return {
|
|
49746
|
-
basis: options.basis ?? "auto",
|
|
49747
|
-
grow: options.grow ?? 0,
|
|
49748
|
-
shrink: options.shrink ?? 1,
|
|
49749
|
-
minSize: options.minSize ?? 0,
|
|
49750
|
-
maxSize: options.maxSize ?? Infinity,
|
|
49751
|
-
contentSize,
|
|
49752
|
-
alignSelf: options.alignSelf
|
|
49753
|
-
};
|
|
49754
|
-
}
|
|
49755
|
-
function createFlexGrowItemProps(contentSize, options = {}) {
|
|
49756
|
-
return {
|
|
49757
|
-
basis: options.basis ?? 0,
|
|
49758
|
-
grow: options.grow ?? 1,
|
|
49759
|
-
shrink: options.shrink ?? 1,
|
|
49760
|
-
minSize: options.minSize ?? 0,
|
|
49761
|
-
maxSize: options.maxSize ?? Infinity,
|
|
49762
|
-
contentSize,
|
|
49763
|
-
alignSelf: options.alignSelf
|
|
49764
|
-
};
|
|
49765
|
-
}
|
|
49766
|
-
|
|
49767
|
-
// src/renderer/svg/index.ts
|
|
49768
|
-
var SvgRenderer = class {
|
|
49769
|
-
options;
|
|
49770
|
-
theme;
|
|
49771
|
-
pageWidth = 0;
|
|
49772
|
-
pageHeight = 0;
|
|
49773
|
-
clipPathDefs = [];
|
|
49774
|
-
clipPathCounter = 0;
|
|
49775
|
-
// Default spacing values
|
|
49776
|
-
DEFAULT_GAP = 16;
|
|
49777
|
-
constructor(options = {}) {
|
|
49778
|
-
this.options = {
|
|
49779
|
-
width: options.width ?? 800,
|
|
49780
|
-
height: options.height ?? 600,
|
|
49781
|
-
scale: options.scale ?? 1,
|
|
49782
|
-
background: options.background ?? "#ffffff",
|
|
49783
|
-
padding: options.padding ?? 20,
|
|
49784
|
-
fontFamily: options.fontFamily ?? "system-ui, -apple-system, sans-serif"
|
|
49785
|
-
};
|
|
49786
|
-
this.theme = defaultTheme;
|
|
49787
|
-
}
|
|
49788
|
-
/**
|
|
49789
|
-
* Render a wireframe document to SVG
|
|
49790
|
-
*/
|
|
49791
|
-
render(doc) {
|
|
49792
|
-
this.clipPathDefs = [];
|
|
49793
|
-
this.clipPathCounter = 0;
|
|
49794
|
-
const firstPage = doc.children[0];
|
|
49795
|
-
let width = this.options.width;
|
|
49796
|
-
let height = this.options.height;
|
|
49797
|
-
if (firstPage) {
|
|
49798
|
-
const pageAny = firstPage;
|
|
49799
|
-
const hasExplicitWidth = pageAny.width !== void 0;
|
|
49800
|
-
const hasExplicitHeight = pageAny.height !== void 0;
|
|
49801
|
-
if (hasExplicitWidth || hasExplicitHeight) {
|
|
49802
|
-
if (hasExplicitWidth) {
|
|
49803
|
-
width = pageAny.width;
|
|
49804
|
-
}
|
|
49805
|
-
if (hasExplicitHeight) {
|
|
49806
|
-
height = pageAny.height;
|
|
49807
|
-
}
|
|
49808
|
-
} else if (firstPage.viewport !== void 0 || firstPage.device !== void 0) {
|
|
49809
|
-
const viewport = resolveViewport(firstPage.viewport, firstPage.device);
|
|
49810
|
-
width = viewport.width;
|
|
49811
|
-
height = viewport.height;
|
|
49812
|
-
}
|
|
49813
|
-
}
|
|
49814
|
-
this.pageWidth = width;
|
|
49815
|
-
this.pageHeight = height;
|
|
49816
|
-
const content = doc.children.map((page) => this.renderPage(page)).join("\n");
|
|
49817
|
-
const allDefs = this.generateDefs() + "\n" + this.clipPathDefs.join("\n");
|
|
49818
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
49819
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
49820
|
-
<defs>
|
|
49821
|
-
${allDefs}
|
|
49822
|
-
</defs>
|
|
49823
|
-
<rect width="100%" height="100%" fill="${this.options.background}"/>
|
|
49824
|
-
<g transform="scale(${this.options.scale})">
|
|
49825
|
-
${content}
|
|
49826
|
-
</g>
|
|
49827
|
-
</svg>`;
|
|
49828
|
-
return { svg, width, height };
|
|
49829
|
-
}
|
|
49830
|
-
/**
|
|
49831
|
-
* Generate SVG defs (styles)
|
|
49832
|
-
*/
|
|
49833
|
-
generateDefs() {
|
|
49834
|
-
return `
|
|
49835
|
-
<style>
|
|
49836
|
-
text { font-family: ${this.options.fontFamily}; }
|
|
49837
|
-
.wf-title { font-weight: 600; }
|
|
49838
|
-
.wf-muted { fill: ${this.theme.colors.muted}; }
|
|
49839
|
-
</style>
|
|
49840
|
-
`;
|
|
49841
|
-
}
|
|
49842
|
-
// ===========================================
|
|
49843
|
-
// Page Layout
|
|
49844
|
-
// ===========================================
|
|
49845
|
-
renderPage(page) {
|
|
49846
|
-
const padding = this.options.padding;
|
|
49847
|
-
const contentWidth = this.pageWidth - padding * 2;
|
|
49848
|
-
const contentHeight = this.pageHeight - padding * 2;
|
|
49849
|
-
const constraints = {
|
|
49850
|
-
maxWidth: contentWidth,
|
|
49851
|
-
maxHeight: contentHeight
|
|
49852
|
-
};
|
|
49853
|
-
const childBoxes = [];
|
|
49854
|
-
let currentY = padding;
|
|
49855
|
-
const isCentered = page.centered === true;
|
|
49856
|
-
const hasHeader = page.children.some((c) => c.type === "Header");
|
|
49857
|
-
const hasFooter = page.children.some((c) => c.type === "Footer");
|
|
49858
|
-
const hasMain = page.children.some((c) => c.type === "Main");
|
|
49859
|
-
if (hasHeader || hasFooter || hasMain) {
|
|
49860
|
-
return this.renderPageWithFixedLayout(page, padding, contentWidth, contentHeight);
|
|
49861
|
-
}
|
|
49862
|
-
const measurements = page.children.map((child) => this.measureNode(child, constraints));
|
|
49863
|
-
const gap = this.getGap(page) || this.DEFAULT_GAP;
|
|
49864
|
-
const totalChildrenHeight = measurements.reduce((sum, m, i) => {
|
|
49865
|
-
return sum + m.height + (i > 0 ? gap : 0);
|
|
49866
|
-
}, 0);
|
|
49867
|
-
if (isCentered) {
|
|
49868
|
-
const availableHeight = contentHeight;
|
|
49869
|
-
currentY = padding + Math.max(0, (availableHeight - totalChildrenHeight) / 2);
|
|
49870
|
-
}
|
|
49871
|
-
for (let i = 0; i < page.children.length; i++) {
|
|
49872
|
-
const child = page.children[i];
|
|
49873
|
-
const measurement = measurements[i];
|
|
49874
|
-
let childX = padding;
|
|
49875
|
-
if (isCentered || this.shouldCenterHorizontally(child)) {
|
|
49876
|
-
childX = padding + (contentWidth - measurement.width) / 2;
|
|
49877
|
-
}
|
|
49878
|
-
const box = this.layoutNode(child, childX, currentY, constraints);
|
|
49879
|
-
childBoxes.push(box);
|
|
49880
|
-
currentY += box.height + gap;
|
|
49881
|
-
}
|
|
49882
|
-
const elements = [];
|
|
49883
|
-
for (const box of childBoxes) {
|
|
49884
|
-
elements.push(this.renderBox(box));
|
|
49885
|
-
}
|
|
49886
|
-
return elements.join("\n");
|
|
49887
|
-
}
|
|
49888
|
-
/**
|
|
49889
|
-
* Render page with fixed header/footer layout
|
|
49890
|
-
* Header at top, Footer at bottom, Main fills remaining space
|
|
49891
|
-
*/
|
|
49892
|
-
renderPageWithFixedLayout(page, padding, contentWidth, contentHeight) {
|
|
49893
|
-
const constraints = {
|
|
49894
|
-
maxWidth: contentWidth,
|
|
49895
|
-
maxHeight: contentHeight
|
|
49896
|
-
};
|
|
49897
|
-
const header = page.children.find((c) => c.type === "Header");
|
|
49898
|
-
const footer = page.children.find((c) => c.type === "Footer");
|
|
49899
|
-
const otherChildren = page.children.filter((c) => c.type !== "Header" && c.type !== "Footer");
|
|
49900
|
-
const elements = [];
|
|
49901
|
-
let headerHeight = 0;
|
|
49902
|
-
let footerHeight = 0;
|
|
49903
|
-
let currentY = padding;
|
|
49904
|
-
if (header) {
|
|
49905
|
-
const headerMeasure = this.measureNode(header, constraints);
|
|
49906
|
-
headerHeight = headerMeasure.height;
|
|
49907
|
-
const headerBox = this.layoutNode(header, padding, currentY, constraints);
|
|
49908
|
-
elements.push(this.renderBox(headerBox));
|
|
49909
|
-
}
|
|
49910
|
-
if (footer) {
|
|
49911
|
-
const footerMeasure = this.measureNode(footer, constraints);
|
|
49912
|
-
footerHeight = footerMeasure.height;
|
|
49913
|
-
const footerY = this.pageHeight - padding - footerHeight;
|
|
49914
|
-
const footerBox = this.layoutNode(footer, padding, footerY, constraints);
|
|
49915
|
-
elements.push(this.renderBox(footerBox));
|
|
49916
|
-
}
|
|
49917
|
-
const mainStartY = currentY + headerHeight;
|
|
49918
|
-
const mainEndY = this.pageHeight - padding - footerHeight;
|
|
49919
|
-
const mainHeight = mainEndY - mainStartY;
|
|
49920
|
-
if (otherChildren.length > 0) {
|
|
49921
|
-
const mainConstraints = {
|
|
49922
|
-
maxWidth: contentWidth,
|
|
49923
|
-
maxHeight: mainHeight
|
|
49924
|
-
};
|
|
49925
|
-
const clipId = `main-clip-${this.clipPathCounter++}`;
|
|
49926
|
-
this.clipPathDefs.push(`<clipPath id="${clipId}"><rect x="${padding}" y="${mainStartY}" width="${contentWidth}" height="${mainHeight}"/></clipPath>`);
|
|
49927
|
-
const mainContent = [];
|
|
49928
|
-
mainContent.push(`<g clip-path="url(#${clipId})">`);
|
|
49929
|
-
let childY = mainStartY;
|
|
49930
|
-
const gap = this.getGap(page) || 0;
|
|
49931
|
-
for (const child of otherChildren) {
|
|
49932
|
-
const childBox = this.layoutNode(child, padding, childY, mainConstraints);
|
|
49933
|
-
mainContent.push(this.renderBox(childBox));
|
|
49934
|
-
childY += childBox.height + gap;
|
|
49935
|
-
}
|
|
49936
|
-
mainContent.push(`</g>`);
|
|
49937
|
-
elements.push(mainContent.join("\n"));
|
|
49938
|
-
}
|
|
49939
|
-
return elements.join("\n");
|
|
49940
|
-
}
|
|
49941
|
-
shouldCenterHorizontally(node) {
|
|
49942
|
-
return node.type === "Card" || node.type === "Modal";
|
|
49943
|
-
}
|
|
49944
|
-
// ===========================================
|
|
49945
|
-
// Measurement Phase
|
|
49946
|
-
// ===========================================
|
|
49947
|
-
measureNode(node, constraints) {
|
|
49948
|
-
switch (node.type) {
|
|
49949
|
-
case "Row":
|
|
49950
|
-
return this.measureRow(node, constraints);
|
|
49951
|
-
case "Col":
|
|
49952
|
-
return this.measureCol(node, constraints);
|
|
49953
|
-
case "Header":
|
|
49954
|
-
return this.measureHeader(node, constraints);
|
|
49955
|
-
case "Footer":
|
|
49956
|
-
return this.measureFooter(node, constraints);
|
|
49957
|
-
case "Main":
|
|
49958
|
-
return this.measureMain(node, constraints);
|
|
49959
|
-
case "Sidebar":
|
|
49960
|
-
return this.measureSidebar(node, constraints);
|
|
49961
|
-
case "Card":
|
|
49962
|
-
return this.measureCard(node, constraints);
|
|
49963
|
-
case "Modal":
|
|
49964
|
-
return this.measureModal(node, constraints);
|
|
49965
|
-
case "Title":
|
|
49966
|
-
return this.measureTitle(node);
|
|
49967
|
-
case "Text":
|
|
49968
|
-
return this.measureText(node);
|
|
49969
|
-
case "Button":
|
|
49970
|
-
return this.measureButton(node, constraints);
|
|
49971
|
-
case "Input":
|
|
49972
|
-
return this.measureInput(node, constraints);
|
|
49973
|
-
case "Textarea":
|
|
49974
|
-
return this.measureTextarea(node, constraints);
|
|
49975
|
-
case "Select":
|
|
49976
|
-
return this.measureSelect(node, constraints);
|
|
49977
|
-
case "Checkbox":
|
|
49978
|
-
return this.measureCheckbox(node);
|
|
49979
|
-
case "Radio":
|
|
49980
|
-
return this.measureRadio(node);
|
|
49981
|
-
case "Switch":
|
|
49982
|
-
return this.measureSwitch(node);
|
|
49983
|
-
case "Link":
|
|
49984
|
-
return this.measureLink(node);
|
|
49985
|
-
case "Image":
|
|
49986
|
-
return this.measureImage(node, constraints);
|
|
49987
|
-
case "Placeholder":
|
|
49988
|
-
return this.measurePlaceholder(node, constraints);
|
|
49989
|
-
case "Avatar":
|
|
49990
|
-
return this.measureAvatar(node, constraints);
|
|
49991
|
-
case "Badge":
|
|
49992
|
-
return this.measureBadge(node);
|
|
49993
|
-
case "Table":
|
|
49994
|
-
return this.measureTable(node);
|
|
49995
|
-
case "List":
|
|
49996
|
-
return this.measureList(node);
|
|
49997
|
-
case "Alert":
|
|
49998
|
-
return this.measureAlert(node, constraints);
|
|
49999
|
-
case "Progress":
|
|
50000
|
-
return this.measureProgress(node, constraints);
|
|
50001
|
-
case "Spinner":
|
|
50002
|
-
return this.measureSpinner(node);
|
|
50003
|
-
case "Nav":
|
|
50004
|
-
return this.measureNav(node);
|
|
50005
|
-
case "Tabs":
|
|
50006
|
-
return this.measureTabs(node);
|
|
50007
|
-
case "Breadcrumb":
|
|
50008
|
-
return this.measureBreadcrumb(node);
|
|
50009
|
-
case "Icon":
|
|
50010
|
-
return this.measureIcon(node);
|
|
50011
|
-
case "Divider":
|
|
50012
|
-
return this.measureDivider(node, constraints);
|
|
50013
|
-
default:
|
|
50014
|
-
return { width: 100, height: 40 };
|
|
50015
|
-
}
|
|
50016
|
-
}
|
|
50017
|
-
measureRow(node, constraints) {
|
|
50018
|
-
const padding = this.getPadding(node);
|
|
50019
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50020
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50021
|
-
const childMeasurements = node.children.map(
|
|
50022
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50023
|
-
);
|
|
50024
|
-
const maxChildHeight = Math.max(...childMeasurements.map((m) => m.height), 0);
|
|
50025
|
-
const totalChildWidth = childMeasurements.reduce((sum, m) => sum + m.width, 0);
|
|
50026
|
-
const totalGapWidth = Math.max(0, (node.children.length - 1) * gap);
|
|
50027
|
-
const contentWidth = totalChildWidth + totalGapWidth + padding.left + padding.right;
|
|
50028
|
-
const hasExplicitWidth = "w" in node && node.w !== void 0;
|
|
50029
|
-
const width = hasExplicitWidth ? constraints.maxWidth : Math.min(contentWidth, constraints.maxWidth);
|
|
50030
|
-
return {
|
|
50031
|
-
width,
|
|
50032
|
-
height: maxChildHeight + padding.top + padding.bottom
|
|
50033
|
-
};
|
|
50034
|
-
}
|
|
50035
|
-
measureCol(node, constraints) {
|
|
50036
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50037
|
-
const padding = this.getPadding(node);
|
|
50038
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50039
|
-
const childMeasurements = node.children.map(
|
|
50040
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50041
|
-
);
|
|
50042
|
-
const totalHeight = childMeasurements.reduce(
|
|
50043
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50044
|
-
0
|
|
50045
|
-
);
|
|
50046
|
-
const maxChildWidth = Math.max(...childMeasurements.map((m) => m.width), 0);
|
|
50047
|
-
return {
|
|
50048
|
-
width: Math.max(maxChildWidth + padding.left + padding.right, constraints.maxWidth),
|
|
50049
|
-
height: totalHeight + padding.top + padding.bottom
|
|
50050
|
-
};
|
|
50051
|
-
}
|
|
50052
|
-
measureHeader(node, constraints) {
|
|
50053
|
-
const padding = this.getPadding(node);
|
|
50054
|
-
const height = this.resolveSize(node.h) || 56;
|
|
50055
|
-
return {
|
|
50056
|
-
width: constraints.maxWidth,
|
|
50057
|
-
height: height + padding.top + padding.bottom
|
|
50058
|
-
};
|
|
50059
|
-
}
|
|
50060
|
-
measureFooter(node, constraints) {
|
|
50061
|
-
const padding = this.getPadding(node);
|
|
50062
|
-
const height = this.resolveSize(node.h) || 60;
|
|
50063
|
-
return {
|
|
50064
|
-
width: constraints.maxWidth,
|
|
50065
|
-
height: height + padding.top + padding.bottom
|
|
50066
|
-
};
|
|
50067
|
-
}
|
|
50068
|
-
measureMain(node, constraints) {
|
|
50069
|
-
const padding = this.getPadding(node);
|
|
50070
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50071
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50072
|
-
const childMeasurements = node.children.map(
|
|
50073
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50074
|
-
);
|
|
50075
|
-
const totalHeight = childMeasurements.reduce(
|
|
50076
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50077
|
-
0
|
|
50078
|
-
);
|
|
50079
|
-
return {
|
|
50080
|
-
width: constraints.maxWidth,
|
|
50081
|
-
height: totalHeight + padding.top + padding.bottom
|
|
50082
|
-
};
|
|
50083
|
-
}
|
|
50084
|
-
measureSidebar(node, constraints) {
|
|
50085
|
-
const width = this.resolveSize(node.w) || 200;
|
|
50086
|
-
const padding = this.getPadding(node);
|
|
50087
|
-
const gap = this.getGap(node) ?? 8;
|
|
50088
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50089
|
-
const childMeasurements = node.children.map(
|
|
50090
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50091
|
-
);
|
|
50092
|
-
const contentHeight = childMeasurements.reduce(
|
|
50093
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50094
|
-
0
|
|
50095
|
-
) + padding.top + padding.bottom;
|
|
50096
|
-
const explicitHeight = this.resolveSize(node.h);
|
|
50097
|
-
const height = explicitHeight || constraints.maxHeight || contentHeight;
|
|
50098
|
-
return { width, height };
|
|
50099
|
-
}
|
|
50100
|
-
measureCard(node, constraints) {
|
|
50101
|
-
let cardWidth = this.resolveSize(node.w);
|
|
50102
|
-
if (!cardWidth) {
|
|
50103
|
-
cardWidth = Math.min(360, constraints.maxWidth);
|
|
50104
|
-
} else {
|
|
50105
|
-
cardWidth = Math.min(cardWidth, constraints.maxWidth);
|
|
50106
|
-
}
|
|
50107
|
-
const explicitHeight = this.resolveSize(node.h);
|
|
50108
|
-
if (explicitHeight) {
|
|
50109
|
-
return { width: cardWidth, height: explicitHeight };
|
|
50110
|
-
}
|
|
50111
|
-
const padding = this.getPadding(node);
|
|
50112
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50113
|
-
const innerWidth = cardWidth - padding.left - padding.right;
|
|
50114
|
-
const childMeasurements = node.children.map(
|
|
50115
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50116
|
-
);
|
|
50117
|
-
let contentHeight = 0;
|
|
50118
|
-
if (node.title) {
|
|
50119
|
-
contentHeight += 28;
|
|
50120
|
-
}
|
|
50121
|
-
contentHeight += childMeasurements.reduce(
|
|
50122
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50123
|
-
0
|
|
50124
|
-
);
|
|
50125
|
-
return {
|
|
50126
|
-
width: cardWidth,
|
|
50127
|
-
height: contentHeight + padding.top + padding.bottom
|
|
50128
|
-
};
|
|
50129
|
-
}
|
|
50130
|
-
measureModal(node, constraints) {
|
|
50131
|
-
const width = this.resolveSize(node.w) || 400;
|
|
50132
|
-
const padding = this.getPadding(node);
|
|
50133
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50134
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50135
|
-
const childMeasurements = node.children.map(
|
|
50136
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50137
|
-
);
|
|
50138
|
-
let contentHeight = node.title ? 40 : 0;
|
|
50139
|
-
contentHeight += childMeasurements.reduce(
|
|
50140
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50141
|
-
0
|
|
50142
|
-
);
|
|
50143
|
-
return {
|
|
50144
|
-
width,
|
|
50145
|
-
height: contentHeight + padding.top + padding.bottom
|
|
50146
|
-
};
|
|
50147
|
-
}
|
|
50148
|
-
measureTitle(node) {
|
|
50149
|
-
const level = node.level || 1;
|
|
50150
|
-
const fontSize = this.getTitleFontSize(level);
|
|
50151
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50152
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50153
|
-
}
|
|
50154
|
-
measureText(node) {
|
|
50155
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
50156
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50157
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50158
|
-
}
|
|
50159
|
-
measureButton(node, constraints) {
|
|
50160
|
-
const hasIcon = !!node.icon;
|
|
50161
|
-
const isIconOnly = hasIcon && !node.content.trim();
|
|
50162
|
-
const iconSize = 16;
|
|
50163
|
-
const padding = 16;
|
|
50164
|
-
let width;
|
|
50165
|
-
if (this.isFullWidth(node)) {
|
|
50166
|
-
width = constraints.maxWidth;
|
|
50167
|
-
} else if (isIconOnly) {
|
|
50168
|
-
width = iconSize + padding * 2;
|
|
50169
|
-
} else if (hasIcon) {
|
|
50170
|
-
width = Math.max(80, this.estimateTextWidth(node.content, 14) + iconSize + 48);
|
|
50171
|
-
} else {
|
|
50172
|
-
width = Math.max(80, this.estimateTextWidth(node.content, 14) + 32);
|
|
50173
|
-
}
|
|
50174
|
-
return { width, height: 40 };
|
|
50175
|
-
}
|
|
50176
|
-
measureInput(node, constraints) {
|
|
50177
|
-
let width;
|
|
50178
|
-
if (this.resolveSize(node.w)) {
|
|
50179
|
-
width = this.resolveSize(node.w);
|
|
50180
|
-
} else if (constraints.inHeader) {
|
|
50181
|
-
const placeholderWidth = node.placeholder ? this.estimateTextWidth(node.placeholder, 14) : 60;
|
|
50182
|
-
width = Math.max(120, placeholderWidth + 24 + 100);
|
|
50183
|
-
} else {
|
|
50184
|
-
width = constraints.maxWidth;
|
|
50185
|
-
}
|
|
50186
|
-
let height = 36;
|
|
50187
|
-
if (node.label) height += 24;
|
|
50188
|
-
return { width, height };
|
|
50189
|
-
}
|
|
50190
|
-
measureTextarea(node, constraints) {
|
|
50191
|
-
const width = this.resolveSize(node.w) || constraints.maxWidth;
|
|
50192
|
-
let height = node.rows ? node.rows * 24 : 100;
|
|
50193
|
-
if (node.label) height += 24;
|
|
50194
|
-
return { width, height };
|
|
50195
|
-
}
|
|
50196
|
-
measureSelect(node, constraints) {
|
|
50197
|
-
const width = this.resolveSize(node.w) || constraints.maxWidth;
|
|
50198
|
-
let height = 40;
|
|
50199
|
-
if (node.label) height += 24;
|
|
50200
|
-
return { width, height };
|
|
50201
|
-
}
|
|
50202
|
-
measureCheckbox(node) {
|
|
50203
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50204
|
-
return { width: 18 + labelWidth, height: 24 };
|
|
50205
|
-
}
|
|
50206
|
-
measureRadio(node) {
|
|
50207
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50208
|
-
return { width: 18 + labelWidth, height: 24 };
|
|
50209
|
-
}
|
|
50210
|
-
measureSwitch(node) {
|
|
50211
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50212
|
-
return { width: 44 + labelWidth, height: 28 };
|
|
50213
|
-
}
|
|
50214
|
-
measureLink(node) {
|
|
50215
|
-
const fontSize = 14;
|
|
50216
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50217
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50218
|
-
}
|
|
50219
|
-
measureImage(node, constraints) {
|
|
50220
|
-
let width;
|
|
50221
|
-
if (this.isFullWidth(node)) {
|
|
50222
|
-
width = constraints.maxWidth;
|
|
50223
|
-
} else {
|
|
50224
|
-
width = this.resolveSize(node.w) || 200;
|
|
50225
|
-
}
|
|
50226
|
-
const height = this.resolveSize(node.h) || 150;
|
|
50227
|
-
return { width, height };
|
|
50228
|
-
}
|
|
50229
|
-
measurePlaceholder(node, constraints) {
|
|
50230
|
-
let width;
|
|
50231
|
-
if (node.w !== void 0) {
|
|
50232
|
-
width = this.isFullWidth(node) ? constraints.maxWidth : this.resolveSize(node.w) || 200;
|
|
50233
|
-
} else {
|
|
50234
|
-
width = constraints.maxWidth || 200;
|
|
50235
|
-
}
|
|
50236
|
-
const height = this.resolveSize(node.h) || 100;
|
|
50237
|
-
return { width, height };
|
|
50238
|
-
}
|
|
50239
|
-
measureAvatar(node, constraints) {
|
|
50240
|
-
const sizes = { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 };
|
|
50241
|
-
const defaultSize = constraints?.inHeader ? "sm" : "md";
|
|
50242
|
-
const size = sizes[node.size || defaultSize] || 40;
|
|
50243
|
-
return { width: size, height: size };
|
|
50244
|
-
}
|
|
50245
|
-
measureBadge(node) {
|
|
50246
|
-
const width = Math.max(24, this.estimateTextWidth(node.content, 12) + 16);
|
|
50247
|
-
return { width, height: 22 };
|
|
50248
|
-
}
|
|
50249
|
-
measureTable(node) {
|
|
50250
|
-
const columns = node.columns || [];
|
|
50251
|
-
const rows = node.rows || [];
|
|
50252
|
-
const rowCount = rows.length || 3;
|
|
50253
|
-
const colWidth = 120;
|
|
50254
|
-
const rowHeight = 40;
|
|
50255
|
-
return {
|
|
50256
|
-
width: columns.length * colWidth,
|
|
50257
|
-
height: (rowCount + 1) * rowHeight
|
|
50258
|
-
};
|
|
50259
|
-
}
|
|
50260
|
-
measureList(node) {
|
|
50261
|
-
const items = node.items || [];
|
|
50262
|
-
const maxItemWidth = Math.max(...items.map((item) => {
|
|
50263
|
-
const content = typeof item === "string" ? item : item.content;
|
|
50264
|
-
return this.estimateTextWidth(content, 14);
|
|
50265
|
-
}), 100);
|
|
50266
|
-
return { width: maxItemWidth + 24, height: items.length * 28 };
|
|
50267
|
-
}
|
|
50268
|
-
measureAlert(_node, constraints) {
|
|
50269
|
-
const width = Math.min(400, constraints.maxWidth);
|
|
50270
|
-
return { width, height: 48 };
|
|
50271
|
-
}
|
|
50272
|
-
measureProgress(node, constraints) {
|
|
50273
|
-
const width = Math.min(200, constraints.maxWidth);
|
|
50274
|
-
let height = 8;
|
|
50275
|
-
if (node.label) height += 24;
|
|
50276
|
-
return { width, height };
|
|
50277
|
-
}
|
|
50278
|
-
measureSpinner(node) {
|
|
50279
|
-
const sizes = { xs: 16, sm: 20, md: 24, lg: 32, xl: 40 };
|
|
50280
|
-
const size = sizes[node.size || "md"] || 24;
|
|
50281
|
-
return { width: size, height: size };
|
|
50282
|
-
}
|
|
50283
|
-
measureNav(node) {
|
|
50284
|
-
const items = node.items || [];
|
|
50285
|
-
if (node.vertical) {
|
|
50286
|
-
const maxWidth = Math.max(...items.map((item) => {
|
|
50287
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50288
|
-
return this.estimateTextWidth(label, 14);
|
|
50289
|
-
}), 100);
|
|
50290
|
-
return { width: maxWidth, height: items.length * 32 };
|
|
50291
|
-
} else {
|
|
50292
|
-
const totalWidth = items.reduce((sum, item) => {
|
|
50293
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50294
|
-
return sum + this.estimateTextWidth(label, 14) + 24;
|
|
50295
|
-
}, 0);
|
|
50296
|
-
return { width: totalWidth, height: 32 };
|
|
50297
|
-
}
|
|
50298
|
-
}
|
|
50299
|
-
measureTabs(node) {
|
|
50300
|
-
const items = node.items || [];
|
|
50301
|
-
const totalWidth = items.reduce((sum, item) => {
|
|
50302
|
-
const label = typeof item === "string" ? item : item;
|
|
50303
|
-
return sum + this.estimateTextWidth(label, 14) + 32;
|
|
50304
|
-
}, 0);
|
|
50305
|
-
return { width: totalWidth, height: 44 };
|
|
50306
|
-
}
|
|
50307
|
-
measureBreadcrumb(node) {
|
|
50308
|
-
const items = node.items || [];
|
|
50309
|
-
const totalWidth = items.reduce((sum, item, idx) => {
|
|
50310
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50311
|
-
return sum + this.estimateTextWidth(label, 14) + (idx < items.length - 1 ? 24 : 0);
|
|
50312
|
-
}, 0);
|
|
50313
|
-
return { width: totalWidth, height: 28 };
|
|
50314
|
-
}
|
|
50315
|
-
measureIcon(node) {
|
|
50316
|
-
const sizes = { xs: 12, sm: 16, md: 20, lg: 24, xl: 32 };
|
|
50317
|
-
const size = sizes[node.size || "md"] || 20;
|
|
50318
|
-
return { width: size, height: size };
|
|
50319
|
-
}
|
|
50320
|
-
measureDivider(_node, constraints) {
|
|
50321
|
-
return { width: constraints.maxWidth, height: 1 };
|
|
50322
|
-
}
|
|
50323
|
-
// ===========================================
|
|
50324
|
-
// Layout Phase
|
|
50325
|
-
// ===========================================
|
|
50326
|
-
layoutNode(node, x, y, constraints) {
|
|
50327
|
-
switch (node.type) {
|
|
50328
|
-
case "Row":
|
|
50329
|
-
return this.layoutRow(node, x, y, constraints);
|
|
50330
|
-
case "Col":
|
|
50331
|
-
return this.layoutCol(node, x, y, constraints);
|
|
50332
|
-
case "Header":
|
|
50333
|
-
return this.layoutHeader(node, x, y, constraints);
|
|
50334
|
-
case "Footer":
|
|
50335
|
-
return this.layoutFooter(node, x, y, constraints);
|
|
50336
|
-
case "Main":
|
|
50337
|
-
return this.layoutMain(node, x, y, constraints);
|
|
50338
|
-
case "Sidebar":
|
|
50339
|
-
return this.layoutSidebar(node, x, y, constraints);
|
|
50340
|
-
case "Card":
|
|
50341
|
-
return this.layoutCard(node, x, y, constraints);
|
|
50342
|
-
default:
|
|
50343
|
-
const size = this.measureNode(node, constraints);
|
|
50344
|
-
return {
|
|
50345
|
-
x,
|
|
50346
|
-
y,
|
|
50347
|
-
width: size.width,
|
|
50348
|
-
height: size.height,
|
|
50349
|
-
node,
|
|
50350
|
-
children: []
|
|
50351
|
-
};
|
|
50352
|
-
}
|
|
50353
|
-
}
|
|
50354
|
-
layoutRow(node, x, y, constraints) {
|
|
50355
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50356
|
-
const padding = this.getPadding(node);
|
|
50357
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50358
|
-
const justify = node.justify || "start";
|
|
50359
|
-
const align = node.align || (constraints.inHeader ? "center" : "start");
|
|
50360
|
-
const childMeasurements = node.children.map(
|
|
50361
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50362
|
-
);
|
|
50363
|
-
const flexItems = node.children.map((child, i) => {
|
|
50364
|
-
const measurement = childMeasurements[i];
|
|
50365
|
-
if ("w" in child && child.w !== void 0 && child.w !== "full") {
|
|
50366
|
-
const resolved = this.resolveSize(child.w);
|
|
50367
|
-
if (resolved !== void 0) {
|
|
50368
|
-
return createFlexItemProps(measurement.height, {
|
|
50369
|
-
basis: resolved,
|
|
50370
|
-
grow: 0,
|
|
50371
|
-
shrink: 0,
|
|
50372
|
-
minSize: resolved,
|
|
50373
|
-
maxSize: resolved,
|
|
50374
|
-
contentSize: measurement.width
|
|
50375
|
-
});
|
|
50376
|
-
}
|
|
50377
|
-
}
|
|
50378
|
-
if (this.isFlexContainer(child)) {
|
|
50379
|
-
return createFlexGrowItemProps(measurement.height, {
|
|
50380
|
-
basis: 0,
|
|
50381
|
-
grow: 1,
|
|
50382
|
-
shrink: 1,
|
|
50383
|
-
minSize: 0,
|
|
50384
|
-
maxSize: Infinity,
|
|
50385
|
-
contentSize: measurement.width
|
|
50386
|
-
});
|
|
50387
|
-
}
|
|
50388
|
-
if (constraints.inHeader && child.type === "Input") {
|
|
50389
|
-
return createFlexGrowItemProps(measurement.height, {
|
|
50390
|
-
basis: measurement.width,
|
|
50391
|
-
// auto = content size
|
|
50392
|
-
grow: 1,
|
|
50393
|
-
shrink: 1,
|
|
50394
|
-
minSize: 120,
|
|
50395
|
-
// min-width: 120px
|
|
50396
|
-
maxSize: Infinity,
|
|
50397
|
-
contentSize: measurement.width
|
|
50398
|
-
});
|
|
50399
|
-
}
|
|
50400
|
-
return createFlexItemProps(measurement.height, {
|
|
50401
|
-
basis: measurement.width,
|
|
50402
|
-
// auto = content size
|
|
50403
|
-
grow: 0,
|
|
50404
|
-
shrink: 1,
|
|
50405
|
-
minSize: 0,
|
|
50406
|
-
maxSize: Infinity,
|
|
50407
|
-
contentSize: measurement.width
|
|
50408
|
-
});
|
|
50409
|
-
});
|
|
50410
|
-
const flexConfig = {
|
|
50411
|
-
mainSize: innerWidth,
|
|
50412
|
-
crossSize: void 0,
|
|
50413
|
-
// Will use max child height
|
|
50414
|
-
direction: "row",
|
|
50415
|
-
justifyContent: toJustifyContent(justify),
|
|
50416
|
-
alignItems: toAlignItems(align),
|
|
50417
|
-
gap
|
|
50418
|
-
};
|
|
50419
|
-
const flexResult = computeFlexLayout(flexItems, flexConfig);
|
|
50420
|
-
const maxChildHeight = Math.max(...childMeasurements.map((m) => m.height), 0);
|
|
50421
|
-
const innerMaxHeight = constraints.maxHeight ? constraints.maxHeight - padding.top - padding.bottom : void 0;
|
|
50422
|
-
const effectiveHeight = innerMaxHeight || maxChildHeight;
|
|
50423
|
-
const rowHeight = effectiveHeight + padding.top + padding.bottom;
|
|
50424
|
-
const children = [];
|
|
50425
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50426
|
-
const child = node.children[i];
|
|
50427
|
-
const flexItem = flexResult.items[i];
|
|
50428
|
-
const measurement = childMeasurements[i];
|
|
50429
|
-
const childX = x + padding.left + flexItem.mainPosition;
|
|
50430
|
-
let childY = y + padding.top;
|
|
50431
|
-
switch (align) {
|
|
50432
|
-
case "center":
|
|
50433
|
-
childY = y + padding.top + (maxChildHeight - measurement.height) / 2;
|
|
50434
|
-
break;
|
|
50435
|
-
case "end":
|
|
50436
|
-
childY = y + padding.top + (maxChildHeight - measurement.height);
|
|
50437
|
-
break;
|
|
50438
|
-
}
|
|
50439
|
-
const childBox = this.layoutNode(child, childX, childY, {
|
|
50440
|
-
...constraints,
|
|
50441
|
-
maxWidth: flexItem.mainSize,
|
|
50442
|
-
maxHeight: effectiveHeight
|
|
50443
|
-
});
|
|
50444
|
-
children.push(childBox);
|
|
50445
|
-
}
|
|
50446
|
-
return {
|
|
50447
|
-
x,
|
|
50448
|
-
y,
|
|
50449
|
-
width: constraints.maxWidth,
|
|
50450
|
-
height: rowHeight,
|
|
50451
|
-
node,
|
|
50452
|
-
children,
|
|
50453
|
-
padding
|
|
50454
|
-
};
|
|
50455
|
-
}
|
|
50456
|
-
layoutCol(node, x, y, constraints) {
|
|
50457
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50458
|
-
const padding = this.getPadding(node);
|
|
50459
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50460
|
-
const innerHeight = constraints.maxHeight ? constraints.maxHeight - padding.top - padding.bottom : void 0;
|
|
50461
|
-
const align = node.align || "stretch";
|
|
50462
|
-
const childMeasurements = node.children.map(
|
|
50463
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50464
|
-
);
|
|
50465
|
-
const flexItems = node.children.map((child, i) => {
|
|
50466
|
-
const measurement = childMeasurements[i];
|
|
50467
|
-
if ("h" in child && child.h !== void 0) {
|
|
50468
|
-
const resolved = this.resolveSize(child.h);
|
|
50469
|
-
if (resolved !== void 0) {
|
|
50470
|
-
return createFlexItemProps(measurement.width, {
|
|
50471
|
-
basis: resolved,
|
|
50472
|
-
grow: 0,
|
|
50473
|
-
shrink: 0,
|
|
50474
|
-
minSize: resolved,
|
|
50475
|
-
maxSize: resolved,
|
|
50476
|
-
contentSize: measurement.height
|
|
50477
|
-
});
|
|
50478
|
-
}
|
|
50479
|
-
}
|
|
50480
|
-
if (child.type === "Row" && this.rowContainsSidebarOrMain(child)) {
|
|
50481
|
-
return createFlexGrowItemProps(measurement.width, {
|
|
50482
|
-
basis: 0,
|
|
50483
|
-
grow: 1,
|
|
50484
|
-
shrink: 1,
|
|
50485
|
-
minSize: 0,
|
|
50486
|
-
maxSize: Infinity,
|
|
50487
|
-
contentSize: measurement.height
|
|
50488
|
-
});
|
|
50489
|
-
}
|
|
50490
|
-
return createFlexItemProps(measurement.width, {
|
|
50491
|
-
basis: measurement.height,
|
|
50492
|
-
// auto = content size
|
|
50493
|
-
grow: 0,
|
|
50494
|
-
shrink: 1,
|
|
50495
|
-
minSize: 0,
|
|
50496
|
-
maxSize: Infinity,
|
|
50497
|
-
contentSize: measurement.height
|
|
50498
|
-
});
|
|
50499
|
-
});
|
|
50500
|
-
const flexConfig = {
|
|
50501
|
-
mainSize: innerHeight ?? childMeasurements.reduce(
|
|
50502
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50503
|
-
0
|
|
50504
|
-
),
|
|
50505
|
-
crossSize: innerWidth,
|
|
50506
|
-
direction: "column",
|
|
50507
|
-
justifyContent: "flex-start",
|
|
50508
|
-
alignItems: toAlignItems(align),
|
|
50509
|
-
gap
|
|
50510
|
-
};
|
|
50511
|
-
const flexResult = computeFlexLayout(flexItems, flexConfig);
|
|
50512
|
-
const children = [];
|
|
50513
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50514
|
-
const child = node.children[i];
|
|
50515
|
-
const flexItem = flexResult.items[i];
|
|
50516
|
-
const measurement = childMeasurements[i];
|
|
50517
|
-
let childX = x + padding.left;
|
|
50518
|
-
let childWidth = align === "stretch" ? innerWidth : measurement.width;
|
|
50519
|
-
switch (align) {
|
|
50520
|
-
case "center":
|
|
50521
|
-
childX = x + padding.left + (innerWidth - measurement.width) / 2;
|
|
50522
|
-
break;
|
|
50523
|
-
case "end":
|
|
50524
|
-
childX = x + padding.left + (innerWidth - measurement.width);
|
|
50525
|
-
break;
|
|
50526
|
-
}
|
|
50527
|
-
const childY = y + padding.top + flexItem.mainPosition;
|
|
50528
|
-
const childBox = this.layoutNode(child, childX, childY, {
|
|
50529
|
-
...constraints,
|
|
50530
|
-
maxWidth: childWidth,
|
|
50531
|
-
maxHeight: flexItem.mainSize
|
|
50532
|
-
});
|
|
50533
|
-
children.push(childBox);
|
|
50534
|
-
}
|
|
50535
|
-
const totalHeight = flexResult.mainSizeUsed;
|
|
50536
|
-
return {
|
|
50537
|
-
x,
|
|
50538
|
-
y,
|
|
50539
|
-
width: constraints.maxWidth,
|
|
50540
|
-
height: totalHeight + padding.top + padding.bottom,
|
|
50541
|
-
node,
|
|
50542
|
-
children,
|
|
50543
|
-
padding
|
|
50544
|
-
};
|
|
50545
|
-
}
|
|
50546
|
-
rowContainsSidebarOrMain(row) {
|
|
50547
|
-
return row.children.some(
|
|
50548
|
-
(child) => child.type === "Sidebar" || child.type === "Main"
|
|
50549
|
-
);
|
|
50550
|
-
}
|
|
50551
|
-
layoutHeader(node, x, y, constraints) {
|
|
50552
|
-
const padding = this.getPadding(node);
|
|
50553
|
-
const height = this.resolveSize(node.h) || 56;
|
|
50554
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50555
|
-
const children = [];
|
|
50556
|
-
let currentY = y + padding.top;
|
|
50557
|
-
for (const child of node.children) {
|
|
50558
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50559
|
-
...constraints,
|
|
50560
|
-
maxWidth: innerWidth,
|
|
50561
|
-
maxHeight: void 0,
|
|
50562
|
-
// Children use natural height
|
|
50563
|
-
inHeader: true
|
|
50564
|
-
// Pass header context for child sizing (e.g., smaller avatars)
|
|
50565
|
-
});
|
|
50566
|
-
const verticalOffset = (height - childBox.height) / 2;
|
|
50567
|
-
childBox.y = y + padding.top + verticalOffset;
|
|
50568
|
-
this.adjustChildrenY(childBox, verticalOffset);
|
|
50569
|
-
children.push(childBox);
|
|
50570
|
-
currentY += childBox.height;
|
|
50571
|
-
}
|
|
50572
|
-
return {
|
|
50573
|
-
x,
|
|
50574
|
-
y,
|
|
50575
|
-
width: constraints.maxWidth,
|
|
50576
|
-
height: height + padding.top + padding.bottom,
|
|
50577
|
-
node,
|
|
50578
|
-
children,
|
|
50579
|
-
padding
|
|
50580
|
-
};
|
|
50581
|
-
}
|
|
50582
|
-
adjustChildrenY(box, offset) {
|
|
50583
|
-
for (const child of box.children) {
|
|
50584
|
-
child.y += offset;
|
|
50585
|
-
this.adjustChildrenY(child, offset);
|
|
50586
|
-
}
|
|
50587
|
-
}
|
|
50588
|
-
/**
|
|
50589
|
-
* Check if a node should flex to fill available space in a Row
|
|
50590
|
-
* Only layout containers without explicit width should flex
|
|
50591
|
-
*/
|
|
50592
|
-
isFlexContainer(node) {
|
|
50593
|
-
if (node.type === "Main") return true;
|
|
50594
|
-
if (node.type === "Col" && !("w" in node && node.w !== void 0)) return true;
|
|
50595
|
-
return false;
|
|
50596
|
-
}
|
|
50597
|
-
layoutFooter(node, x, y, constraints) {
|
|
50598
|
-
const padding = this.getPadding(node);
|
|
50599
|
-
const height = this.resolveSize(node.h) || 60;
|
|
50600
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50601
|
-
const children = [];
|
|
50602
|
-
let currentY = y + padding.top;
|
|
50603
|
-
for (const child of node.children) {
|
|
50604
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50605
|
-
...constraints,
|
|
50606
|
-
maxWidth: innerWidth,
|
|
50607
|
-
maxHeight: void 0
|
|
50608
|
-
// Children use natural height
|
|
50609
|
-
});
|
|
50610
|
-
const verticalOffset = (height - childBox.height) / 2;
|
|
50611
|
-
childBox.y = y + padding.top + verticalOffset;
|
|
50612
|
-
this.adjustChildrenY(childBox, verticalOffset);
|
|
50613
|
-
children.push(childBox);
|
|
50614
|
-
currentY += childBox.height;
|
|
50615
|
-
}
|
|
50616
|
-
return {
|
|
50617
|
-
x,
|
|
50618
|
-
y,
|
|
50619
|
-
width: constraints.maxWidth,
|
|
50620
|
-
height: height + padding.top + padding.bottom,
|
|
50621
|
-
node,
|
|
50622
|
-
children,
|
|
50623
|
-
padding
|
|
50624
|
-
};
|
|
50625
|
-
}
|
|
50626
|
-
layoutMain(node, x, y, constraints) {
|
|
50627
|
-
const padding = this.getPadding(node);
|
|
50628
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50629
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50630
|
-
const childMeasurements = node.children.map(
|
|
50631
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50632
|
-
);
|
|
50633
|
-
const children = [];
|
|
50634
|
-
let currentY = y + padding.top;
|
|
50635
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50636
|
-
const child = node.children[i];
|
|
50637
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50638
|
-
...constraints,
|
|
50639
|
-
maxWidth: innerWidth
|
|
50640
|
-
});
|
|
50641
|
-
children.push(childBox);
|
|
50642
|
-
currentY += childBox.height + gap;
|
|
50643
|
-
}
|
|
50644
|
-
const totalHeight = childMeasurements.reduce(
|
|
50645
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50646
|
-
0
|
|
50647
|
-
);
|
|
50648
|
-
return {
|
|
50649
|
-
x,
|
|
50650
|
-
y,
|
|
50651
|
-
width: constraints.maxWidth,
|
|
50652
|
-
height: totalHeight + padding.top + padding.bottom,
|
|
50653
|
-
node,
|
|
50654
|
-
children,
|
|
50655
|
-
padding
|
|
50656
|
-
};
|
|
50657
|
-
}
|
|
50658
|
-
layoutSidebar(node, x, y, constraints) {
|
|
50659
|
-
const width = this.resolveSize(node.w) || 200;
|
|
50660
|
-
const padding = this.getPadding(node);
|
|
50661
|
-
const gap = this.getGap(node) ?? 8;
|
|
50662
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50663
|
-
const children = [];
|
|
50664
|
-
let currentY = y + padding.top;
|
|
50665
|
-
for (const child of node.children) {
|
|
50666
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50667
|
-
...constraints,
|
|
50668
|
-
maxWidth: innerWidth
|
|
50669
|
-
});
|
|
50670
|
-
children.push(childBox);
|
|
50671
|
-
currentY += childBox.height + gap;
|
|
50672
|
-
}
|
|
50673
|
-
const contentHeight = currentY - y - padding.top - gap + padding.bottom;
|
|
50674
|
-
const height = constraints.maxHeight || Math.max(contentHeight, 200);
|
|
50675
|
-
return {
|
|
50676
|
-
x,
|
|
50677
|
-
y,
|
|
50678
|
-
width,
|
|
50679
|
-
height,
|
|
50680
|
-
node,
|
|
50681
|
-
children,
|
|
50682
|
-
padding
|
|
50683
|
-
};
|
|
50684
|
-
}
|
|
50685
|
-
layoutCard(node, x, y, constraints) {
|
|
50686
|
-
let cardWidth = this.resolveSize(node.w);
|
|
50687
|
-
if (!cardWidth) {
|
|
50688
|
-
cardWidth = Math.min(360, constraints.maxWidth);
|
|
50689
|
-
}
|
|
50690
|
-
const padding = this.getPadding(node);
|
|
50691
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50692
|
-
const innerWidth = cardWidth - padding.left - padding.right;
|
|
50693
|
-
const children = [];
|
|
50694
|
-
let currentY = y + padding.top;
|
|
50695
|
-
if (node.title) {
|
|
50696
|
-
currentY += 28;
|
|
50697
|
-
}
|
|
50698
|
-
for (const child of node.children) {
|
|
50699
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50700
|
-
...constraints,
|
|
50701
|
-
maxWidth: innerWidth
|
|
50702
|
-
});
|
|
50703
|
-
children.push(childBox);
|
|
50704
|
-
currentY += childBox.height + gap;
|
|
50705
|
-
}
|
|
50706
|
-
const totalHeight = currentY - y - gap + padding.bottom;
|
|
50707
|
-
return {
|
|
50708
|
-
x,
|
|
50709
|
-
y,
|
|
50710
|
-
width: cardWidth,
|
|
50711
|
-
height: totalHeight,
|
|
50712
|
-
node,
|
|
50713
|
-
children,
|
|
50714
|
-
padding
|
|
50715
|
-
};
|
|
50716
|
-
}
|
|
50717
|
-
// ===========================================
|
|
50718
|
-
// Render Phase
|
|
50719
|
-
// ===========================================
|
|
50720
|
-
renderBox(box) {
|
|
50721
|
-
if (!box.node) return "";
|
|
50722
|
-
switch (box.node.type) {
|
|
50723
|
-
case "Row":
|
|
50724
|
-
return this.renderRowBox(box);
|
|
50725
|
-
case "Col":
|
|
50726
|
-
return this.renderColBox(box);
|
|
50727
|
-
case "Header":
|
|
50728
|
-
return this.renderHeaderBox(box);
|
|
50729
|
-
case "Footer":
|
|
50730
|
-
return this.renderFooterBox(box);
|
|
50731
|
-
case "Main":
|
|
50732
|
-
return this.renderMainBox(box);
|
|
50733
|
-
case "Sidebar":
|
|
50734
|
-
return this.renderSidebarBox(box);
|
|
50735
|
-
case "Card":
|
|
50736
|
-
return this.renderCardBox(box);
|
|
50737
|
-
case "Modal":
|
|
50738
|
-
return this.renderModalBox(box);
|
|
50739
|
-
case "Title":
|
|
50740
|
-
return this.renderTitleBox(box);
|
|
50741
|
-
case "Text":
|
|
50742
|
-
return this.renderTextBox(box);
|
|
50743
|
-
case "Button":
|
|
50744
|
-
return this.renderButtonBox(box);
|
|
50745
|
-
case "Input":
|
|
50746
|
-
return this.renderInputBox(box);
|
|
50747
|
-
case "Textarea":
|
|
50748
|
-
return this.renderTextareaBox(box);
|
|
50749
|
-
case "Select":
|
|
50750
|
-
return this.renderSelectBox(box);
|
|
50751
|
-
case "Checkbox":
|
|
50752
|
-
return this.renderCheckboxBox(box);
|
|
50753
|
-
case "Radio":
|
|
50754
|
-
return this.renderRadioBox(box);
|
|
50755
|
-
case "Switch":
|
|
50756
|
-
return this.renderSwitchBox(box);
|
|
50757
|
-
case "Link":
|
|
50758
|
-
return this.renderLinkBox(box);
|
|
50759
|
-
case "Image":
|
|
50760
|
-
return this.renderImageBox(box);
|
|
50761
|
-
case "Placeholder":
|
|
50762
|
-
return this.renderPlaceholderBox(box);
|
|
50763
|
-
case "Avatar":
|
|
50764
|
-
return this.renderAvatarBox(box);
|
|
50765
|
-
case "Badge":
|
|
50766
|
-
return this.renderBadgeBox(box);
|
|
50767
|
-
case "Table":
|
|
50768
|
-
return this.renderTableBox(box);
|
|
50769
|
-
case "List":
|
|
50770
|
-
return this.renderListBox(box);
|
|
50771
|
-
case "Alert":
|
|
50772
|
-
return this.renderAlertBox(box);
|
|
50773
|
-
case "Progress":
|
|
50774
|
-
return this.renderProgressBox(box);
|
|
50775
|
-
case "Spinner":
|
|
50776
|
-
return this.renderSpinnerBox(box);
|
|
50777
|
-
case "Nav":
|
|
50778
|
-
return this.renderNavBox(box);
|
|
50779
|
-
case "Tabs":
|
|
50780
|
-
return this.renderTabsBox(box);
|
|
50781
|
-
case "Breadcrumb":
|
|
50782
|
-
return this.renderBreadcrumbBox(box);
|
|
50783
|
-
case "Icon":
|
|
50784
|
-
return this.renderIconBox(box);
|
|
50785
|
-
case "Divider":
|
|
50786
|
-
return this.renderDividerBox(box);
|
|
50787
|
-
default:
|
|
50788
|
-
return `<!-- Unsupported: ${box.node.type} -->`;
|
|
50789
|
-
}
|
|
50790
|
-
}
|
|
50791
|
-
renderRowBox(box) {
|
|
50792
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50793
|
-
return childrenSvg;
|
|
50794
|
-
}
|
|
50795
|
-
renderColBox(box) {
|
|
50796
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50797
|
-
return childrenSvg;
|
|
50798
|
-
}
|
|
50799
|
-
renderHeaderBox(box) {
|
|
50800
|
-
const node = box.node;
|
|
50801
|
-
const hasBorder = node.border !== false;
|
|
50802
|
-
let svg = `<g>
|
|
50803
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}"/>`;
|
|
50804
|
-
if (hasBorder) {
|
|
50805
|
-
svg += `<line x1="${box.x}" y1="${box.y + box.height}" x2="${box.x + box.width}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50806
|
-
}
|
|
50807
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50808
|
-
svg += `</g>`;
|
|
50809
|
-
return svg;
|
|
50810
|
-
}
|
|
50811
|
-
renderFooterBox(box) {
|
|
50812
|
-
const node = box.node;
|
|
50813
|
-
const hasBorder = node.border !== false;
|
|
50814
|
-
let svg = `<g>
|
|
50815
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}"`;
|
|
50816
|
-
if (hasBorder) {
|
|
50817
|
-
svg += ` stroke="${this.theme.colors.border}" stroke-width="1"`;
|
|
50818
|
-
}
|
|
50819
|
-
svg += `/>`;
|
|
50820
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50821
|
-
svg += `</g>`;
|
|
50822
|
-
return svg;
|
|
50823
|
-
}
|
|
50824
|
-
renderMainBox(box) {
|
|
50825
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50826
|
-
return childrenSvg;
|
|
50827
|
-
}
|
|
50828
|
-
renderSidebarBox(box) {
|
|
50829
|
-
let svg = `<g>
|
|
50830
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50831
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50832
|
-
svg += `</g>`;
|
|
50833
|
-
return svg;
|
|
50834
|
-
}
|
|
50835
|
-
renderCardBox(box) {
|
|
50836
|
-
const node = box.node;
|
|
50837
|
-
const shadowAttr = node.shadow ? 'filter="url(#shadow)"' : "";
|
|
50838
|
-
let svg = `<g>
|
|
50839
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1" ${shadowAttr}/>`;
|
|
50840
|
-
if (node.title) {
|
|
50841
|
-
const padding = this.getPadding(node);
|
|
50842
|
-
svg += `<text x="${box.x + padding.left}" y="${box.y + padding.top + 18}" font-size="16" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
50843
|
-
}
|
|
50844
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50845
|
-
svg += `</g>`;
|
|
50846
|
-
return svg;
|
|
50847
|
-
}
|
|
50848
|
-
renderModalBox(box) {
|
|
50849
|
-
const node = box.node;
|
|
50850
|
-
const modalX = (this.pageWidth - box.width) / 2;
|
|
50851
|
-
const modalY = (this.pageHeight - box.height) / 2;
|
|
50852
|
-
let svg = `<g>
|
|
50853
|
-
<rect width="${this.pageWidth}" height="${this.pageHeight}" fill="rgba(0,0,0,0.5)"/>
|
|
50854
|
-
<rect x="${modalX}" y="${modalY}" width="${box.width}" height="${box.height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50855
|
-
if (node.title) {
|
|
50856
|
-
svg += `<text x="${modalX + 20}" y="${modalY + 30}" font-size="18" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
50857
|
-
}
|
|
50858
|
-
for (const child of box.children) {
|
|
50859
|
-
const adjustedChild = { ...child, x: modalX + (child.x - box.x), y: modalY + (child.y - box.y) };
|
|
50860
|
-
svg += this.renderBox(adjustedChild);
|
|
50861
|
-
}
|
|
50862
|
-
svg += `</g>`;
|
|
50863
|
-
return svg;
|
|
50864
|
-
}
|
|
50865
|
-
renderTitleBox(box) {
|
|
50866
|
-
const node = box.node;
|
|
50867
|
-
const level = node.level || 1;
|
|
50868
|
-
const fontSize = this.getTitleFontSize(level);
|
|
50869
|
-
const textY = box.y + fontSize;
|
|
50870
|
-
let textX = box.x;
|
|
50871
|
-
let anchor = "start";
|
|
50872
|
-
if (node.align === "center") {
|
|
50873
|
-
textX = box.x + box.width / 2;
|
|
50874
|
-
anchor = "middle";
|
|
50875
|
-
} else if (node.align === "right") {
|
|
50876
|
-
textX = box.x + box.width;
|
|
50877
|
-
anchor = "end";
|
|
50878
|
-
}
|
|
50879
|
-
return `<text x="${textX}" y="${textY}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}" text-anchor="${anchor}">${this.escapeXml(node.content)}</text>`;
|
|
50880
|
-
}
|
|
50881
|
-
renderTextBox(box) {
|
|
50882
|
-
const node = box.node;
|
|
50883
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
50884
|
-
const fill = node.muted ? this.theme.colors.muted : this.theme.colors.foreground;
|
|
50885
|
-
const fontWeight = node.weight || "normal";
|
|
50886
|
-
const textY = box.y + fontSize;
|
|
50887
|
-
let textX = box.x;
|
|
50888
|
-
let anchor = "start";
|
|
50889
|
-
if (node.align === "center") {
|
|
50890
|
-
textX = box.x + box.width / 2;
|
|
50891
|
-
anchor = "middle";
|
|
50892
|
-
} else if (node.align === "right") {
|
|
50893
|
-
textX = box.x + box.width;
|
|
50894
|
-
anchor = "end";
|
|
50895
|
-
}
|
|
50896
|
-
return `<text x="${textX}" y="${textY}" font-size="${fontSize}" font-weight="${fontWeight}" fill="${fill}" text-anchor="${anchor}">${this.escapeXml(node.content)}</text>`;
|
|
50897
|
-
}
|
|
50898
|
-
renderButtonBox(box) {
|
|
50899
|
-
const node = box.node;
|
|
50900
|
-
const hasIcon = !!node.icon;
|
|
50901
|
-
const isIconOnly = hasIcon && !node.content.trim();
|
|
50902
|
-
let fill = this.theme.colors.primary;
|
|
50903
|
-
let textFill = "#ffffff";
|
|
50904
|
-
let strokeAttr = "";
|
|
50905
|
-
if (node.secondary) {
|
|
50906
|
-
fill = this.theme.colors.secondary;
|
|
50907
|
-
} else if (node.outline) {
|
|
50908
|
-
fill = "white";
|
|
50909
|
-
textFill = this.theme.colors.foreground;
|
|
50910
|
-
strokeAttr = `stroke="${this.theme.colors.border}" stroke-width="1"`;
|
|
50911
|
-
} else if (node.ghost) {
|
|
50912
|
-
fill = "transparent";
|
|
50913
|
-
textFill = this.theme.colors.foreground;
|
|
50914
|
-
}
|
|
50915
|
-
let svg = `<g>
|
|
50916
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="${fill}" ${strokeAttr}/>`;
|
|
50917
|
-
if (hasIcon) {
|
|
50918
|
-
const iconData = getIconData(node.icon);
|
|
50919
|
-
if (iconData) {
|
|
50920
|
-
const iconSize = 16;
|
|
50921
|
-
const iconX = isIconOnly ? box.x + (box.width - iconSize) / 2 : box.x + 16;
|
|
50922
|
-
const iconY = box.y + (box.height - iconSize) / 2;
|
|
50923
|
-
svg += this.renderIconPaths(iconData, iconX, iconY, iconSize, textFill);
|
|
50924
|
-
}
|
|
50925
|
-
}
|
|
50926
|
-
if (!isIconOnly) {
|
|
50927
|
-
const textX = hasIcon ? box.x + 36 + (box.width - 52) / 2 : box.x + box.width / 2;
|
|
50928
|
-
svg += `<text x="${textX}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${textFill}" text-anchor="middle">${this.escapeXml(node.content)}</text>`;
|
|
50929
|
-
}
|
|
50930
|
-
svg += `</g>`;
|
|
50931
|
-
return svg;
|
|
50932
|
-
}
|
|
50933
|
-
renderInputBox(box) {
|
|
50934
|
-
const node = box.node;
|
|
50935
|
-
let y = box.y;
|
|
50936
|
-
let svg = "<g>";
|
|
50937
|
-
if (node.label) {
|
|
50938
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50939
|
-
y += 24;
|
|
50940
|
-
}
|
|
50941
|
-
const inputHeight = 36;
|
|
50942
|
-
const placeholder = node.placeholder || "";
|
|
50943
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${inputHeight}" rx="4" fill="#f4f4f5"/>`;
|
|
50944
|
-
svg += `<text x="${box.x + 12}" y="${y + inputHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50945
|
-
svg += "</g>";
|
|
50946
|
-
return svg;
|
|
50947
|
-
}
|
|
50948
|
-
renderTextareaBox(box) {
|
|
50949
|
-
const node = box.node;
|
|
50950
|
-
let y = box.y;
|
|
50951
|
-
let svg = "<g>";
|
|
50952
|
-
if (node.label) {
|
|
50953
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50954
|
-
y += 24;
|
|
50955
|
-
}
|
|
50956
|
-
const textareaHeight = box.height - (node.label ? 24 : 0);
|
|
50957
|
-
const placeholder = node.placeholder || "";
|
|
50958
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${textareaHeight}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50959
|
-
svg += `<text x="${box.x + 12}" y="${y + 24}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50960
|
-
svg += "</g>";
|
|
50961
|
-
return svg;
|
|
50962
|
-
}
|
|
50963
|
-
renderSelectBox(box) {
|
|
50964
|
-
const node = box.node;
|
|
50965
|
-
let y = box.y;
|
|
50966
|
-
let svg = "<g>";
|
|
50967
|
-
if (node.label) {
|
|
50968
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50969
|
-
y += 24;
|
|
50970
|
-
}
|
|
50971
|
-
const selectHeight = 40;
|
|
50972
|
-
const placeholder = node.placeholder || "Select...";
|
|
50973
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${selectHeight}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50974
|
-
svg += `<text x="${box.x + 12}" y="${y + selectHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50975
|
-
svg += `<path d="M${box.x + box.width - 24} ${y + selectHeight / 2 - 3} l6 6 l6 -6" fill="none" stroke="${this.theme.colors.muted}" stroke-width="1.5"/>`;
|
|
50976
|
-
svg += "</g>";
|
|
50977
|
-
return svg;
|
|
50978
|
-
}
|
|
50979
|
-
renderCheckboxBox(box) {
|
|
50980
|
-
const node = box.node;
|
|
50981
|
-
const size = 18;
|
|
50982
|
-
let svg = `<g>
|
|
50983
|
-
<rect x="${box.x}" y="${box.y}" width="${size}" height="${size}" rx="3" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50984
|
-
if (node.checked) {
|
|
50985
|
-
svg += `<path d="M${box.x + 4} ${box.y + 9} L${box.x + 7} ${box.y + 12} L${box.x + 14} ${box.y + 5}" fill="none" stroke="${this.theme.colors.foreground}" stroke-width="2"/>`;
|
|
50986
|
-
}
|
|
50987
|
-
if (node.label) {
|
|
50988
|
-
svg += `<text x="${box.x + size + 8}" y="${box.y + size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50989
|
-
}
|
|
50990
|
-
svg += "</g>";
|
|
50991
|
-
return svg;
|
|
50992
|
-
}
|
|
50993
|
-
renderRadioBox(box) {
|
|
50994
|
-
const node = box.node;
|
|
50995
|
-
const size = 18;
|
|
50996
|
-
const radius = size / 2;
|
|
50997
|
-
const cx = box.x + radius;
|
|
50998
|
-
const cy = box.y + radius;
|
|
50999
|
-
let svg = `<g>
|
|
51000
|
-
<circle cx="${cx}" cy="${cy}" r="${radius - 1}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51001
|
-
if (node.checked) {
|
|
51002
|
-
svg += `<circle cx="${cx}" cy="${cy}" r="${radius - 5}" fill="${this.theme.colors.foreground}"/>`;
|
|
51003
|
-
}
|
|
51004
|
-
if (node.label) {
|
|
51005
|
-
svg += `<text x="${box.x + size + 8}" y="${box.y + size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
51006
|
-
}
|
|
51007
|
-
svg += "</g>";
|
|
51008
|
-
return svg;
|
|
51009
|
-
}
|
|
51010
|
-
renderSwitchBox(box) {
|
|
51011
|
-
const node = box.node;
|
|
51012
|
-
const width = 44;
|
|
51013
|
-
const height = 24;
|
|
51014
|
-
const radius = height / 2;
|
|
51015
|
-
const isOn = node.checked;
|
|
51016
|
-
const bgColor = isOn ? this.theme.colors.primary : this.theme.colors.border;
|
|
51017
|
-
const knobX = isOn ? box.x + width - radius : box.x + radius;
|
|
51018
|
-
let svg = `<g>
|
|
51019
|
-
<rect x="${box.x}" y="${box.y}" width="${width}" height="${height}" rx="${radius}" fill="${bgColor}"/>
|
|
51020
|
-
<circle cx="${knobX}" cy="${box.y + radius}" r="${radius - 3}" fill="white"/>`;
|
|
51021
|
-
if (node.label) {
|
|
51022
|
-
svg += `<text x="${box.x + width + 8}" y="${box.y + height - 6}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
51023
|
-
}
|
|
51024
|
-
svg += "</g>";
|
|
51025
|
-
return svg;
|
|
51026
|
-
}
|
|
51027
|
-
renderLinkBox(box) {
|
|
51028
|
-
const node = box.node;
|
|
51029
|
-
const fontSize = 14;
|
|
51030
|
-
const textY = box.y + fontSize;
|
|
51031
|
-
return `<text x="${box.x}" y="${textY}" font-size="${fontSize}" fill="${this.theme.colors.primary}" text-decoration="underline">${this.escapeXml(node.content)}</text>`;
|
|
51032
|
-
}
|
|
51033
|
-
renderImageBox(box) {
|
|
51034
|
-
const node = box.node;
|
|
51035
|
-
return `<g>
|
|
51036
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51037
|
-
<line x1="${box.x}" y1="${box.y}" x2="${box.x + box.width}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51038
|
-
<line x1="${box.x + box.width}" y1="${box.y}" x2="${box.x}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51039
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.alt || "Image")}</text>
|
|
51040
|
-
</g>`;
|
|
51041
|
-
}
|
|
51042
|
-
renderPlaceholderBox(box) {
|
|
51043
|
-
const node = box.node;
|
|
51044
|
-
const patternId = `placeholder-pattern-${this.clipPathCounter++}`;
|
|
51045
|
-
const patternDef = `<pattern id="${patternId}" width="14" height="14" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
|
|
51046
|
-
<rect width="14" height="14" fill="#f9f9f9"/>
|
|
51047
|
-
<rect width="7" height="14" fill="rgba(0,0,0,0.03)"/>
|
|
51048
|
-
</pattern>`;
|
|
51049
|
-
this.clipPathDefs.push(patternDef);
|
|
51050
|
-
return `<g>
|
|
51051
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="url(#${patternId})" stroke="${this.theme.colors.muted}" stroke-width="1" stroke-dasharray="4,2"/>
|
|
51052
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}" text-anchor="middle">${this.escapeXml(node.label || "Placeholder")}</text>
|
|
51053
|
-
</g>`;
|
|
51054
|
-
}
|
|
51055
|
-
renderAvatarBox(box) {
|
|
51056
|
-
const node = box.node;
|
|
51057
|
-
const radius = box.width / 2;
|
|
51058
|
-
const cx = box.x + radius;
|
|
51059
|
-
const cy = box.y + radius;
|
|
51060
|
-
const initial = node.name ? node.name.charAt(0).toUpperCase() : "?";
|
|
51061
|
-
return `<g>
|
|
51062
|
-
<circle cx="${cx}" cy="${cy}" r="${radius}" fill="${this.theme.colors.foreground}"/>
|
|
51063
|
-
<text x="${cx}" y="${cy + 5}" font-size="${box.width / 2.5}" fill="${this.theme.colors.background}" text-anchor="middle">${initial}</text>
|
|
51064
|
-
</g>`;
|
|
51065
|
-
}
|
|
51066
|
-
renderBadgeBox(box) {
|
|
51067
|
-
const node = box.node;
|
|
51068
|
-
return `<g>
|
|
51069
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="11" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51070
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 4}" font-size="12" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.content)}</text>
|
|
51071
|
-
</g>`;
|
|
51072
|
-
}
|
|
51073
|
-
renderTableBox(box) {
|
|
51074
|
-
const node = box.node;
|
|
51075
|
-
const columns = node.columns || [];
|
|
51076
|
-
const rows = node.rows || [];
|
|
51077
|
-
const rowCount = rows.length || 3;
|
|
51078
|
-
const colWidth = 120;
|
|
51079
|
-
const rowHeight = 40;
|
|
51080
|
-
let svg = `<g>`;
|
|
51081
|
-
svg += `<rect x="${box.x}" y="${box.y}" width="${columns.length * colWidth}" height="${rowHeight}" fill="${this.theme.colors.muted}"/>`;
|
|
51082
|
-
columns.forEach((col, i) => {
|
|
51083
|
-
svg += `<text x="${box.x + i * colWidth + 12}" y="${box.y + rowHeight / 2 + 5}" font-size="14" font-weight="600">${this.escapeXml(col)}</text>`;
|
|
51084
|
-
});
|
|
51085
|
-
const displayRowCount = rows.length > 0 ? rows.length : rowCount;
|
|
51086
|
-
for (let rowIdx = 0; rowIdx < displayRowCount; rowIdx++) {
|
|
51087
|
-
const rowY = box.y + (rowIdx + 1) * rowHeight;
|
|
51088
|
-
svg += `<rect x="${box.x}" y="${rowY}" width="${columns.length * colWidth}" height="${rowHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51089
|
-
columns.forEach((_, colIdx) => {
|
|
51090
|
-
const cellContent = rows[rowIdx] && rows[rowIdx][colIdx] ? String(typeof rows[rowIdx][colIdx] === "object" ? "..." : rows[rowIdx][colIdx]) : "\u2014";
|
|
51091
|
-
svg += `<text x="${box.x + colIdx * colWidth + 12}" y="${rowY + rowHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(cellContent)}</text>`;
|
|
51092
|
-
});
|
|
51093
|
-
}
|
|
51094
|
-
svg += "</g>";
|
|
51095
|
-
return svg;
|
|
51096
|
-
}
|
|
51097
|
-
renderListBox(box) {
|
|
51098
|
-
const node = box.node;
|
|
51099
|
-
const items = node.items || [];
|
|
51100
|
-
const ordered = node.ordered || false;
|
|
51101
|
-
let svg = "<g>";
|
|
51102
|
-
items.forEach((item, idx) => {
|
|
51103
|
-
const marker = ordered ? `${idx + 1}.` : "\u2022";
|
|
51104
|
-
const content = typeof item === "string" ? item : item.content;
|
|
51105
|
-
svg += `<text x="${box.x}" y="${box.y + idx * 28 + 16}" font-size="14" fill="${this.theme.colors.foreground}">${marker} ${this.escapeXml(content)}</text>`;
|
|
51106
|
-
});
|
|
51107
|
-
svg += "</g>";
|
|
51108
|
-
return svg;
|
|
51109
|
-
}
|
|
51110
|
-
renderAlertBox(box) {
|
|
51111
|
-
const node = box.node;
|
|
51112
|
-
return `<g>
|
|
51113
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51114
|
-
<text x="${box.x + 16}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>
|
|
51115
|
-
</g>`;
|
|
51116
|
-
}
|
|
51117
|
-
renderProgressBox(box) {
|
|
51118
|
-
const node = box.node;
|
|
51119
|
-
let y = box.y;
|
|
51120
|
-
let svg = "<g>";
|
|
51121
|
-
if (node.label) {
|
|
51122
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
51123
|
-
y += 24;
|
|
51124
|
-
}
|
|
51125
|
-
const barHeight = 8;
|
|
51126
|
-
const value = node.value || 0;
|
|
51127
|
-
const max = node.max || 100;
|
|
51128
|
-
const percent = Math.min(100, Math.max(0, value / max * 100));
|
|
51129
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${barHeight}" rx="${barHeight / 2}" fill="${this.theme.colors.muted}"/>`;
|
|
51130
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width * percent / 100}" height="${barHeight}" rx="${barHeight / 2}" fill="${this.theme.colors.primary}"/>`;
|
|
51131
|
-
svg += "</g>";
|
|
51132
|
-
return svg;
|
|
51133
|
-
}
|
|
51134
|
-
renderSpinnerBox(box) {
|
|
51135
|
-
const cx = box.x + box.width / 2;
|
|
51136
|
-
const cy = box.y + box.height / 2;
|
|
51137
|
-
const radius = box.width / 2 - 2;
|
|
51138
|
-
return `<g>
|
|
51139
|
-
<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="${this.theme.colors.muted}" stroke-width="2"/>
|
|
51140
|
-
<path d="M${cx},${cy - radius} A${radius},${radius} 0 0,1 ${cx + radius},${cy}" fill="none" stroke="${this.theme.colors.primary}" stroke-width="2" stroke-linecap="round"/>
|
|
51141
|
-
</g>`;
|
|
51142
|
-
}
|
|
51143
|
-
renderNavBox(box) {
|
|
51144
|
-
const node = box.node;
|
|
51145
|
-
const vertical = node.vertical || false;
|
|
51146
|
-
let svg = "<g>";
|
|
51147
|
-
if (node.children && node.children.length > 0) {
|
|
51148
|
-
let offsetY = 0;
|
|
51149
|
-
node.children.forEach((child) => {
|
|
51150
|
-
if (child.type === "divider") {
|
|
51151
|
-
offsetY += 16;
|
|
51152
|
-
svg += `<line x1="${box.x}" y1="${box.y + offsetY}" x2="${box.x + box.width - 32}" y2="${box.y + offsetY}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51153
|
-
offsetY += 8;
|
|
51154
|
-
} else if (child.type === "group") {
|
|
51155
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="11" font-weight="500" fill="${this.theme.colors.muted}" text-transform="uppercase">${this.escapeXml(child.label)}</text>`;
|
|
51156
|
-
offsetY += 28;
|
|
51157
|
-
child.items.forEach((item) => {
|
|
51158
|
-
if (item.type === "divider") {
|
|
51159
|
-
offsetY += 8;
|
|
51160
|
-
svg += `<line x1="${box.x}" y1="${box.y + offsetY}" x2="${box.x + box.width - 32}" y2="${box.y + offsetY}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51161
|
-
offsetY += 8;
|
|
51162
|
-
} else {
|
|
51163
|
-
const fill = item.active ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51164
|
-
const fontWeight = item.active ? 'font-weight="500"' : "";
|
|
51165
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="14" ${fontWeight} fill="${fill}">${this.escapeXml(item.label)}</text>`;
|
|
51166
|
-
offsetY += 32;
|
|
51167
|
-
}
|
|
51168
|
-
});
|
|
51169
|
-
} else if (child.type === "item") {
|
|
51170
|
-
const fill = child.active ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51171
|
-
const fontWeight = child.active ? 'font-weight="500"' : "";
|
|
51172
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="14" ${fontWeight} fill="${fill}">${this.escapeXml(child.label)}</text>`;
|
|
51173
|
-
offsetY += 32;
|
|
51174
|
-
}
|
|
51175
|
-
});
|
|
51176
|
-
svg += "</g>";
|
|
51177
|
-
return svg;
|
|
51178
|
-
}
|
|
51179
|
-
const items = node.items || [];
|
|
51180
|
-
if (vertical) {
|
|
51181
|
-
items.forEach((item, idx) => {
|
|
51182
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51183
|
-
const isActive = typeof item === "object" && item.active;
|
|
51184
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51185
|
-
svg += `<text x="${box.x}" y="${box.y + idx * 32 + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51186
|
-
});
|
|
51187
|
-
} else {
|
|
51188
|
-
let offsetX = 0;
|
|
51189
|
-
items.forEach((item) => {
|
|
51190
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51191
|
-
const isActive = typeof item === "object" && item.active;
|
|
51192
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51193
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51194
|
-
offsetX += this.estimateTextWidth(label, 14) + 24;
|
|
51195
|
-
});
|
|
51196
|
-
}
|
|
51197
|
-
svg += "</g>";
|
|
51198
|
-
return svg;
|
|
51199
|
-
}
|
|
51200
|
-
renderTabsBox(box) {
|
|
51201
|
-
const node = box.node;
|
|
51202
|
-
const items = node.items || [];
|
|
51203
|
-
const tabHeight = 40;
|
|
51204
|
-
let svg = "<g>";
|
|
51205
|
-
let offsetX = 0;
|
|
51206
|
-
items.forEach((item, idx) => {
|
|
51207
|
-
const label = typeof item === "string" ? item : item;
|
|
51208
|
-
const tabWidth = this.estimateTextWidth(label, 14) + 32;
|
|
51209
|
-
const isFirst = idx === 0;
|
|
51210
|
-
svg += `<rect x="${box.x + offsetX}" y="${box.y}" width="${tabWidth}" height="${tabHeight}" fill="${isFirst ? "white" : this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51211
|
-
svg += `<text x="${box.x + offsetX + tabWidth / 2}" y="${box.y + tabHeight / 2 + 5}" font-size="14" text-anchor="middle" fill="${this.theme.colors.foreground}">${this.escapeXml(label)}</text>`;
|
|
51212
|
-
offsetX += tabWidth;
|
|
51213
|
-
});
|
|
51214
|
-
svg += "</g>";
|
|
51215
|
-
return svg;
|
|
51216
|
-
}
|
|
51217
|
-
renderBreadcrumbBox(box) {
|
|
51218
|
-
const node = box.node;
|
|
51219
|
-
const items = node.items || [];
|
|
51220
|
-
const separator = "/";
|
|
51221
|
-
let svg = "<g>";
|
|
51222
|
-
let offsetX = 0;
|
|
51223
|
-
items.forEach((item, idx) => {
|
|
51224
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51225
|
-
const isLast = idx === items.length - 1;
|
|
51226
|
-
const fill = isLast ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51227
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51228
|
-
offsetX += this.estimateTextWidth(label, 14) + 8;
|
|
51229
|
-
if (!isLast) {
|
|
51230
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${this.theme.colors.muted}">${separator}</text>`;
|
|
51231
|
-
offsetX += 16;
|
|
51232
|
-
}
|
|
51233
|
-
});
|
|
51234
|
-
svg += "</g>";
|
|
51235
|
-
return svg;
|
|
51236
|
-
}
|
|
51237
|
-
renderIconBox(box) {
|
|
51238
|
-
const node = box.node;
|
|
51239
|
-
const iconData = getIconData(node.name);
|
|
51240
|
-
if (!iconData) {
|
|
51241
|
-
return `<!-- Icon not found: ${node.name} -->`;
|
|
51242
|
-
}
|
|
51243
|
-
const color = this.theme.colors.foreground;
|
|
51244
|
-
return this.renderIconPaths(iconData, box.x, box.y, box.width, color);
|
|
51245
|
-
}
|
|
51246
|
-
renderDividerBox(box) {
|
|
51247
|
-
return `<line x1="${box.x}" y1="${box.y}" x2="${box.x + box.width}" y2="${box.y}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51248
|
-
}
|
|
51249
|
-
// ===========================================
|
|
51250
|
-
// Utility Methods
|
|
51251
|
-
// ===========================================
|
|
51252
|
-
renderIconPaths(data, x, y, size, color) {
|
|
51253
|
-
const scale = size / 24;
|
|
51254
|
-
const paths = data.map(([tag, attrs]) => {
|
|
51255
|
-
const attrStr = Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(" ");
|
|
51256
|
-
return `<${tag} ${attrStr} />`;
|
|
51257
|
-
}).join("");
|
|
51258
|
-
return `<g transform="translate(${x}, ${y}) scale(${scale})" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths}</g>`;
|
|
51259
|
-
}
|
|
51260
|
-
getPadding(node) {
|
|
51261
|
-
const defaultPadding = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
51262
|
-
if (!("p" in node) && !("px" in node) && !("py" in node)) {
|
|
51263
|
-
if (node.type === "Card" || node.type === "Header" || node.type === "Footer" || node.type === "Sidebar") {
|
|
51264
|
-
return { top: 16, right: 16, bottom: 16, left: 16 };
|
|
51265
|
-
}
|
|
51266
|
-
return defaultPadding;
|
|
51267
|
-
}
|
|
51268
|
-
let p = 0;
|
|
51269
|
-
if ("p" in node && node.p !== void 0) {
|
|
51270
|
-
p = this.resolveSpacing(node.p);
|
|
51271
|
-
}
|
|
51272
|
-
let px = p;
|
|
51273
|
-
let py = p;
|
|
51274
|
-
if ("px" in node && node.px !== void 0) {
|
|
51275
|
-
px = this.resolveSpacing(node.px);
|
|
51276
|
-
}
|
|
51277
|
-
if ("py" in node && node.py !== void 0) {
|
|
51278
|
-
py = this.resolveSpacing(node.py);
|
|
51279
|
-
}
|
|
51280
|
-
if (node.type === "Header") {
|
|
51281
|
-
return { top: 0, right: px, bottom: 0, left: px };
|
|
51282
|
-
}
|
|
51283
|
-
return { top: py, right: px, bottom: py, left: px };
|
|
51284
|
-
}
|
|
51285
|
-
getGap(node) {
|
|
51286
|
-
if ("gap" in node && node.gap !== void 0) {
|
|
51287
|
-
return this.resolveSpacing(node.gap);
|
|
51288
|
-
}
|
|
51289
|
-
return void 0;
|
|
51290
|
-
}
|
|
51291
|
-
resolveSpacing(value) {
|
|
51292
|
-
if (typeof value === "number") {
|
|
51293
|
-
return value * 4;
|
|
51294
|
-
}
|
|
51295
|
-
if (typeof value === "object" && value && "value" in value) {
|
|
51296
|
-
return value.value;
|
|
51297
|
-
}
|
|
51298
|
-
return 0;
|
|
51299
|
-
}
|
|
51300
|
-
resolveSize(value) {
|
|
51301
|
-
if (value === void 0 || value === null) return void 0;
|
|
51302
|
-
if (typeof value === "number") return value;
|
|
51303
|
-
if (typeof value === "string") {
|
|
51304
|
-
if (value === "full") return void 0;
|
|
51305
|
-
const num = parseFloat(value);
|
|
51306
|
-
if (!isNaN(num)) return num;
|
|
51307
|
-
}
|
|
51308
|
-
if (typeof value === "object" && value && "value" in value) {
|
|
51309
|
-
return value.value;
|
|
51310
|
-
}
|
|
51311
|
-
return void 0;
|
|
51312
|
-
}
|
|
51313
|
-
isFullWidth(node) {
|
|
51314
|
-
if ("w" in node) {
|
|
51315
|
-
return node.w === "full";
|
|
51316
|
-
}
|
|
51317
|
-
return false;
|
|
51318
|
-
}
|
|
51319
|
-
estimateTextWidth(text, fontSize) {
|
|
51320
|
-
return text.length * fontSize * 0.6;
|
|
51321
|
-
}
|
|
51322
|
-
resolveFontSize(size) {
|
|
51323
|
-
if (!size) return 16;
|
|
51324
|
-
if (typeof size === "string") {
|
|
51325
|
-
const sizes = {
|
|
51326
|
-
xs: 12,
|
|
51327
|
-
sm: 14,
|
|
51328
|
-
base: 16,
|
|
51329
|
-
md: 16,
|
|
51330
|
-
lg: 18,
|
|
51331
|
-
xl: 20,
|
|
51332
|
-
"2xl": 24,
|
|
51333
|
-
"3xl": 30
|
|
51334
|
-
};
|
|
51335
|
-
return sizes[size] || 16;
|
|
51336
|
-
}
|
|
51337
|
-
if (typeof size === "object" && "value" in size) {
|
|
51338
|
-
if (size.unit === "px") return size.value;
|
|
51339
|
-
if (size.unit === "rem") return size.value * 16;
|
|
51340
|
-
if (size.unit === "em") return size.value * 16;
|
|
51341
|
-
return size.value;
|
|
51342
|
-
}
|
|
51343
|
-
return 16;
|
|
51344
|
-
}
|
|
51345
|
-
getTitleFontSize(level) {
|
|
51346
|
-
const sizes = { 1: 36, 2: 30, 3: 24, 4: 20, 5: 18, 6: 16 };
|
|
51347
|
-
return sizes[level] || 20;
|
|
51348
|
-
}
|
|
51349
|
-
escapeXml(str) {
|
|
51350
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
51351
|
-
}
|
|
51352
|
-
};
|
|
51353
|
-
function createSvgRenderer(options) {
|
|
51354
|
-
return new SvgRenderer(options);
|
|
51355
|
-
}
|
|
51356
|
-
function renderToSvg(doc, options) {
|
|
51357
|
-
const renderer = new SvgRenderer(options);
|
|
51358
|
-
return renderer.render(doc);
|
|
51359
|
-
}
|
|
51360
|
-
|
|
51361
49707
|
// src/renderer/index.ts
|
|
51362
49708
|
function render(document, options = {}) {
|
|
51363
49709
|
const renderer = createHtmlRenderer(options);
|
|
@@ -51394,7 +49740,7 @@ ${html}
|
|
|
51394
49740
|
</body>
|
|
51395
49741
|
</html>`;
|
|
51396
49742
|
}
|
|
51397
|
-
function
|
|
49743
|
+
function renderToSvg(document, options = {}) {
|
|
51398
49744
|
const firstPage = document.children[0];
|
|
51399
49745
|
let width = options.width ?? 800;
|
|
51400
49746
|
let height = options.height ?? 600;
|
|
@@ -51430,15 +49776,10 @@ ${css}
|
|
|
51430
49776
|
</svg>`;
|
|
51431
49777
|
return { svg, width, height };
|
|
51432
49778
|
}
|
|
51433
|
-
function renderToPureSvg(document, options = {}) {
|
|
51434
|
-
return renderToSvg(document, options);
|
|
51435
|
-
}
|
|
51436
49779
|
// Annotate the CommonJS export names for ESM import in node:
|
|
51437
49780
|
0 && (module.exports = {
|
|
51438
49781
|
HtmlRenderer,
|
|
51439
|
-
SvgRenderer,
|
|
51440
49782
|
createHtmlRenderer,
|
|
51441
|
-
createSvgRenderer,
|
|
51442
49783
|
darkTheme,
|
|
51443
49784
|
defaultTheme,
|
|
51444
49785
|
generateComponentStyles,
|
|
@@ -51449,7 +49790,6 @@ function renderToPureSvg(document, options = {}) {
|
|
|
51449
49790
|
render,
|
|
51450
49791
|
renderIconSvg,
|
|
51451
49792
|
renderToHtml,
|
|
51452
|
-
renderToPureSvg,
|
|
51453
49793
|
renderToSvg
|
|
51454
49794
|
});
|
|
51455
49795
|
/**
|