@frontmcp/uipack 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/adapters/content-detector.d.ts.map +1 -1
- package/adapters/index.js +92 -42
- package/adapters/template-renderer.d.ts +11 -1
- package/adapters/template-renderer.d.ts.map +1 -1
- package/component/index.js +13 -10
- package/esm/adapters/index.mjs +92 -42
- package/esm/component/index.mjs +13 -10
- package/esm/index.mjs +96 -40
- package/esm/package.json +2 -2
- package/esm/shell/index.mjs +54 -25
- package/esm/utils/index.mjs +5 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +99 -40
- package/package.json +2 -2
- package/shell/custom-shell-applier.d.ts +7 -6
- package/shell/custom-shell-applier.d.ts.map +1 -1
- package/shell/data-injector.d.ts +5 -0
- package/shell/data-injector.d.ts.map +1 -1
- package/shell/index.d.ts +1 -0
- package/shell/index.d.ts.map +1 -1
- package/shell/index.js +57 -25
- package/shell/trusted-html.d.ts +40 -0
- package/shell/trusted-html.d.ts.map +1 -0
- package/types/ui-config.d.ts +30 -2
- package/types/ui-config.d.ts.map +1 -1
- package/utils/index.d.ts +7 -0
- package/utils/index.d.ts.map +1 -1
- package/utils/index.js +5 -1
package/README.md
CHANGED
|
@@ -125,17 +125,18 @@ const result = await fetcher.fetchBatch({
|
|
|
125
125
|
|
|
126
126
|
### Shell
|
|
127
127
|
|
|
128
|
-
| Export
|
|
129
|
-
|
|
|
130
|
-
| `buildShell(content, config)`
|
|
131
|
-
| `buildCSPMetaTag(config?)`
|
|
132
|
-
| `buildCSPDirectives(config?)`
|
|
133
|
-
| `buildDataInjectionScript(toolName, input?, output?)`
|
|
134
|
-
| `createTemplateHelpers(toolName)`
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
128
|
+
| Export | Type | Purpose |
|
|
129
|
+
| ------------------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------- |
|
|
130
|
+
| `buildShell(content, config)` | function | Main entry point -> `ShellResult` |
|
|
131
|
+
| `buildCSPMetaTag(config?)` | function | Generate `<meta>` CSP tag |
|
|
132
|
+
| `buildCSPDirectives(config?)` | function | Merge custom domains with defaults |
|
|
133
|
+
| `buildDataInjectionScript(toolName, input?, output?)` | function | `<script>` setting `window.__mcp*` globals |
|
|
134
|
+
| `createTemplateHelpers(toolName)` | function | `html`, `trustedHtml`, `escapeHtml`, `formatDate`, `formatCurrency`, `uniqueId`, `jsonEmbed` |
|
|
135
|
+
| `` html`…` ``, `trustedHtml(markup)`, `isTrustedHtml(value)` | function | Build / mark / detect `TrustedHtml` template markup (interpolated values in `html` are escaped) |
|
|
136
|
+
| `resolveShellTemplate(opts)` | function | Resolve custom shell from npm/URL/inline |
|
|
137
|
+
| `applyShellTemplate(template, values)` | function | Apply values to resolved template |
|
|
138
|
+
| `validateShellTemplate(template)` | function | Validate a custom shell template |
|
|
139
|
+
| `DEFAULT_CDN_DOMAINS` | constant | jsDelivr, Cloudflare, Google Fonts |
|
|
139
140
|
|
|
140
141
|
### Component
|
|
141
142
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-detector.d.ts","sourceRoot":"","sources":["../../src/adapters/content-detector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"content-detector.d.ts","sourceRoot":"","sources":["../../src/adapters/content-detector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AA2BzF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAsCrE"}
|
package/adapters/index.js
CHANGED
|
@@ -514,8 +514,9 @@ function escapeHtml(str) {
|
|
|
514
514
|
const s = String(str);
|
|
515
515
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
516
516
|
}
|
|
517
|
-
|
|
518
|
-
|
|
517
|
+
var SCRIPT_UNSAFE_CHARACTERS = /[<>&\u2028\u2029]/g;
|
|
518
|
+
function toUnicodeEscape(character) {
|
|
519
|
+
return `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
519
520
|
}
|
|
520
521
|
function safeJsonForScript(value) {
|
|
521
522
|
if (value === void 0) {
|
|
@@ -531,7 +532,7 @@ function safeJsonForScript(value) {
|
|
|
531
532
|
if (jsonString === void 0) {
|
|
532
533
|
return "null";
|
|
533
534
|
}
|
|
534
|
-
return
|
|
535
|
+
return jsonString.replace(SCRIPT_UNSAFE_CHARACTERS, toUnicodeEscape);
|
|
535
536
|
} catch {
|
|
536
537
|
return '{"error":"Value could not be serialized"}';
|
|
537
538
|
}
|
|
@@ -1828,14 +1829,16 @@ var REQUIRED_PLACEHOLDERS = ["CONTENT"];
|
|
|
1828
1829
|
var OPTIONAL_PLACEHOLDERS = ["CSP", "DATA", "BRIDGE", "TITLE"];
|
|
1829
1830
|
|
|
1830
1831
|
// libs/uipack/src/shell/custom-shell-applier.ts
|
|
1832
|
+
var PLACEHOLDER_PATTERN = new RegExp(`\\{\\{(${SHELL_PLACEHOLDER_NAMES.join("|")})\\}\\}`, "g");
|
|
1833
|
+
var VALUE_KEYS = {
|
|
1834
|
+
CSP: "csp",
|
|
1835
|
+
DATA: "data",
|
|
1836
|
+
BRIDGE: "bridge",
|
|
1837
|
+
CONTENT: "content",
|
|
1838
|
+
TITLE: "title"
|
|
1839
|
+
};
|
|
1831
1840
|
function applyShellTemplate(template, values) {
|
|
1832
|
-
|
|
1833
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.CSP, values.csp);
|
|
1834
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.DATA, values.data);
|
|
1835
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.BRIDGE, values.bridge);
|
|
1836
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.CONTENT, values.content);
|
|
1837
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.TITLE, values.title);
|
|
1838
|
-
return result;
|
|
1841
|
+
return template.replace(PLACEHOLDER_PATTERN, (_token, name) => values[VALUE_KEYS[name]]);
|
|
1839
1842
|
}
|
|
1840
1843
|
|
|
1841
1844
|
// libs/uipack/src/shell/custom-shell-validator.ts
|
|
@@ -1854,6 +1857,29 @@ function validateShellTemplate(template) {
|
|
|
1854
1857
|
};
|
|
1855
1858
|
}
|
|
1856
1859
|
|
|
1860
|
+
// libs/uipack/src/shell/trusted-html.ts
|
|
1861
|
+
var TRUSTED_HTML = /* @__PURE__ */ Symbol.for("@frontmcp/uipack/trusted-html");
|
|
1862
|
+
function trustedHtml(markup) {
|
|
1863
|
+
const value = String(markup);
|
|
1864
|
+
return Object.freeze({ [TRUSTED_HTML]: value, toString: () => value });
|
|
1865
|
+
}
|
|
1866
|
+
function isTrustedHtml(value) {
|
|
1867
|
+
return typeof value === "object" && value !== null && typeof value[TRUSTED_HTML] === "string";
|
|
1868
|
+
}
|
|
1869
|
+
function interpolate(value) {
|
|
1870
|
+
if (isTrustedHtml(value)) return value[TRUSTED_HTML];
|
|
1871
|
+
if (Array.isArray(value)) return value.map(interpolate).join("");
|
|
1872
|
+
if (value === false) return "";
|
|
1873
|
+
return escapeHtml(value);
|
|
1874
|
+
}
|
|
1875
|
+
function html(strings, ...values) {
|
|
1876
|
+
let markup = strings[0];
|
|
1877
|
+
for (let index = 0; index < values.length; index++) {
|
|
1878
|
+
markup += interpolate(values[index]) + strings[index + 1];
|
|
1879
|
+
}
|
|
1880
|
+
return trustedHtml(markup);
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1857
1883
|
// libs/uipack/src/shell/data-injector.ts
|
|
1858
1884
|
function hasSizing(sizing) {
|
|
1859
1885
|
if (!sizing) return false;
|
|
@@ -1907,9 +1933,9 @@ function createTemplateHelpers() {
|
|
|
1907
1933
|
uniqueId: (prefix = "mcp") => {
|
|
1908
1934
|
return `${prefix}-${++_uniqueIdCounter}`;
|
|
1909
1935
|
},
|
|
1910
|
-
jsonEmbed: (data) =>
|
|
1911
|
-
|
|
1912
|
-
|
|
1936
|
+
jsonEmbed: (data) => safeJsonForScript(data),
|
|
1937
|
+
html,
|
|
1938
|
+
trustedHtml
|
|
1913
1939
|
};
|
|
1914
1940
|
}
|
|
1915
1941
|
|
|
@@ -1987,12 +2013,12 @@ function buildShell(content, config) {
|
|
|
1987
2013
|
sizing
|
|
1988
2014
|
});
|
|
1989
2015
|
if (!withShell) {
|
|
1990
|
-
const
|
|
2016
|
+
const html3 = `${dataScript}
|
|
1991
2017
|
${content}`;
|
|
1992
2018
|
return {
|
|
1993
|
-
html:
|
|
1994
|
-
hash: simpleHash(
|
|
1995
|
-
size: Buffer.byteLength(
|
|
2019
|
+
html: html3,
|
|
2020
|
+
hash: simpleHash(html3),
|
|
2021
|
+
size: Buffer.byteLength(html3, "utf-8")
|
|
1996
2022
|
};
|
|
1997
2023
|
}
|
|
1998
2024
|
if (customShell) {
|
|
@@ -2025,7 +2051,7 @@ ${content}`;
|
|
|
2025
2051
|
const bridgeScript = generateBridgeIIFE({ minify: true });
|
|
2026
2052
|
headParts.push(`<script>${bridgeScript}</script>`);
|
|
2027
2053
|
}
|
|
2028
|
-
const
|
|
2054
|
+
const html2 = `<!DOCTYPE html>
|
|
2029
2055
|
<html lang="en">
|
|
2030
2056
|
<head>
|
|
2031
2057
|
${headParts.map((p) => ` ${p}`).join("\n")}
|
|
@@ -2035,9 +2061,9 @@ ${content}
|
|
|
2035
2061
|
</body>
|
|
2036
2062
|
</html>`;
|
|
2037
2063
|
return {
|
|
2038
|
-
html,
|
|
2039
|
-
hash: simpleHash(
|
|
2040
|
-
size: Buffer.byteLength(
|
|
2064
|
+
html: html2,
|
|
2065
|
+
hash: simpleHash(html2),
|
|
2066
|
+
size: Buffer.byteLength(html2, "utf-8")
|
|
2041
2067
|
};
|
|
2042
2068
|
}
|
|
2043
2069
|
function buildCustomShell(content, customShell, ctx) {
|
|
@@ -2070,7 +2096,7 @@ ${sizingStyle}` : dataScript;
|
|
|
2070
2096
|
const bridgeScript = generateBridgeIIFE({ minify: true });
|
|
2071
2097
|
bridgeHtml = `<script>${bridgeScript}</script>`;
|
|
2072
2098
|
}
|
|
2073
|
-
const
|
|
2099
|
+
const html2 = applyShellTemplate(template, {
|
|
2074
2100
|
csp: cspTag,
|
|
2075
2101
|
data: dataWithSizing,
|
|
2076
2102
|
bridge: bridgeHtml,
|
|
@@ -2078,9 +2104,9 @@ ${sizingStyle}` : dataScript;
|
|
|
2078
2104
|
title: ctx.title ? escapeHtmlForTag(ctx.title) : ""
|
|
2079
2105
|
});
|
|
2080
2106
|
return {
|
|
2081
|
-
html,
|
|
2082
|
-
hash: simpleHash(
|
|
2083
|
-
size: Buffer.byteLength(
|
|
2107
|
+
html: html2,
|
|
2108
|
+
hash: simpleHash(html2),
|
|
2109
|
+
size: Buffer.byteLength(html2, "utf-8")
|
|
2084
2110
|
};
|
|
2085
2111
|
}
|
|
2086
2112
|
function simpleHash(str) {
|
|
@@ -2377,10 +2403,10 @@ function resolveFileSource(source, options = {}) {
|
|
|
2377
2403
|
};
|
|
2378
2404
|
}
|
|
2379
2405
|
function resolveFunctionSource(source, input, output) {
|
|
2380
|
-
const
|
|
2406
|
+
const html2 = source(input, output);
|
|
2381
2407
|
return {
|
|
2382
2408
|
mode: "inline",
|
|
2383
|
-
html,
|
|
2409
|
+
html: html2,
|
|
2384
2410
|
exportName: "default",
|
|
2385
2411
|
meta: { mcpAware: false, renderer: "html" },
|
|
2386
2412
|
peerDependencies: []
|
|
@@ -2585,6 +2611,7 @@ var MERMAID_PREFIXES = [
|
|
|
2585
2611
|
"xychart"
|
|
2586
2612
|
];
|
|
2587
2613
|
var PDF_MAGIC = "JVBERi";
|
|
2614
|
+
var BASE64_PATTERN = /^[A-Za-z0-9+/=\r\n]+$/;
|
|
2588
2615
|
function detectContentType(value) {
|
|
2589
2616
|
if (value === null || value === void 0) {
|
|
2590
2617
|
return "text";
|
|
@@ -2599,7 +2626,7 @@ function detectContentType(value) {
|
|
|
2599
2626
|
if (typeof value === "string") {
|
|
2600
2627
|
const trimmed = value.trimStart();
|
|
2601
2628
|
if (trimmed.startsWith(PDF_MAGIC)) {
|
|
2602
|
-
return "pdf";
|
|
2629
|
+
return BASE64_PATTERN.test(trimmed.trimEnd()) ? "pdf" : "text";
|
|
2603
2630
|
}
|
|
2604
2631
|
for (const prefix of MERMAID_PREFIXES) {
|
|
2605
2632
|
if (trimmed.startsWith(prefix)) {
|
|
@@ -2661,7 +2688,7 @@ function buildPdfHtml(base64) {
|
|
|
2661
2688
|
import * as pdfjsLib from 'https://esm.sh/pdfjs-dist@4/build/pdf.min.mjs';
|
|
2662
2689
|
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://esm.sh/pdfjs-dist@4/build/pdf.worker.min.mjs';
|
|
2663
2690
|
|
|
2664
|
-
const base64 = ${
|
|
2691
|
+
const base64 = ${safeJsonForScript(base64)};
|
|
2665
2692
|
const binaryStr = atob(base64);
|
|
2666
2693
|
const bytes = new Uint8Array(binaryStr.length);
|
|
2667
2694
|
for (let i = 0; i < binaryStr.length; i++) bytes[i] = binaryStr.charCodeAt(i);
|
|
@@ -2756,6 +2783,30 @@ function buildCspConfig(resolver) {
|
|
|
2756
2783
|
}
|
|
2757
2784
|
return { resourceDomains: cspResourceDomains, connectDomains: cspConnectDomains };
|
|
2758
2785
|
}
|
|
2786
|
+
var STRING_RESULT_DOCS = "https://docs.agentfront.dev/frontmcp/guides/building-tool-ui#trusted-markup";
|
|
2787
|
+
var noticedStringResultTools = /* @__PURE__ */ new Set();
|
|
2788
|
+
function noticeStringResult(toolName, logger) {
|
|
2789
|
+
if (noticedStringResultTools.has(toolName)) return;
|
|
2790
|
+
noticedStringResultTools.add(toolName);
|
|
2791
|
+
logger.warn(
|
|
2792
|
+
`[frontmcp] The UI template of tool "${toolName}" returned a plain string containing markup, which is rendered as HTML. FrontMCP 1.9 will HTML-escape plain string results by default. Build the markup with ctx.helpers.html\`\u2026\` (interpolated values are escaped) or wrap safe markup with ctx.helpers.trustedHtml(), then set ui.escapeStringResults: true (or escapeStringResults: false to keep the current behaviour without this notice). See ${STRING_RESULT_DOCS}`
|
|
2793
|
+
);
|
|
2794
|
+
}
|
|
2795
|
+
function renderUnwrappedResult(rawResult, options) {
|
|
2796
|
+
if (isTrustedHtml(rawResult)) {
|
|
2797
|
+
return String(rawResult);
|
|
2798
|
+
}
|
|
2799
|
+
if (typeof rawResult !== "string") {
|
|
2800
|
+
return `<pre>${escapeHtml(JSON.stringify(rawResult, null, 2))}</pre>`;
|
|
2801
|
+
}
|
|
2802
|
+
if (detectContentType(rawResult) !== "html" || options.escapeStringResults === true) {
|
|
2803
|
+
return escapeHtml(rawResult);
|
|
2804
|
+
}
|
|
2805
|
+
if (options.escapeStringResults === void 0) {
|
|
2806
|
+
noticeStringResult(options.toolName, options.logger ?? console);
|
|
2807
|
+
}
|
|
2808
|
+
return rawResult;
|
|
2809
|
+
}
|
|
2759
2810
|
function renderToolTemplate(options) {
|
|
2760
2811
|
const { toolName, input, output, template, resolver, platformType, sizing } = options;
|
|
2761
2812
|
const uiType = detectUIType(template);
|
|
@@ -2768,7 +2819,7 @@ function renderToolTemplate(options) {
|
|
|
2768
2819
|
resolver,
|
|
2769
2820
|
sizing
|
|
2770
2821
|
};
|
|
2771
|
-
let
|
|
2822
|
+
let html2;
|
|
2772
2823
|
let hash = "";
|
|
2773
2824
|
let size = 0;
|
|
2774
2825
|
if (typeof template === "object" && template !== null && "file" in template) {
|
|
@@ -2777,44 +2828,43 @@ function renderToolTemplate(options) {
|
|
|
2777
2828
|
{ source: template, inlineReact: resourceMode === "inline" },
|
|
2778
2829
|
{ ...shellConfig, csp: cspConfig }
|
|
2779
2830
|
);
|
|
2780
|
-
|
|
2831
|
+
html2 = result.html;
|
|
2781
2832
|
hash = result.hash;
|
|
2782
2833
|
size = result.size;
|
|
2783
2834
|
} else if (typeof template === "function") {
|
|
2784
2835
|
if (uiType === "react") {
|
|
2785
2836
|
const shellResult = buildShell('<div id="root"></div>', shellConfig);
|
|
2786
|
-
|
|
2837
|
+
html2 = shellResult.html;
|
|
2787
2838
|
hash = shellResult.hash;
|
|
2788
2839
|
size = shellResult.size;
|
|
2789
2840
|
} else {
|
|
2790
2841
|
const helpers = createTemplateHelpers();
|
|
2791
2842
|
const ctx = { input, output, helpers };
|
|
2792
2843
|
const rawResult = template(ctx);
|
|
2793
|
-
const wrapped = wrapDetectedContent(rawResult);
|
|
2844
|
+
const wrapped = isTrustedHtml(rawResult) ? void 0 : wrapDetectedContent(rawResult);
|
|
2794
2845
|
if (wrapped) {
|
|
2795
|
-
|
|
2846
|
+
html2 = wrapped;
|
|
2796
2847
|
} else {
|
|
2797
|
-
const
|
|
2798
|
-
|
|
2799
|
-
html = shellResult.html;
|
|
2848
|
+
const shellResult = buildShell(renderUnwrappedResult(rawResult, options), shellConfig);
|
|
2849
|
+
html2 = shellResult.html;
|
|
2800
2850
|
hash = shellResult.hash;
|
|
2801
2851
|
size = shellResult.size;
|
|
2802
2852
|
}
|
|
2803
2853
|
}
|
|
2804
2854
|
} else if (typeof template === "string") {
|
|
2805
2855
|
const shellResult = buildShell(template, shellConfig);
|
|
2806
|
-
|
|
2856
|
+
html2 = shellResult.html;
|
|
2807
2857
|
hash = shellResult.hash;
|
|
2808
2858
|
size = shellResult.size;
|
|
2809
2859
|
} else {
|
|
2810
2860
|
const shellResult = buildShell('<div id="root"></div>', shellConfig);
|
|
2811
|
-
|
|
2861
|
+
html2 = shellResult.html;
|
|
2812
2862
|
hash = shellResult.hash;
|
|
2813
2863
|
size = shellResult.size;
|
|
2814
2864
|
}
|
|
2815
2865
|
const htmlKey = "ui/html";
|
|
2816
2866
|
const meta = {
|
|
2817
|
-
[htmlKey]:
|
|
2867
|
+
[htmlKey]: html2,
|
|
2818
2868
|
"ui/type": uiType,
|
|
2819
2869
|
"ui/mimeType": MCP_APPS_MIME_TYPE
|
|
2820
2870
|
};
|
|
@@ -2825,10 +2875,10 @@ function renderToolTemplate(options) {
|
|
|
2825
2875
|
if (sizing.aspectRatio !== void 0) meta["ui/aspectRatio"] = sizing.aspectRatio;
|
|
2826
2876
|
}
|
|
2827
2877
|
return {
|
|
2828
|
-
html,
|
|
2878
|
+
html: html2,
|
|
2829
2879
|
uiType,
|
|
2830
2880
|
hash,
|
|
2831
|
-
size: size || Buffer.byteLength(
|
|
2881
|
+
size: size || Buffer.byteLength(html2, "utf8"),
|
|
2832
2882
|
meta
|
|
2833
2883
|
};
|
|
2834
2884
|
}
|
|
@@ -36,6 +36,16 @@ export interface RenderToolTemplateOptions {
|
|
|
36
36
|
* shell, and is mirrored onto the returned `meta` as `ui/preferredHeight` etc.
|
|
37
37
|
*/
|
|
38
38
|
sizing?: WidgetSizing;
|
|
39
|
+
/**
|
|
40
|
+
* HTML-escape a plain string returned by a template function; results built with
|
|
41
|
+
* `html` / `trustedHtml` stay markup. When unset, strings that look like HTML render as
|
|
42
|
+
* markup and a one-time notice per tool is logged; `false` keeps that without the notice.
|
|
43
|
+
*/
|
|
44
|
+
escapeStringResults?: boolean;
|
|
45
|
+
/** Receives the one-time string-result notice. Defaults to `console`. */
|
|
46
|
+
logger?: {
|
|
47
|
+
warn: (message: string) => void;
|
|
48
|
+
};
|
|
39
49
|
}
|
|
40
50
|
/**
|
|
41
51
|
* Result of rendering a tool template.
|
|
@@ -57,7 +67,7 @@ export interface RenderToolTemplateResult {
|
|
|
57
67
|
*
|
|
58
68
|
* Supported template types:
|
|
59
69
|
* - FileSource object `{ file: './widget.tsx' }` — bundled with esbuild, React loaded from esm.sh
|
|
60
|
-
* - HTML template builder function `(ctx) => string`
|
|
70
|
+
* - HTML template builder function `(ctx) => string | TrustedHtml`
|
|
61
71
|
* - Static HTML/MDX string
|
|
62
72
|
*
|
|
63
73
|
* React function references (`template: MyComponent`) are NOT supported for bundling.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAOnD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AA6DD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,CAsG/F"}
|
package/component/index.js
CHANGED
|
@@ -450,8 +450,9 @@ function createEsmShResolver(options = {}) {
|
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
// libs/uipack/src/utils/index.ts
|
|
453
|
-
|
|
454
|
-
|
|
453
|
+
var SCRIPT_UNSAFE_CHARACTERS = /[<>&\u2028\u2029]/g;
|
|
454
|
+
function toUnicodeEscape(character) {
|
|
455
|
+
return `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
455
456
|
}
|
|
456
457
|
function safeJsonForScript(value) {
|
|
457
458
|
if (value === void 0) {
|
|
@@ -467,7 +468,7 @@ function safeJsonForScript(value) {
|
|
|
467
468
|
if (jsonString === void 0) {
|
|
468
469
|
return "null";
|
|
469
470
|
}
|
|
470
|
-
return
|
|
471
|
+
return jsonString.replace(SCRIPT_UNSAFE_CHARACTERS, toUnicodeEscape);
|
|
471
472
|
} catch {
|
|
472
473
|
return '{"error":"Value could not be serialized"}';
|
|
473
474
|
}
|
|
@@ -2070,14 +2071,16 @@ var REQUIRED_PLACEHOLDERS = ["CONTENT"];
|
|
|
2070
2071
|
var OPTIONAL_PLACEHOLDERS = ["CSP", "DATA", "BRIDGE", "TITLE"];
|
|
2071
2072
|
|
|
2072
2073
|
// libs/uipack/src/shell/custom-shell-applier.ts
|
|
2074
|
+
var PLACEHOLDER_PATTERN = new RegExp(`\\{\\{(${SHELL_PLACEHOLDER_NAMES.join("|")})\\}\\}`, "g");
|
|
2075
|
+
var VALUE_KEYS = {
|
|
2076
|
+
CSP: "csp",
|
|
2077
|
+
DATA: "data",
|
|
2078
|
+
BRIDGE: "bridge",
|
|
2079
|
+
CONTENT: "content",
|
|
2080
|
+
TITLE: "title"
|
|
2081
|
+
};
|
|
2073
2082
|
function applyShellTemplate(template, values) {
|
|
2074
|
-
|
|
2075
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.CSP, values.csp);
|
|
2076
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.DATA, values.data);
|
|
2077
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.BRIDGE, values.bridge);
|
|
2078
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.CONTENT, values.content);
|
|
2079
|
-
result = result.replaceAll(SHELL_PLACEHOLDERS.TITLE, values.title);
|
|
2080
|
-
return result;
|
|
2083
|
+
return template.replace(PLACEHOLDER_PATTERN, (_token, name) => values[VALUE_KEYS[name]]);
|
|
2081
2084
|
}
|
|
2082
2085
|
|
|
2083
2086
|
// libs/uipack/src/shell/custom-shell-validator.ts
|