@vielzeug/sandbox 1.2.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/_bridge.cjs +67 -0
- package/dist/_bridge.cjs.map +1 -0
- package/dist/_bridge.d.ts +3 -0
- package/dist/_bridge.d.ts.map +1 -0
- package/dist/_bridge.js +73 -0
- package/dist/_bridge.js.map +1 -0
- package/dist/_document.cjs +21 -0
- package/dist/_document.cjs.map +1 -0
- package/dist/_document.d.ts +6 -0
- package/dist/_document.d.ts.map +1 -0
- package/dist/_document.js +46 -0
- package/dist/_document.js.map +1 -0
- package/dist/_policy.cjs +2 -0
- package/dist/_policy.cjs.map +1 -0
- package/dist/_policy.d.ts +15 -0
- package/dist/_policy.d.ts.map +1 -0
- package/dist/_policy.js +70 -0
- package/dist/_policy.js.map +1 -0
- package/dist/_protocol.cjs +2 -0
- package/dist/_protocol.cjs.map +1 -0
- package/dist/_protocol.d.ts +21 -0
- package/dist/_protocol.d.ts.map +1 -0
- package/dist/_protocol.js +21 -0
- package/dist/_protocol.js.map +1 -0
- package/dist/_runtime.cjs +2 -0
- package/dist/_runtime.cjs.map +1 -0
- package/dist/_runtime.d.ts +3 -0
- package/dist/_runtime.d.ts.map +1 -0
- package/dist/_runtime.js +133 -0
- package/dist/_runtime.js.map +1 -0
- package/dist/_sandbox.cjs +1 -80
- package/dist/_sandbox.cjs.map +1 -1
- package/dist/_sandbox.d.ts +3 -18
- package/dist/_sandbox.d.ts.map +1 -1
- package/dist/_sandbox.js +6 -188
- package/dist/_sandbox.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +3 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/sandbox.cjs +27 -22
- package/dist/sandbox.cjs.map +1 -1
- package/dist/sandbox.iife.js +27 -22
- package/dist/sandbox.iife.js.map +1 -1
- package/dist/sandbox.js +27 -22
- package/dist/sandbox.js.map +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +9 -3
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +5 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,8 +24,8 @@ await sandbox.render('<ore-button variant="primary">Click me</ore-button>');
|
|
|
24
24
|
// Subsequent renders — same contract, a fresh Promise each time
|
|
25
25
|
await sandbox.render(newHtml);
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
sandbox.
|
|
27
|
+
// Replace body descendants without a full page reset
|
|
28
|
+
sandbox.replaceBody('<p>updated</p>');
|
|
29
29
|
|
|
30
30
|
// Push state into the sandbox
|
|
31
31
|
sandbox.setState('theme', 'dark');
|
|
@@ -60,15 +60,15 @@ Creates an isolated `<iframe sandbox="allow-scripts">` inside `container`.
|
|
|
60
60
|
|
|
61
61
|
| Option | Type | Description |
|
|
62
62
|
| ---------------------- | ------------------------ | ------------------------------------------------------------------------------- |
|
|
63
|
-
| `scripts` | `string[]` |
|
|
64
|
-
| `namedStyles` | `Record<string, string>` | Named
|
|
65
|
-
| `nonce` | `string` |
|
|
66
|
-
| `lang` | `string` |
|
|
67
|
-
| `title` | `string` | Document `<title>`. Default: `''`
|
|
68
|
-
| `allowedScriptOrigins` | `string[]` |
|
|
69
|
-
| `allowedStyleOrigins` | `string[]` |
|
|
70
|
-
| `allowedImageOrigins` | `string[]` |
|
|
71
|
-
| `allowedFontOrigins` | `string[]` |
|
|
63
|
+
| `scripts` | `string[]` | Absolute `http:` or `https:` script URLs injected with `crossorigin="anonymous"`; origins auto-added |
|
|
64
|
+
| `namedStyles` | `Record<string, string>` | Named `<style>` blocks; keys start with a letter and use only letters, digits, `_`, or `-` |
|
|
65
|
+
| `nonce` | `string` | Non-empty base64/base64url-style token for both bridge scripts and `script-src` |
|
|
66
|
+
| `lang` | `string` | Basic language tag, such as `en`, `de`, or `zh-Hant`. Default: `'en'` |
|
|
67
|
+
| `title` | `string` | Document `<title>`. Default: `''` |
|
|
68
|
+
| `allowedScriptOrigins` | `string[]` | Absolute `http:` or `https:` origins added to `script-src` |
|
|
69
|
+
| `allowedStyleOrigins` | `string[]` | Absolute `http:` or `https:` origins added to `style-src` |
|
|
70
|
+
| `allowedImageOrigins` | `string[]` | Absolute `http:` or `https:` origins added to `img-src` |
|
|
71
|
+
| `allowedFontOrigins` | `string[]` | Absolute `http:` or `https:` origins added to `font-src` |
|
|
72
72
|
|
|
73
73
|
### `SandboxHandle`
|
|
74
74
|
|
|
@@ -78,7 +78,7 @@ Creates an isolated `<iframe sandbox="allow-scripts">` inside `container`.
|
|
|
78
78
|
| `disposalSignal` | `AbortSignal` aborted on `dispose()` — tie async operations to the sandbox's lifetime |
|
|
79
79
|
| `ready` | Resolves on the **first** load or dispose; does not reset on re-renders |
|
|
80
80
|
| `render(html, options?)` | Full page reset; lazy iframe creation. Returns a Promise that resolves on ready or rejects with `SandboxTimeoutError` after 5s. Pass `signal` to skip if already aborted |
|
|
81
|
-
| `
|
|
81
|
+
| `replaceBody(html)` | Replace body descendants without navigating. Head scripts/styles survive; descendant listeners and state do not. Call after `render()` resolves |
|
|
82
82
|
| `setState(key, value)` | Push a single state value into the sandbox; warns if called before ready |
|
|
83
83
|
| `setStateAll(record)` | Push multiple state values in one message; more efficient than repeated `setState()` |
|
|
84
84
|
| `updateStyle(id, css)` | Hot-patch a `namedStyles` block by id, live and in the baseline for the next render |
|
|
@@ -92,7 +92,7 @@ Builds a strict Content-Security-Policy string from `SandboxOptions`. Origins fr
|
|
|
92
92
|
|
|
93
93
|
### `buildDocument(html, options?): string`
|
|
94
94
|
|
|
95
|
-
Builds
|
|
95
|
+
Builds isolated markup with CSP meta tag, bridge script, and injected scripts/styles. It does not return a host runtime handle; use `createSandbox()` for state updates, body replacement, style updates, readiness, or disposal.
|
|
96
96
|
|
|
97
97
|
## Bridge Protocol
|
|
98
98
|
|
|
@@ -133,7 +133,7 @@ declare interface Window {
|
|
|
133
133
|
|
|
134
134
|
## Errors
|
|
135
135
|
|
|
136
|
-
`SandboxError` is the base class for
|
|
136
|
+
`SandboxError` is the base class for package errors. `SandboxConfigurationError` rejects malformed CSP/document options during construction. `SandboxTimeoutError extends SandboxError` and is thrown by `render()` when no `'ready'` signal arrives within 5 seconds (usually a document missing the bridge script). This rejection happens in every build, not just dev — always handle it:
|
|
137
137
|
|
|
138
138
|
```ts
|
|
139
139
|
import { SandboxTimeoutError } from '@vielzeug/sandbox';
|
package/dist/_bridge.cjs
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
function e(e){return`
|
|
2
|
+
window.__sandboxChannel = ${JSON.stringify(e.channel)};
|
|
3
|
+
window.__sandboxGeneration = ${String(e.generation)};
|
|
4
|
+
const __sandboxChannel = window.__sandboxChannel;
|
|
5
|
+
const __sandboxGeneration = window.__sandboxGeneration;
|
|
6
|
+
if ('ontouchstart' in window) document.addEventListener('touchstart', function() {}, { passive: true });
|
|
7
|
+
window.addEventListener('message', function(e) {
|
|
8
|
+
var msg = e.data;
|
|
9
|
+
if (e.source !== parent || !msg || msg.channel !== __sandboxChannel || msg.generation !== __sandboxGeneration) return;
|
|
10
|
+
if (msg.type === 'state-update') {
|
|
11
|
+
document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: msg.key, value: msg.value } }));
|
|
12
|
+
}
|
|
13
|
+
if (msg.type === 'state-update-all' && msg.record && typeof msg.record === 'object') {
|
|
14
|
+
var keys = Object.keys(msg.record);
|
|
15
|
+
for (var i = 0; i < keys.length; i++) {
|
|
16
|
+
var k = keys[i];
|
|
17
|
+
document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: k, value: msg.record[k] } }));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (msg.type === 'style-patch' && msg.id && typeof msg.css === 'string') {
|
|
21
|
+
var el = document.getElementById(msg.id);
|
|
22
|
+
if (el && el.tagName === 'STYLE') el.textContent = msg.css;
|
|
23
|
+
}
|
|
24
|
+
if (msg.type === 'html-replace' && typeof msg.html === 'string') {
|
|
25
|
+
document.body.innerHTML = msg.html;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
function post(msg) {
|
|
29
|
+
msg.channel = __sandboxChannel;
|
|
30
|
+
msg.generation = __sandboxGeneration;
|
|
31
|
+
parent.postMessage(msg, '*');
|
|
32
|
+
}
|
|
33
|
+
window.onerror = function(message, _src, _line, _col, err) {
|
|
34
|
+
post({ type: 'error', message: String(message), stack: err && err.stack });
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
37
|
+
window.addEventListener('unhandledrejection', function(e) {
|
|
38
|
+
var reason = e.reason;
|
|
39
|
+
post({ type: 'error', message: String(reason), stack: reason && reason.stack });
|
|
40
|
+
});
|
|
41
|
+
window.__sandbox__ = {
|
|
42
|
+
emit: function(event, detail) {
|
|
43
|
+
post({ type: 'custom', event: String(event), detail: detail });
|
|
44
|
+
},
|
|
45
|
+
onState: function(key, handler) {
|
|
46
|
+
function listener(e) {
|
|
47
|
+
if (e.detail && e.detail.key === key) handler(e.detail.value);
|
|
48
|
+
}
|
|
49
|
+
document.addEventListener('sandbox:state-update', listener);
|
|
50
|
+
return function() {
|
|
51
|
+
document.removeEventListener('sandbox:state-update', listener);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
post({ type: 'ready' });
|
|
56
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
57
|
+
new ResizeObserver(function(entries) {
|
|
58
|
+
var entry = entries[0];
|
|
59
|
+
if (!entry) return;
|
|
60
|
+
var h = entry.borderBoxSize && entry.borderBoxSize[0]
|
|
61
|
+
? entry.borderBoxSize[0].blockSize
|
|
62
|
+
: entry.contentRect.height;
|
|
63
|
+
post({ type: 'resize', height: h });
|
|
64
|
+
}).observe(document.body);
|
|
65
|
+
}
|
|
66
|
+
`.trim()}exports.buildBridgeScript=e;
|
|
67
|
+
//# sourceMappingURL=_bridge.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_bridge.cjs","names":[],"sources":["../src/_bridge.ts"],"sourcesContent":["import type { BridgeBootstrap } from './_protocol.js';\n\nexport function buildBridgeScript(bootstrap: BridgeBootstrap): string {\n const channel = JSON.stringify(bootstrap.channel);\n const generation = String(bootstrap.generation);\n\n return `\nwindow.__sandboxChannel = ${channel};\nwindow.__sandboxGeneration = ${generation};\nconst __sandboxChannel = window.__sandboxChannel;\nconst __sandboxGeneration = window.__sandboxGeneration;\nif ('ontouchstart' in window) document.addEventListener('touchstart', function() {}, { passive: true });\nwindow.addEventListener('message', function(e) {\n var msg = e.data;\n if (e.source !== parent || !msg || msg.channel !== __sandboxChannel || msg.generation !== __sandboxGeneration) return;\n if (msg.type === 'state-update') {\n document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: msg.key, value: msg.value } }));\n }\n if (msg.type === 'state-update-all' && msg.record && typeof msg.record === 'object') {\n var keys = Object.keys(msg.record);\n for (var i = 0; i < keys.length; i++) {\n var k = keys[i];\n document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: k, value: msg.record[k] } }));\n }\n }\n if (msg.type === 'style-patch' && msg.id && typeof msg.css === 'string') {\n var el = document.getElementById(msg.id);\n if (el && el.tagName === 'STYLE') el.textContent = msg.css;\n }\n if (msg.type === 'html-replace' && typeof msg.html === 'string') {\n document.body.innerHTML = msg.html;\n }\n});\nfunction post(msg) {\n msg.channel = __sandboxChannel;\n msg.generation = __sandboxGeneration;\n parent.postMessage(msg, '*');\n}\nwindow.onerror = function(message, _src, _line, _col, err) {\n post({ type: 'error', message: String(message), stack: err && err.stack });\n return true;\n};\nwindow.addEventListener('unhandledrejection', function(e) {\n var reason = e.reason;\n post({ type: 'error', message: String(reason), stack: reason && reason.stack });\n});\nwindow.__sandbox__ = {\n emit: function(event, detail) {\n post({ type: 'custom', event: String(event), detail: detail });\n },\n onState: function(key, handler) {\n function listener(e) {\n if (e.detail && e.detail.key === key) handler(e.detail.value);\n }\n document.addEventListener('sandbox:state-update', listener);\n return function() {\n document.removeEventListener('sandbox:state-update', listener);\n };\n }\n};\npost({ type: 'ready' });\nif (typeof ResizeObserver !== 'undefined') {\n new ResizeObserver(function(entries) {\n var entry = entries[0];\n if (!entry) return;\n var h = entry.borderBoxSize && entry.borderBoxSize[0]\n ? entry.borderBoxSize[0].blockSize\n : entry.contentRect.height;\n post({ type: 'resize', height: h });\n }).observe(document.body);\n}\n`.trim();\n}\n"],"mappings":"AAEA,SAAgB,EAAkB,EAAoC,CAIpE,MAAO;4BAHS,KAAK,UAAU,EAAU,OAIf,EAAQ;+BAHf,OAAO,EAAU,UAIP,EAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DxC,KAAK,CACP"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_bridge.d.ts","sourceRoot":"","sources":["../src/_bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,eAAe,GAAG,MAAM,CAsEpE"}
|
package/dist/_bridge.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/_bridge.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
return `
|
|
4
|
+
window.__sandboxChannel = ${JSON.stringify(e.channel)};
|
|
5
|
+
window.__sandboxGeneration = ${String(e.generation)};
|
|
6
|
+
const __sandboxChannel = window.__sandboxChannel;
|
|
7
|
+
const __sandboxGeneration = window.__sandboxGeneration;
|
|
8
|
+
if ('ontouchstart' in window) document.addEventListener('touchstart', function() {}, { passive: true });
|
|
9
|
+
window.addEventListener('message', function(e) {
|
|
10
|
+
var msg = e.data;
|
|
11
|
+
if (e.source !== parent || !msg || msg.channel !== __sandboxChannel || msg.generation !== __sandboxGeneration) return;
|
|
12
|
+
if (msg.type === 'state-update') {
|
|
13
|
+
document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: msg.key, value: msg.value } }));
|
|
14
|
+
}
|
|
15
|
+
if (msg.type === 'state-update-all' && msg.record && typeof msg.record === 'object') {
|
|
16
|
+
var keys = Object.keys(msg.record);
|
|
17
|
+
for (var i = 0; i < keys.length; i++) {
|
|
18
|
+
var k = keys[i];
|
|
19
|
+
document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: k, value: msg.record[k] } }));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (msg.type === 'style-patch' && msg.id && typeof msg.css === 'string') {
|
|
23
|
+
var el = document.getElementById(msg.id);
|
|
24
|
+
if (el && el.tagName === 'STYLE') el.textContent = msg.css;
|
|
25
|
+
}
|
|
26
|
+
if (msg.type === 'html-replace' && typeof msg.html === 'string') {
|
|
27
|
+
document.body.innerHTML = msg.html;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
function post(msg) {
|
|
31
|
+
msg.channel = __sandboxChannel;
|
|
32
|
+
msg.generation = __sandboxGeneration;
|
|
33
|
+
parent.postMessage(msg, '*');
|
|
34
|
+
}
|
|
35
|
+
window.onerror = function(message, _src, _line, _col, err) {
|
|
36
|
+
post({ type: 'error', message: String(message), stack: err && err.stack });
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
window.addEventListener('unhandledrejection', function(e) {
|
|
40
|
+
var reason = e.reason;
|
|
41
|
+
post({ type: 'error', message: String(reason), stack: reason && reason.stack });
|
|
42
|
+
});
|
|
43
|
+
window.__sandbox__ = {
|
|
44
|
+
emit: function(event, detail) {
|
|
45
|
+
post({ type: 'custom', event: String(event), detail: detail });
|
|
46
|
+
},
|
|
47
|
+
onState: function(key, handler) {
|
|
48
|
+
function listener(e) {
|
|
49
|
+
if (e.detail && e.detail.key === key) handler(e.detail.value);
|
|
50
|
+
}
|
|
51
|
+
document.addEventListener('sandbox:state-update', listener);
|
|
52
|
+
return function() {
|
|
53
|
+
document.removeEventListener('sandbox:state-update', listener);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
post({ type: 'ready' });
|
|
58
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
59
|
+
new ResizeObserver(function(entries) {
|
|
60
|
+
var entry = entries[0];
|
|
61
|
+
if (!entry) return;
|
|
62
|
+
var h = entry.borderBoxSize && entry.borderBoxSize[0]
|
|
63
|
+
? entry.borderBoxSize[0].blockSize
|
|
64
|
+
: entry.contentRect.height;
|
|
65
|
+
post({ type: 'resize', height: h });
|
|
66
|
+
}).observe(document.body);
|
|
67
|
+
}
|
|
68
|
+
`.trim();
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { e as buildBridgeScript };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=_bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_bridge.js","names":[],"sources":["../src/_bridge.ts"],"sourcesContent":["import type { BridgeBootstrap } from './_protocol.js';\n\nexport function buildBridgeScript(bootstrap: BridgeBootstrap): string {\n const channel = JSON.stringify(bootstrap.channel);\n const generation = String(bootstrap.generation);\n\n return `\nwindow.__sandboxChannel = ${channel};\nwindow.__sandboxGeneration = ${generation};\nconst __sandboxChannel = window.__sandboxChannel;\nconst __sandboxGeneration = window.__sandboxGeneration;\nif ('ontouchstart' in window) document.addEventListener('touchstart', function() {}, { passive: true });\nwindow.addEventListener('message', function(e) {\n var msg = e.data;\n if (e.source !== parent || !msg || msg.channel !== __sandboxChannel || msg.generation !== __sandboxGeneration) return;\n if (msg.type === 'state-update') {\n document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: msg.key, value: msg.value } }));\n }\n if (msg.type === 'state-update-all' && msg.record && typeof msg.record === 'object') {\n var keys = Object.keys(msg.record);\n for (var i = 0; i < keys.length; i++) {\n var k = keys[i];\n document.dispatchEvent(new CustomEvent('sandbox:state-update', { detail: { key: k, value: msg.record[k] } }));\n }\n }\n if (msg.type === 'style-patch' && msg.id && typeof msg.css === 'string') {\n var el = document.getElementById(msg.id);\n if (el && el.tagName === 'STYLE') el.textContent = msg.css;\n }\n if (msg.type === 'html-replace' && typeof msg.html === 'string') {\n document.body.innerHTML = msg.html;\n }\n});\nfunction post(msg) {\n msg.channel = __sandboxChannel;\n msg.generation = __sandboxGeneration;\n parent.postMessage(msg, '*');\n}\nwindow.onerror = function(message, _src, _line, _col, err) {\n post({ type: 'error', message: String(message), stack: err && err.stack });\n return true;\n};\nwindow.addEventListener('unhandledrejection', function(e) {\n var reason = e.reason;\n post({ type: 'error', message: String(reason), stack: reason && reason.stack });\n});\nwindow.__sandbox__ = {\n emit: function(event, detail) {\n post({ type: 'custom', event: String(event), detail: detail });\n },\n onState: function(key, handler) {\n function listener(e) {\n if (e.detail && e.detail.key === key) handler(e.detail.value);\n }\n document.addEventListener('sandbox:state-update', listener);\n return function() {\n document.removeEventListener('sandbox:state-update', listener);\n };\n }\n};\npost({ type: 'ready' });\nif (typeof ResizeObserver !== 'undefined') {\n new ResizeObserver(function(entries) {\n var entry = entries[0];\n if (!entry) return;\n var h = entry.borderBoxSize && entry.borderBoxSize[0]\n ? entry.borderBoxSize[0].blockSize\n : entry.contentRect.height;\n post({ type: 'resize', height: h });\n }).observe(document.body);\n}\n`.trim();\n}\n"],"mappings":";AAEA,SAAgB,EAAkB,GAAoC;CAIpE,OAAO;4BAHS,KAAK,UAAU,EAAU,OAIf,EAAQ;+BAHf,OAAO,EAAU,UAIP,EAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DxC,KAAK;AACP"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const e=require("./_policy.cjs"),t=require("./_bridge.cjs");function n(e){return e.replace(/<\/style/gi,`\\3C /style`)}function r(e){return e.replace(/&/g,`&`).replace(/"/g,`"`).replace(/</g,`<`).replace(/>/g,`>`)}function i(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function a(a,o,s){let c=r(e.buildCspFromOptions(o)),l=Object.entries(o.namedStyles).map(([e,t])=>`<style id="${r(e)}">${n(t)}</style>`).join(`
|
|
2
|
+
`),u=o.scripts.map(e=>`<script crossorigin="anonymous" src="${r(e)}"><\/script>`).join(`
|
|
3
|
+
`),d=o.nonce?` nonce="${r(o.nonce)}"`:``,f=`<script${d}>window.__sandboxChannel=${JSON.stringify(s.channel)};window.__sandboxGeneration=${s.generation};<\/script>`;return`<!doctype html>
|
|
4
|
+
<html lang="${r(o.lang)}">
|
|
5
|
+
<head>
|
|
6
|
+
<meta http-equiv="Content-Security-Policy" content="${c}">
|
|
7
|
+
${f}
|
|
8
|
+
<meta charset="utf-8">
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
+
<title>${i(o.title)}</title>
|
|
11
|
+
${l}
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
${u}
|
|
15
|
+
${a}
|
|
16
|
+
<script${d}>
|
|
17
|
+
${t.buildBridgeScript(s)}
|
|
18
|
+
<\/script>
|
|
19
|
+
</body>
|
|
20
|
+
</html>`}function o(t,n={}){return a(t,e.normalizeSandboxOptions(n),{channel:``,generation:0})}function s(e,t,n){return a(e,t,n)}exports.buildDocument=o,exports.buildRuntimeDocument=s;
|
|
21
|
+
//# sourceMappingURL=_document.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_document.cjs","names":[],"sources":["../src/_document.ts"],"sourcesContent":["import type { BridgeBootstrap } from './_protocol.js';\nimport type { SandboxOptions } from './types.js';\n\nimport { buildBridgeScript } from './_bridge.js';\nimport { buildCspFromOptions, normalizeSandboxOptions, type NormalizedSandboxOptions } from './_policy.js';\n\nfunction escapeCss(css: string): string {\n return css.replace(/<\\/style/gi, '\\\\3C /style');\n}\n\nfunction escapeAttr(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction escapeText(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction buildDocumentFromOptions(html: string, options: NormalizedSandboxOptions, bootstrap: BridgeBootstrap): string {\n const csp = escapeAttr(buildCspFromOptions(options));\n const styles = Object.entries(options.namedStyles)\n .map(([id, css]) => `<style id=\"${escapeAttr(id)}\">${escapeCss(css)}</style>`)\n .join('\\n');\n const scripts = options.scripts\n .map((src) => `<script crossorigin=\"anonymous\" src=\"${escapeAttr(src)}\"></script>`)\n .join('\\n');\n const nonce = options.nonce ? ` nonce=\"${escapeAttr(options.nonce)}\"` : '';\n const bootstrapScript = `<script${nonce}>window.__sandboxChannel=${JSON.stringify(bootstrap.channel)};window.__sandboxGeneration=${bootstrap.generation};</script>`;\n\n return `<!doctype html>\n<html lang=\"${escapeAttr(options.lang)}\">\n<head>\n<meta http-equiv=\"Content-Security-Policy\" content=\"${csp}\">\n${bootstrapScript}\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeText(options.title)}</title>\n${styles}\n</head>\n<body>\n${scripts}\n${html}\n<script${nonce}>\n${buildBridgeScript(bootstrap)}\n</script>\n</body>\n</html>`;\n}\n\nexport function buildDocument(html: string, options: SandboxOptions = {}): string {\n return buildDocumentFromOptions(html, normalizeSandboxOptions(options), { channel: '', generation: 0 });\n}\n\nexport function buildRuntimeDocument(\n html: string,\n options: NormalizedSandboxOptions,\n bootstrap: BridgeBootstrap,\n): string {\n return buildDocumentFromOptions(html, options, bootstrap);\n}\n"],"mappings":"4DAMA,SAAS,EAAU,EAAqB,CACtC,OAAO,EAAI,QAAQ,aAAc,aAAa,CAChD,CAEA,SAAS,EAAW,EAAuB,CACzC,OAAO,EAAM,QAAQ,KAAM,OAAO,CAAC,CAAC,QAAQ,KAAM,QAAQ,CAAC,CAAC,QAAQ,KAAM,MAAM,CAAC,CAAC,QAAQ,KAAM,MAAM,CACxG,CAEA,SAAS,EAAW,EAAuB,CACzC,OAAO,EAAM,QAAQ,KAAM,OAAO,CAAC,CAAC,QAAQ,KAAM,MAAM,CAAC,CAAC,QAAQ,KAAM,MAAM,CAChF,CAEA,SAAS,EAAyB,EAAc,EAAmC,EAAoC,CACrH,IAAM,EAAM,EAAW,EAAA,oBAAoB,CAAO,CAAC,EAC7C,EAAS,OAAO,QAAQ,EAAQ,WAAW,CAAC,CAC/C,KAAK,CAAC,EAAI,KAAS,cAAc,EAAW,CAAE,EAAE,IAAI,EAAU,CAAG,EAAE,SAAS,CAAC,CAC7E,KAAK;CAAI,EACN,EAAU,EAAQ,QACrB,IAAK,GAAQ,wCAAwC,EAAW,CAAG,EAAE,aAAY,CAAC,CAClF,KAAK;CAAI,EACN,EAAQ,EAAQ,MAAQ,WAAW,EAAW,EAAQ,KAAK,EAAE,GAAK,GAClE,EAAkB,UAAU,EAAM,2BAA2B,KAAK,UAAU,EAAU,OAAO,EAAE,8BAA8B,EAAU,WAAW,aAExJ,MAAO;cACK,EAAW,EAAQ,IAAI,EAAE;;sDAEe,EAAI;EACxD,EAAgB;;;SAGT,EAAW,EAAQ,KAAK,EAAE;EACjC,EAAO;;;EAGP,EAAQ;EACR,EAAK;SACE,EAAM;EACb,EAAA,kBAAkB,CAAS,EAAE;;;QAI/B,CAEA,SAAgB,EAAc,EAAc,EAA0B,CAAC,EAAW,CAChF,OAAO,EAAyB,EAAM,EAAA,wBAAwB,CAAO,EAAG,CAAE,QAAS,GAAI,WAAY,CAAE,CAAC,CACxG,CAEA,SAAgB,EACd,EACA,EACA,EACQ,CACR,OAAO,EAAyB,EAAM,EAAS,CAAS,CAC1D"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BridgeBootstrap } from './_protocol.js';
|
|
2
|
+
import type { SandboxOptions } from './types.js';
|
|
3
|
+
import { type NormalizedSandboxOptions } from './_policy.js';
|
|
4
|
+
export declare function buildDocument(html: string, options?: SandboxOptions): string;
|
|
5
|
+
export declare function buildRuntimeDocument(html: string, options: NormalizedSandboxOptions, bootstrap: BridgeBootstrap): string;
|
|
6
|
+
//# sourceMappingURL=_document.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_document.d.ts","sourceRoot":"","sources":["../src/_document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAgD,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAC;AA6C3G,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CAEhF;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,wBAAwB,EACjC,SAAS,EAAE,eAAe,GACzB,MAAM,CAER"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { buildCspFromOptions as e, normalizeSandboxOptions as t } from "./_policy.js";
|
|
2
|
+
import { buildBridgeScript as n } from "./_bridge.js";
|
|
3
|
+
//#region src/_document.ts
|
|
4
|
+
function r(e) {
|
|
5
|
+
return e.replace(/<\/style/gi, "\\3C /style");
|
|
6
|
+
}
|
|
7
|
+
function i(e) {
|
|
8
|
+
return e.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
9
|
+
}
|
|
10
|
+
function a(e) {
|
|
11
|
+
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
12
|
+
}
|
|
13
|
+
function o(t, o, s) {
|
|
14
|
+
let c = i(e(o)), l = Object.entries(o.namedStyles).map(([e, t]) => `<style id="${i(e)}">${r(t)}</style>`).join("\n"), u = o.scripts.map((e) => `<script crossorigin="anonymous" src="${i(e)}"><\/script>`).join("\n"), d = o.nonce ? ` nonce="${i(o.nonce)}"` : "", f = `<script${d}>window.__sandboxChannel=${JSON.stringify(s.channel)};window.__sandboxGeneration=${s.generation};<\/script>`;
|
|
15
|
+
return `<!doctype html>
|
|
16
|
+
<html lang="${i(o.lang)}">
|
|
17
|
+
<head>
|
|
18
|
+
<meta http-equiv="Content-Security-Policy" content="${c}">
|
|
19
|
+
${f}
|
|
20
|
+
<meta charset="utf-8">
|
|
21
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
22
|
+
<title>${a(o.title)}</title>
|
|
23
|
+
${l}
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
${u}
|
|
27
|
+
${t}
|
|
28
|
+
<script${d}>
|
|
29
|
+
${n(s)}
|
|
30
|
+
<\/script>
|
|
31
|
+
</body>
|
|
32
|
+
</html>`;
|
|
33
|
+
}
|
|
34
|
+
function s(e, n = {}) {
|
|
35
|
+
return o(e, t(n), {
|
|
36
|
+
channel: "",
|
|
37
|
+
generation: 0
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function c(e, t, n) {
|
|
41
|
+
return o(e, t, n);
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { s as buildDocument, c as buildRuntimeDocument };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=_document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_document.js","names":[],"sources":["../src/_document.ts"],"sourcesContent":["import type { BridgeBootstrap } from './_protocol.js';\nimport type { SandboxOptions } from './types.js';\n\nimport { buildBridgeScript } from './_bridge.js';\nimport { buildCspFromOptions, normalizeSandboxOptions, type NormalizedSandboxOptions } from './_policy.js';\n\nfunction escapeCss(css: string): string {\n return css.replace(/<\\/style/gi, '\\\\3C /style');\n}\n\nfunction escapeAttr(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction escapeText(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction buildDocumentFromOptions(html: string, options: NormalizedSandboxOptions, bootstrap: BridgeBootstrap): string {\n const csp = escapeAttr(buildCspFromOptions(options));\n const styles = Object.entries(options.namedStyles)\n .map(([id, css]) => `<style id=\"${escapeAttr(id)}\">${escapeCss(css)}</style>`)\n .join('\\n');\n const scripts = options.scripts\n .map((src) => `<script crossorigin=\"anonymous\" src=\"${escapeAttr(src)}\"></script>`)\n .join('\\n');\n const nonce = options.nonce ? ` nonce=\"${escapeAttr(options.nonce)}\"` : '';\n const bootstrapScript = `<script${nonce}>window.__sandboxChannel=${JSON.stringify(bootstrap.channel)};window.__sandboxGeneration=${bootstrap.generation};</script>`;\n\n return `<!doctype html>\n<html lang=\"${escapeAttr(options.lang)}\">\n<head>\n<meta http-equiv=\"Content-Security-Policy\" content=\"${csp}\">\n${bootstrapScript}\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeText(options.title)}</title>\n${styles}\n</head>\n<body>\n${scripts}\n${html}\n<script${nonce}>\n${buildBridgeScript(bootstrap)}\n</script>\n</body>\n</html>`;\n}\n\nexport function buildDocument(html: string, options: SandboxOptions = {}): string {\n return buildDocumentFromOptions(html, normalizeSandboxOptions(options), { channel: '', generation: 0 });\n}\n\nexport function buildRuntimeDocument(\n html: string,\n options: NormalizedSandboxOptions,\n bootstrap: BridgeBootstrap,\n): string {\n return buildDocumentFromOptions(html, options, bootstrap);\n}\n"],"mappings":";;;AAMA,SAAS,EAAU,GAAqB;CACtC,OAAO,EAAI,QAAQ,cAAc,aAAa;AAChD;AAEA,SAAS,EAAW,GAAuB;CACzC,OAAO,EAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,QAAQ,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;AACxG;AAEA,SAAS,EAAW,GAAuB;CACzC,OAAO,EAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;AAChF;AAEA,SAAS,EAAyB,GAAc,GAAmC,GAAoC;CACrH,IAAM,IAAM,EAAW,EAAoB,CAAO,CAAC,GAC7C,IAAS,OAAO,QAAQ,EAAQ,WAAW,CAAC,CAC/C,KAAK,CAAC,GAAI,OAAS,cAAc,EAAW,CAAE,EAAE,IAAI,EAAU,CAAG,EAAE,SAAS,CAAC,CAC7E,KAAK,IAAI,GACN,IAAU,EAAQ,QACrB,KAAK,MAAQ,wCAAwC,EAAW,CAAG,EAAE,aAAY,CAAC,CAClF,KAAK,IAAI,GACN,IAAQ,EAAQ,QAAQ,WAAW,EAAW,EAAQ,KAAK,EAAE,KAAK,IAClE,IAAkB,UAAU,EAAM,2BAA2B,KAAK,UAAU,EAAU,OAAO,EAAE,8BAA8B,EAAU,WAAW;CAExJ,OAAO;cACK,EAAW,EAAQ,IAAI,EAAE;;sDAEe,EAAI;EACxD,EAAgB;;;SAGT,EAAW,EAAQ,KAAK,EAAE;EACjC,EAAO;;;EAGP,EAAQ;EACR,EAAK;SACE,EAAM;EACb,EAAkB,CAAS,EAAE;;;;AAI/B;AAEA,SAAgB,EAAc,GAAc,IAA0B,CAAC,GAAW;CAChF,OAAO,EAAyB,GAAM,EAAwB,CAAO,GAAG;EAAE,SAAS;EAAI,YAAY;CAAE,CAAC;AACxG;AAEA,SAAgB,EACd,GACA,GACA,GACQ;CACR,OAAO,EAAyB,GAAM,GAAS,CAAS;AAC1D"}
|
package/dist/_policy.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors.cjs");var t=/^[A-Za-z][A-Za-z0-9_-]*$/,n=/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/,r=/^[A-Za-z0-9+/_-]+={0,2}$/;function i(t,n){throw new e.SandboxConfigurationError(`${t} is invalid: ${String(n)}`)}function a(e,t){let n;try{n=new URL(e)}catch{return i(t,e)}return n.protocol!==`http:`&&n.protocol!==`https:`||n.username||n.password||n.pathname!==`/`||n.search||n.hash?i(t,e):n.origin}function o(e,t){return(e??[]).map(e=>a(e,t))}function s(e){let t;try{t=new URL(e)}catch{return i(`scripts`,e)}return t.protocol!==`http:`&&t.protocol!==`https:`?i(`scripts`,e):t.href}function c(e){let n={};for(let[r,a]of Object.entries(e??{}))(!t.test(r)||typeof a!=`string`)&&i(`namedStyles`,r),n[r]=a;return n}function l(e={}){let t=e.lang??`en`;n.test(t)||i(`lang`,t),e.nonce!==void 0&&(!r.test(e.nonce)||e.nonce.length===0)&&i(`nonce`,e.nonce),e.title!==void 0&&typeof e.title!=`string`&&i(`title`,e.title);let a=(e.scripts??[]).map(s);return{allowedFontOrigins:o(e.allowedFontOrigins,`allowedFontOrigins`),allowedImageOrigins:o(e.allowedImageOrigins,`allowedImageOrigins`),allowedScriptOrigins:o(e.allowedScriptOrigins,`allowedScriptOrigins`),allowedStyleOrigins:o(e.allowedStyleOrigins,`allowedStyleOrigins`),lang:t,namedStyles:c(e.namedStyles),nonce:e.nonce,scripts:a,title:e.title??``}}function u(e){let t=[`'unsafe-inline'`,...e.nonce?[`'nonce-${e.nonce}'`]:[],...e.allowedScriptOrigins,...e.scripts.map(e=>new URL(e).origin)].join(` `),n=[`'unsafe-inline'`,...e.allowedStyleOrigins].join(` `),r=[`data:`,...e.allowedImageOrigins].join(` `),i=e.allowedFontOrigins.join(` `)||`'none'`;return[`default-src 'none'`,`script-src ${t}`,`style-src ${n}`,`img-src ${r}`,`font-src ${i}`,`connect-src 'none'`,`form-action 'none'`,`base-uri 'none'`].join(`; `)}exports.buildCspFromOptions=u,exports.normalizeSandboxOptions=l;
|
|
2
|
+
//# sourceMappingURL=_policy.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_policy.cjs","names":[],"sources":["../src/_policy.ts"],"sourcesContent":["import type { SandboxOptions } from './types.js';\n\nimport { SandboxConfigurationError } from './errors.js';\n\nexport interface NormalizedSandboxOptions {\n allowedFontOrigins: string[];\n allowedImageOrigins: string[];\n allowedScriptOrigins: string[];\n allowedStyleOrigins: string[];\n lang: string;\n namedStyles: Record<string, string>;\n nonce: string | undefined;\n scripts: string[];\n title: string;\n}\n\nconst ID = /^[A-Za-z][A-Za-z0-9_-]*$/;\nconst LANG = /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;\nconst NONCE = /^[A-Za-z0-9+/_-]+={0,2}$/;\n\nfunction fail(field: string, value: unknown): never {\n throw new SandboxConfigurationError(`${field} is invalid: ${String(value)}`);\n}\n\nfunction normalizeOrigin(value: string, field: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n return fail(field, value);\n }\n\n if (\n (url.protocol !== 'http:' && url.protocol !== 'https:') ||\n url.username ||\n url.password ||\n url.pathname !== '/' ||\n url.search ||\n url.hash\n ) {\n return fail(field, value);\n }\n\n return url.origin;\n}\n\nfunction normalizeOrigins(values: string[] | undefined, field: string): string[] {\n return (values ?? []).map((value) => normalizeOrigin(value, field));\n}\n\nfunction normalizeScript(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n return fail('scripts', value);\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return fail('scripts', value);\n\n return url.href;\n}\n\nfunction normalizeStyles(styles: Record<string, string> | undefined): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [id, css] of Object.entries(styles ?? {})) {\n if (!ID.test(id) || typeof css !== 'string') fail('namedStyles', id);\n\n normalized[id] = css;\n }\n\n return normalized;\n}\n\nexport function normalizeSandboxOptions(options: SandboxOptions = {}): NormalizedSandboxOptions {\n const lang = options.lang ?? 'en';\n\n if (!LANG.test(lang)) fail('lang', lang);\n\n if (options.nonce !== undefined && (!NONCE.test(options.nonce) || options.nonce.length === 0)) {\n fail('nonce', options.nonce);\n }\n\n if (options.title !== undefined && typeof options.title !== 'string') fail('title', options.title);\n\n const scripts = (options.scripts ?? []).map(normalizeScript);\n\n return {\n allowedFontOrigins: normalizeOrigins(options.allowedFontOrigins, 'allowedFontOrigins'),\n allowedImageOrigins: normalizeOrigins(options.allowedImageOrigins, 'allowedImageOrigins'),\n allowedScriptOrigins: normalizeOrigins(options.allowedScriptOrigins, 'allowedScriptOrigins'),\n allowedStyleOrigins: normalizeOrigins(options.allowedStyleOrigins, 'allowedStyleOrigins'),\n lang,\n namedStyles: normalizeStyles(options.namedStyles),\n nonce: options.nonce,\n scripts,\n title: options.title ?? '',\n };\n}\n\nexport function buildCspFromOptions(options: NormalizedSandboxOptions): string {\n const scriptOrigins = [\n \"'unsafe-inline'\",\n ...(options.nonce ? [`'nonce-${options.nonce}'`] : []),\n ...options.allowedScriptOrigins,\n ...options.scripts.map((script) => new URL(script).origin),\n ].join(' ');\n const styleOrigins = [\"'unsafe-inline'\", ...options.allowedStyleOrigins].join(' ');\n const imageOrigins = ['data:', ...options.allowedImageOrigins].join(' ');\n const fontOrigins = options.allowedFontOrigins.join(' ') || \"'none'\";\n\n return [\n \"default-src 'none'\",\n `script-src ${scriptOrigins}`,\n `style-src ${styleOrigins}`,\n `img-src ${imageOrigins}`,\n `font-src ${fontOrigins}`,\n \"connect-src 'none'\",\n \"form-action 'none'\",\n \"base-uri 'none'\",\n ].join('; ');\n}\n"],"mappings":"gCAgBA,IAAM,EAAK,2BACL,EAAO,wCACP,EAAQ,2BAEd,SAAS,EAAK,EAAe,EAAuB,CAClD,MAAM,IAAI,EAAA,0BAA0B,GAAG,EAAM,eAAe,OAAO,CAAK,GAAG,CAC7E,CAEA,SAAS,EAAgB,EAAe,EAAuB,CAC7D,IAAI,EAEJ,GAAI,CACF,EAAM,IAAI,IAAI,CAAK,CACrB,MAAQ,CACN,OAAO,EAAK,EAAO,CAAK,CAC1B,CAaA,OAVG,EAAI,WAAa,SAAW,EAAI,WAAa,UAC9C,EAAI,UACJ,EAAI,UACJ,EAAI,WAAa,KACjB,EAAI,QACJ,EAAI,KAEG,EAAK,EAAO,CAAK,EAGnB,EAAI,MACb,CAEA,SAAS,EAAiB,EAA8B,EAAyB,CAC/E,OAAQ,GAAU,CAAC,EAAA,CAAG,IAAK,GAAU,EAAgB,EAAO,CAAK,CAAC,CACpE,CAEA,SAAS,EAAgB,EAAuB,CAC9C,IAAI,EAEJ,GAAI,CACF,EAAM,IAAI,IAAI,CAAK,CACrB,MAAQ,CACN,OAAO,EAAK,UAAW,CAAK,CAC9B,CAIA,OAFI,EAAI,WAAa,SAAW,EAAI,WAAa,SAAiB,EAAK,UAAW,CAAK,EAEhF,EAAI,IACb,CAEA,SAAS,EAAgB,EAAoE,CAC3F,IAAM,EAAqC,CAAC,EAE5C,IAAK,GAAM,CAAC,EAAI,KAAQ,OAAO,QAAQ,GAAU,CAAC,CAAC,GAC7C,CAAC,EAAG,KAAK,CAAE,GAAK,OAAO,GAAQ,WAAU,EAAK,cAAe,CAAE,EAEnE,EAAW,GAAM,EAGnB,OAAO,CACT,CAEA,SAAgB,EAAwB,EAA0B,CAAC,EAA6B,CAC9F,IAAM,EAAO,EAAQ,MAAQ,KAExB,EAAK,KAAK,CAAI,GAAG,EAAK,OAAQ,CAAI,EAEnC,EAAQ,QAAU,IAAA,KAAc,CAAC,EAAM,KAAK,EAAQ,KAAK,GAAK,EAAQ,MAAM,SAAW,IACzF,EAAK,QAAS,EAAQ,KAAK,EAGzB,EAAQ,QAAU,IAAA,IAAa,OAAO,EAAQ,OAAU,UAAU,EAAK,QAAS,EAAQ,KAAK,EAEjG,IAAM,GAAW,EAAQ,SAAW,CAAC,EAAA,CAAG,IAAI,CAAe,EAE3D,MAAO,CACL,mBAAoB,EAAiB,EAAQ,mBAAoB,oBAAoB,EACrF,oBAAqB,EAAiB,EAAQ,oBAAqB,qBAAqB,EACxF,qBAAsB,EAAiB,EAAQ,qBAAsB,sBAAsB,EAC3F,oBAAqB,EAAiB,EAAQ,oBAAqB,qBAAqB,EACxF,OACA,YAAa,EAAgB,EAAQ,WAAW,EAChD,MAAO,EAAQ,MACf,UACA,MAAO,EAAQ,OAAS,EAC1B,CACF,CAEA,SAAgB,EAAoB,EAA2C,CAC7E,IAAM,EAAgB,CACpB,kBACA,GAAI,EAAQ,MAAQ,CAAC,UAAU,EAAQ,MAAM,EAAE,EAAI,CAAC,EACpD,GAAG,EAAQ,qBACX,GAAG,EAAQ,QAAQ,IAAK,GAAW,IAAI,IAAI,CAAM,CAAC,CAAC,MAAM,CAC3D,CAAC,CAAC,KAAK,GAAG,EACJ,EAAe,CAAC,kBAAmB,GAAG,EAAQ,mBAAmB,CAAC,CAAC,KAAK,GAAG,EAC3E,EAAe,CAAC,QAAS,GAAG,EAAQ,mBAAmB,CAAC,CAAC,KAAK,GAAG,EACjE,EAAc,EAAQ,mBAAmB,KAAK,GAAG,GAAK,SAE5D,MAAO,CACL,qBACA,cAAc,IACd,aAAa,IACb,WAAW,IACX,YAAY,IACZ,qBACA,qBACA,iBACF,CAAC,CAAC,KAAK,IAAI,CACb"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SandboxOptions } from './types.js';
|
|
2
|
+
export interface NormalizedSandboxOptions {
|
|
3
|
+
allowedFontOrigins: string[];
|
|
4
|
+
allowedImageOrigins: string[];
|
|
5
|
+
allowedScriptOrigins: string[];
|
|
6
|
+
allowedStyleOrigins: string[];
|
|
7
|
+
lang: string;
|
|
8
|
+
namedStyles: Record<string, string>;
|
|
9
|
+
nonce: string | undefined;
|
|
10
|
+
scripts: string[];
|
|
11
|
+
title: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function normalizeSandboxOptions(options?: SandboxOptions): NormalizedSandboxOptions;
|
|
14
|
+
export declare function buildCspFromOptions(options: NormalizedSandboxOptions): string;
|
|
15
|
+
//# sourceMappingURL=_policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_policy.d.ts","sourceRoot":"","sources":["../src/_policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD,MAAM,WAAW,wBAAwB;IACvC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AA+DD,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,cAAmB,GAAG,wBAAwB,CAwB9F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAqB7E"}
|
package/dist/_policy.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { SandboxConfigurationError as e } from "./errors.js";
|
|
2
|
+
//#region src/_policy.ts
|
|
3
|
+
var t = /^[A-Za-z][A-Za-z0-9_-]*$/, n = /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/, r = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
4
|
+
function i(t, n) {
|
|
5
|
+
throw new e(`${t} is invalid: ${String(n)}`);
|
|
6
|
+
}
|
|
7
|
+
function a(e, t) {
|
|
8
|
+
let n;
|
|
9
|
+
try {
|
|
10
|
+
n = new URL(e);
|
|
11
|
+
} catch {
|
|
12
|
+
return i(t, e);
|
|
13
|
+
}
|
|
14
|
+
return n.protocol !== "http:" && n.protocol !== "https:" || n.username || n.password || n.pathname !== "/" || n.search || n.hash ? i(t, e) : n.origin;
|
|
15
|
+
}
|
|
16
|
+
function o(e, t) {
|
|
17
|
+
return (e ?? []).map((e) => a(e, t));
|
|
18
|
+
}
|
|
19
|
+
function s(e) {
|
|
20
|
+
let t;
|
|
21
|
+
try {
|
|
22
|
+
t = new URL(e);
|
|
23
|
+
} catch {
|
|
24
|
+
return i("scripts", e);
|
|
25
|
+
}
|
|
26
|
+
return t.protocol !== "http:" && t.protocol !== "https:" ? i("scripts", e) : t.href;
|
|
27
|
+
}
|
|
28
|
+
function c(e) {
|
|
29
|
+
let n = {};
|
|
30
|
+
for (let [r, a] of Object.entries(e ?? {})) (!t.test(r) || typeof a != "string") && i("namedStyles", r), n[r] = a;
|
|
31
|
+
return n;
|
|
32
|
+
}
|
|
33
|
+
function l(e = {}) {
|
|
34
|
+
let t = e.lang ?? "en";
|
|
35
|
+
n.test(t) || i("lang", t), e.nonce !== void 0 && (!r.test(e.nonce) || e.nonce.length === 0) && i("nonce", e.nonce), e.title !== void 0 && typeof e.title != "string" && i("title", e.title);
|
|
36
|
+
let a = (e.scripts ?? []).map(s);
|
|
37
|
+
return {
|
|
38
|
+
allowedFontOrigins: o(e.allowedFontOrigins, "allowedFontOrigins"),
|
|
39
|
+
allowedImageOrigins: o(e.allowedImageOrigins, "allowedImageOrigins"),
|
|
40
|
+
allowedScriptOrigins: o(e.allowedScriptOrigins, "allowedScriptOrigins"),
|
|
41
|
+
allowedStyleOrigins: o(e.allowedStyleOrigins, "allowedStyleOrigins"),
|
|
42
|
+
lang: t,
|
|
43
|
+
namedStyles: c(e.namedStyles),
|
|
44
|
+
nonce: e.nonce,
|
|
45
|
+
scripts: a,
|
|
46
|
+
title: e.title ?? ""
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function u(e) {
|
|
50
|
+
let t = [
|
|
51
|
+
"'unsafe-inline'",
|
|
52
|
+
...e.nonce ? [`'nonce-${e.nonce}'`] : [],
|
|
53
|
+
...e.allowedScriptOrigins,
|
|
54
|
+
...e.scripts.map((e) => new URL(e).origin)
|
|
55
|
+
].join(" "), n = ["'unsafe-inline'", ...e.allowedStyleOrigins].join(" "), r = ["data:", ...e.allowedImageOrigins].join(" "), i = e.allowedFontOrigins.join(" ") || "'none'";
|
|
56
|
+
return [
|
|
57
|
+
"default-src 'none'",
|
|
58
|
+
`script-src ${t}`,
|
|
59
|
+
`style-src ${n}`,
|
|
60
|
+
`img-src ${r}`,
|
|
61
|
+
`font-src ${i}`,
|
|
62
|
+
"connect-src 'none'",
|
|
63
|
+
"form-action 'none'",
|
|
64
|
+
"base-uri 'none'"
|
|
65
|
+
].join("; ");
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { u as buildCspFromOptions, l as normalizeSandboxOptions };
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=_policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_policy.js","names":[],"sources":["../src/_policy.ts"],"sourcesContent":["import type { SandboxOptions } from './types.js';\n\nimport { SandboxConfigurationError } from './errors.js';\n\nexport interface NormalizedSandboxOptions {\n allowedFontOrigins: string[];\n allowedImageOrigins: string[];\n allowedScriptOrigins: string[];\n allowedStyleOrigins: string[];\n lang: string;\n namedStyles: Record<string, string>;\n nonce: string | undefined;\n scripts: string[];\n title: string;\n}\n\nconst ID = /^[A-Za-z][A-Za-z0-9_-]*$/;\nconst LANG = /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;\nconst NONCE = /^[A-Za-z0-9+/_-]+={0,2}$/;\n\nfunction fail(field: string, value: unknown): never {\n throw new SandboxConfigurationError(`${field} is invalid: ${String(value)}`);\n}\n\nfunction normalizeOrigin(value: string, field: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n return fail(field, value);\n }\n\n if (\n (url.protocol !== 'http:' && url.protocol !== 'https:') ||\n url.username ||\n url.password ||\n url.pathname !== '/' ||\n url.search ||\n url.hash\n ) {\n return fail(field, value);\n }\n\n return url.origin;\n}\n\nfunction normalizeOrigins(values: string[] | undefined, field: string): string[] {\n return (values ?? []).map((value) => normalizeOrigin(value, field));\n}\n\nfunction normalizeScript(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n return fail('scripts', value);\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return fail('scripts', value);\n\n return url.href;\n}\n\nfunction normalizeStyles(styles: Record<string, string> | undefined): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [id, css] of Object.entries(styles ?? {})) {\n if (!ID.test(id) || typeof css !== 'string') fail('namedStyles', id);\n\n normalized[id] = css;\n }\n\n return normalized;\n}\n\nexport function normalizeSandboxOptions(options: SandboxOptions = {}): NormalizedSandboxOptions {\n const lang = options.lang ?? 'en';\n\n if (!LANG.test(lang)) fail('lang', lang);\n\n if (options.nonce !== undefined && (!NONCE.test(options.nonce) || options.nonce.length === 0)) {\n fail('nonce', options.nonce);\n }\n\n if (options.title !== undefined && typeof options.title !== 'string') fail('title', options.title);\n\n const scripts = (options.scripts ?? []).map(normalizeScript);\n\n return {\n allowedFontOrigins: normalizeOrigins(options.allowedFontOrigins, 'allowedFontOrigins'),\n allowedImageOrigins: normalizeOrigins(options.allowedImageOrigins, 'allowedImageOrigins'),\n allowedScriptOrigins: normalizeOrigins(options.allowedScriptOrigins, 'allowedScriptOrigins'),\n allowedStyleOrigins: normalizeOrigins(options.allowedStyleOrigins, 'allowedStyleOrigins'),\n lang,\n namedStyles: normalizeStyles(options.namedStyles),\n nonce: options.nonce,\n scripts,\n title: options.title ?? '',\n };\n}\n\nexport function buildCspFromOptions(options: NormalizedSandboxOptions): string {\n const scriptOrigins = [\n \"'unsafe-inline'\",\n ...(options.nonce ? [`'nonce-${options.nonce}'`] : []),\n ...options.allowedScriptOrigins,\n ...options.scripts.map((script) => new URL(script).origin),\n ].join(' ');\n const styleOrigins = [\"'unsafe-inline'\", ...options.allowedStyleOrigins].join(' ');\n const imageOrigins = ['data:', ...options.allowedImageOrigins].join(' ');\n const fontOrigins = options.allowedFontOrigins.join(' ') || \"'none'\";\n\n return [\n \"default-src 'none'\",\n `script-src ${scriptOrigins}`,\n `style-src ${styleOrigins}`,\n `img-src ${imageOrigins}`,\n `font-src ${fontOrigins}`,\n \"connect-src 'none'\",\n \"form-action 'none'\",\n \"base-uri 'none'\",\n ].join('; ');\n}\n"],"mappings":";;AAgBA,IAAM,IAAK,4BACL,IAAO,yCACP,IAAQ;AAEd,SAAS,EAAK,GAAe,GAAuB;CAClD,MAAM,IAAI,EAA0B,GAAG,EAAM,eAAe,OAAO,CAAK,GAAG;AAC7E;AAEA,SAAS,EAAgB,GAAe,GAAuB;CAC7D,IAAI;CAEJ,IAAI;EACF,IAAM,IAAI,IAAI,CAAK;CACrB,QAAQ;EACN,OAAO,EAAK,GAAO,CAAK;CAC1B;CAaA,OAVG,EAAI,aAAa,WAAW,EAAI,aAAa,YAC9C,EAAI,YACJ,EAAI,YACJ,EAAI,aAAa,OACjB,EAAI,UACJ,EAAI,OAEG,EAAK,GAAO,CAAK,IAGnB,EAAI;AACb;AAEA,SAAS,EAAiB,GAA8B,GAAyB;CAC/E,QAAQ,KAAU,CAAC,EAAA,CAAG,KAAK,MAAU,EAAgB,GAAO,CAAK,CAAC;AACpE;AAEA,SAAS,EAAgB,GAAuB;CAC9C,IAAI;CAEJ,IAAI;EACF,IAAM,IAAI,IAAI,CAAK;CACrB,QAAQ;EACN,OAAO,EAAK,WAAW,CAAK;CAC9B;CAIA,OAFI,EAAI,aAAa,WAAW,EAAI,aAAa,WAAiB,EAAK,WAAW,CAAK,IAEhF,EAAI;AACb;AAEA,SAAS,EAAgB,GAAoE;CAC3F,IAAM,IAAqC,CAAC;CAE5C,KAAK,IAAM,CAAC,GAAI,MAAQ,OAAO,QAAQ,KAAU,CAAC,CAAC,GAGjD,CAFI,CAAC,EAAG,KAAK,CAAE,KAAK,OAAO,KAAQ,aAAU,EAAK,eAAe,CAAE,GAEnE,EAAW,KAAM;CAGnB,OAAO;AACT;AAEA,SAAgB,EAAwB,IAA0B,CAAC,GAA6B;CAC9F,IAAM,IAAO,EAAQ,QAAQ;CAQ7B,AANK,EAAK,KAAK,CAAI,KAAG,EAAK,QAAQ,CAAI,GAEnC,EAAQ,UAAU,KAAA,MAAc,CAAC,EAAM,KAAK,EAAQ,KAAK,KAAK,EAAQ,MAAM,WAAW,MACzF,EAAK,SAAS,EAAQ,KAAK,GAGzB,EAAQ,UAAU,KAAA,KAAa,OAAO,EAAQ,SAAU,YAAU,EAAK,SAAS,EAAQ,KAAK;CAEjG,IAAM,KAAW,EAAQ,WAAW,CAAC,EAAA,CAAG,IAAI,CAAe;CAE3D,OAAO;EACL,oBAAoB,EAAiB,EAAQ,oBAAoB,oBAAoB;EACrF,qBAAqB,EAAiB,EAAQ,qBAAqB,qBAAqB;EACxF,sBAAsB,EAAiB,EAAQ,sBAAsB,sBAAsB;EAC3F,qBAAqB,EAAiB,EAAQ,qBAAqB,qBAAqB;EACxF;EACA,aAAa,EAAgB,EAAQ,WAAW;EAChD,OAAO,EAAQ;EACf;EACA,OAAO,EAAQ,SAAS;CAC1B;AACF;AAEA,SAAgB,EAAoB,GAA2C;CAC7E,IAAM,IAAgB;EACpB;EACA,GAAI,EAAQ,QAAQ,CAAC,UAAU,EAAQ,MAAM,EAAE,IAAI,CAAC;EACpD,GAAG,EAAQ;EACX,GAAG,EAAQ,QAAQ,KAAK,MAAW,IAAI,IAAI,CAAM,CAAC,CAAC,MAAM;CAC3D,CAAC,CAAC,KAAK,GAAG,GACJ,IAAe,CAAC,mBAAmB,GAAG,EAAQ,mBAAmB,CAAC,CAAC,KAAK,GAAG,GAC3E,IAAe,CAAC,SAAS,GAAG,EAAQ,mBAAmB,CAAC,CAAC,KAAK,GAAG,GACjE,IAAc,EAAQ,mBAAmB,KAAK,GAAG,KAAK;CAE5D,OAAO;EACL;EACA,cAAc;EACd,aAAa;EACb,WAAW;EACX,YAAY;EACZ;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=`custom`,t=`error`,n=`html-replace`,r=`ready`,i=`resize`,a=`state-update`,o=`state-update-all`,s=`style-patch`;function c(e,t){return typeof e==`object`&&!!e&&typeof e.channel==`string`&&e.channel===t.channel&&typeof e.generation==`number`&&e.generation===t.generation&&typeof e.type==`string`}function l(){if(typeof crypto.randomUUID==`function`)return crypto.randomUUID();let e=crypto.getRandomValues(new Uint32Array(4));return Array.from(e,e=>e.toString(16).padStart(8,`0`)).join(``)}function u(e,t){return{...t,channel:e.channel,generation:e.generation}}exports.MSG_CUSTOM=e,exports.MSG_ERROR=t,exports.MSG_HTML_REPLACE=n,exports.MSG_READY=r,exports.MSG_RESIZE=i,exports.MSG_STATE_UPDATE=a,exports.MSG_STATE_UPDATE_ALL=o,exports.MSG_STYLE_PATCH=s,exports.createChannel=l,exports.envelope=u,exports.isProtocolMessage=c;
|
|
2
|
+
//# sourceMappingURL=_protocol.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_protocol.cjs","names":[],"sources":["../src/_protocol.ts"],"sourcesContent":["export const MSG_CUSTOM = 'custom';\nexport const MSG_ERROR = 'error';\nexport const MSG_HTML_REPLACE = 'html-replace';\nexport const MSG_READY = 'ready';\nexport const MSG_RESIZE = 'resize';\nexport const MSG_STATE_UPDATE = 'state-update';\nexport const MSG_STATE_UPDATE_ALL = 'state-update-all';\nexport const MSG_STYLE_PATCH = 'style-patch';\n\nexport interface BridgeBootstrap {\n channel: string;\n generation: number;\n}\n\nexport type ProtocolMessage = Record<string, unknown> & { channel: string; generation: number; type: string };\n\nexport function isProtocolMessage(value: unknown, bootstrap: BridgeBootstrap): value is ProtocolMessage {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { channel?: unknown }).channel === 'string' &&\n (value as { channel: string }).channel === bootstrap.channel &&\n typeof (value as { generation?: unknown }).generation === 'number' &&\n (value as { generation: number }).generation === bootstrap.generation &&\n typeof (value as { type?: unknown }).type === 'string'\n );\n}\n\nexport function createChannel(): string {\n if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n\n const bytes = crypto.getRandomValues(new Uint32Array(4));\n\n return Array.from(bytes, (byte) => byte.toString(16).padStart(8, '0')).join('');\n}\n\nexport function envelope(bootstrap: BridgeBootstrap, message: Record<string, unknown>): ProtocolMessage {\n return { ...message, channel: bootstrap.channel, generation: bootstrap.generation } as ProtocolMessage;\n}\n"],"mappings":"AAAA,IAAa,EAAa,SACb,EAAY,QACZ,EAAmB,eACnB,EAAY,QACZ,EAAa,SACb,EAAmB,eACnB,EAAuB,mBACvB,EAAkB,cAS/B,SAAgB,EAAkB,EAAgB,EAAsD,CACtG,OACE,OAAO,GAAU,YACjB,GACA,OAAQ,EAAgC,SAAY,UACnD,EAA8B,UAAY,EAAU,SACrD,OAAQ,EAAmC,YAAe,UACzD,EAAiC,aAAe,EAAU,YAC3D,OAAQ,EAA6B,MAAS,QAElD,CAEA,SAAgB,GAAwB,CACtC,GAAI,OAAO,OAAO,YAAe,WAAY,OAAO,OAAO,WAAW,EAEtE,IAAM,EAAQ,OAAO,gBAAgB,IAAI,YAAY,CAAC,CAAC,EAEvD,OAAO,MAAM,KAAK,EAAQ,GAAS,EAAK,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAChF,CAEA,SAAgB,EAAS,EAA4B,EAAmD,CACtG,MAAO,CAAE,GAAG,EAAS,QAAS,EAAU,QAAS,WAAY,EAAU,UAAW,CACpF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const MSG_CUSTOM = "custom";
|
|
2
|
+
export declare const MSG_ERROR = "error";
|
|
3
|
+
export declare const MSG_HTML_REPLACE = "html-replace";
|
|
4
|
+
export declare const MSG_READY = "ready";
|
|
5
|
+
export declare const MSG_RESIZE = "resize";
|
|
6
|
+
export declare const MSG_STATE_UPDATE = "state-update";
|
|
7
|
+
export declare const MSG_STATE_UPDATE_ALL = "state-update-all";
|
|
8
|
+
export declare const MSG_STYLE_PATCH = "style-patch";
|
|
9
|
+
export interface BridgeBootstrap {
|
|
10
|
+
channel: string;
|
|
11
|
+
generation: number;
|
|
12
|
+
}
|
|
13
|
+
export type ProtocolMessage = Record<string, unknown> & {
|
|
14
|
+
channel: string;
|
|
15
|
+
generation: number;
|
|
16
|
+
type: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function isProtocolMessage(value: unknown, bootstrap: BridgeBootstrap): value is ProtocolMessage;
|
|
19
|
+
export declare function createChannel(): string;
|
|
20
|
+
export declare function envelope(bootstrap: BridgeBootstrap, message: Record<string, unknown>): ProtocolMessage;
|
|
21
|
+
//# sourceMappingURL=_protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_protocol.d.ts","sourceRoot":"","sources":["../src/_protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,WAAW,CAAC;AACnC,eAAO,MAAM,SAAS,UAAU,CAAC;AACjC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,SAAS,UAAU,CAAC;AACjC,eAAO,MAAM,UAAU,WAAW,CAAC;AACnC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,GAAG,KAAK,IAAI,eAAe,CAUtG;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAEtG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/_protocol.ts
|
|
2
|
+
var e = "custom", t = "error", n = "html-replace", r = "ready", i = "resize", a = "state-update", o = "state-update-all", s = "style-patch";
|
|
3
|
+
function c(e, t) {
|
|
4
|
+
return typeof e == "object" && !!e && typeof e.channel == "string" && e.channel === t.channel && typeof e.generation == "number" && e.generation === t.generation && typeof e.type == "string";
|
|
5
|
+
}
|
|
6
|
+
function l() {
|
|
7
|
+
if (typeof crypto.randomUUID == "function") return crypto.randomUUID();
|
|
8
|
+
let e = crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(4));
|
|
9
|
+
return Array.from(e, (e) => e.toString(16).padStart(8, "0")).join("");
|
|
10
|
+
}
|
|
11
|
+
function u(e, t) {
|
|
12
|
+
return {
|
|
13
|
+
...t,
|
|
14
|
+
channel: e.channel,
|
|
15
|
+
generation: e.generation
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { e as MSG_CUSTOM, t as MSG_ERROR, n as MSG_HTML_REPLACE, r as MSG_READY, i as MSG_RESIZE, a as MSG_STATE_UPDATE, o as MSG_STATE_UPDATE_ALL, s as MSG_STYLE_PATCH, l as createChannel, u as envelope, c as isProtocolMessage };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=_protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_protocol.js","names":[],"sources":["../src/_protocol.ts"],"sourcesContent":["export const MSG_CUSTOM = 'custom';\nexport const MSG_ERROR = 'error';\nexport const MSG_HTML_REPLACE = 'html-replace';\nexport const MSG_READY = 'ready';\nexport const MSG_RESIZE = 'resize';\nexport const MSG_STATE_UPDATE = 'state-update';\nexport const MSG_STATE_UPDATE_ALL = 'state-update-all';\nexport const MSG_STYLE_PATCH = 'style-patch';\n\nexport interface BridgeBootstrap {\n channel: string;\n generation: number;\n}\n\nexport type ProtocolMessage = Record<string, unknown> & { channel: string; generation: number; type: string };\n\nexport function isProtocolMessage(value: unknown, bootstrap: BridgeBootstrap): value is ProtocolMessage {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { channel?: unknown }).channel === 'string' &&\n (value as { channel: string }).channel === bootstrap.channel &&\n typeof (value as { generation?: unknown }).generation === 'number' &&\n (value as { generation: number }).generation === bootstrap.generation &&\n typeof (value as { type?: unknown }).type === 'string'\n );\n}\n\nexport function createChannel(): string {\n if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n\n const bytes = crypto.getRandomValues(new Uint32Array(4));\n\n return Array.from(bytes, (byte) => byte.toString(16).padStart(8, '0')).join('');\n}\n\nexport function envelope(bootstrap: BridgeBootstrap, message: Record<string, unknown>): ProtocolMessage {\n return { ...message, channel: bootstrap.channel, generation: bootstrap.generation } as ProtocolMessage;\n}\n"],"mappings":";AAAA,IAAa,IAAa,UACb,IAAY,SACZ,IAAmB,gBACnB,IAAY,SACZ,IAAa,UACb,IAAmB,gBACnB,IAAuB,oBACvB,IAAkB;AAS/B,SAAgB,EAAkB,GAAgB,GAAsD;CACtG,OACE,OAAO,KAAU,cACjB,KACA,OAAQ,EAAgC,WAAY,YACnD,EAA8B,YAAY,EAAU,WACrD,OAAQ,EAAmC,cAAe,YACzD,EAAiC,eAAe,EAAU,cAC3D,OAAQ,EAA6B,QAAS;AAElD;AAEA,SAAgB,IAAwB;CACtC,IAAI,OAAO,OAAO,cAAe,YAAY,OAAO,OAAO,WAAW;CAEtE,IAAM,IAAQ,OAAO,gCAAgB,IAAI,YAAY,CAAC,CAAC;CAEvD,OAAO,MAAM,KAAK,IAAQ,MAAS,EAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AAChF;AAEA,SAAgB,EAAS,GAA4B,GAAmD;CACtG,OAAO;EAAE,GAAG;EAAS,SAAS,EAAU;EAAS,YAAY,EAAU;CAAW;AACpF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_policy.cjs"),n=require("./_document.cjs");require("./_dev.cjs");const r=require("./_protocol.cjs");var i=5e3;function a(a,o={}){let s=t.normalizeSandboxOptions(o),c=r.createChannel(),l={...s.namedStyles},u=new Set,d=new AbortController,f=null,p=!1,m=!1,h=0,g=null,_=null,v,y=new Promise(e=>{v=e});function b(){return{channel:c,generation:h}}function x(){g!==null&&(clearTimeout(g),g=null)}function S(){x(),_?.resolve(),_=null,m=!1}function C(e){for(let t of u)t(e)}function w(e){if(!f||e.source!==f.contentWindow)return;let t=b();if(r.isProtocolMessage(e.data,t))switch(e.data.type){case r.MSG_CUSTOM:typeof e.data.event==`string`&&C({detail:e.data.detail,event:e.data.event,type:r.MSG_CUSTOM});break;case r.MSG_ERROR:typeof e.data.message==`string`&&C({message:e.data.message,...typeof e.data.stack==`string`?{stack:e.data.stack}:{},type:r.MSG_ERROR});break;case r.MSG_READY:S(),v(),m=!0;break;case r.MSG_RESIZE:typeof e.data.height==`number`&&Number.isFinite(e.data.height)&&e.data.height>=0&&C({height:e.data.height,type:r.MSG_RESIZE})}}function T(){return f||(f=document.createElement(`iframe`),f.setAttribute(`sandbox`,`allow-scripts`),f.setAttribute(`referrerpolicy`,`no-referrer`),f.dataset.sandboxChannel=c,a.appendChild(f),window.addEventListener(`message`,w),f)}function E(){p||(p=!0,S(),d.abort(),v(),f&&=(window.removeEventListener(`message`,w),f.remove(),null),u.clear())}function D(e){return p?()=>{}:(u.add(e),()=>u.delete(e))}function O(t,r){if(p||r?.signal?.aborted)return Promise.resolve();t.trim(),S(),h+=1;let a=T(),o=b(),c={...s,namedStyles:{...l}};a.dataset.sandboxGeneration=String(h),a.srcdoc=n.buildRuntimeDocument(t,c,o);let u=new Promise((e,t)=>{_={reject:t,resolve:e}});return g=setTimeout(()=>{_&&(_.reject(new e.SandboxTimeoutError(`render() did not receive a 'ready' signal from the sandbox document within ${i}ms. The document is likely missing the bridge script — use buildDocument() to generate documents that include it.`)),_=null,g=null)},i),u}function k(e){f?.contentWindow?.postMessage(r.envelope(b(),e),`*`)}function A(e){p||!m||!f?.contentWindow||k({html:e,type:r.MSG_HTML_REPLACE})}function j(e,t){p||f?.contentWindow&&k({key:e,type:r.MSG_STATE_UPDATE,value:t})}function M(e){p||f?.contentWindow&&k({record:e,type:r.MSG_STATE_UPDATE_ALL})}function N(e,t){p||(l[e]=t,m&&f?.contentWindow&&k({css:t,id:e,type:r.MSG_STYLE_PATCH}))}return{get disposalSignal(){return d.signal},dispose:E,get disposed(){return p},onMessage:D,ready:y,render:O,replaceBody:A,setState:j,setStateAll:M,[Symbol.dispose](){E()},updateStyle:N}}exports.createSandbox=a;
|
|
2
|
+
//# sourceMappingURL=_runtime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_runtime.cjs","names":[],"sources":["../src/_runtime.ts"],"sourcesContent":["import type { SandboxHandle, SandboxMessage, SandboxOptions, Unsubscribe } from './types.js';\n\nimport { devOnly, warn } from './_dev.js';\nimport { buildRuntimeDocument } from './_document.js';\nimport { normalizeSandboxOptions } from './_policy.js';\nimport {\n createChannel,\n envelope,\n isProtocolMessage,\n MSG_CUSTOM,\n MSG_ERROR,\n MSG_HTML_REPLACE,\n MSG_READY,\n MSG_RESIZE,\n MSG_STATE_UPDATE,\n MSG_STATE_UPDATE_ALL,\n MSG_STYLE_PATCH,\n type BridgeBootstrap,\n} from './_protocol.js';\nimport { SandboxTimeoutError } from './errors.js';\n\nconst READY_TIMEOUT_MS = 5000;\n\nexport function createSandbox(container: HTMLElement, options: SandboxOptions = {}): SandboxHandle {\n const normalized = normalizeSandboxOptions(options);\n const channel = createChannel();\n const namedStyles: Record<string, string> = { ...normalized.namedStyles };\n const listeners = new Set<(message: SandboxMessage) => void>();\n const controller = new AbortController();\n let iframe: HTMLIFrameElement | null = null;\n let disposed = false;\n let bridgeReady = false;\n let generation = 0;\n let readyTimeout: ReturnType<typeof setTimeout> | null = null;\n let currentRender: { reject: (error: unknown) => void; resolve: () => void } | null = null;\n\n let resolveReady!: () => void;\n const ready = new Promise<void>((resolve) => {\n resolveReady = resolve;\n });\n\n function currentBootstrap(): BridgeBootstrap {\n return { channel, generation };\n }\n\n function clearReadyTimeout(): void {\n if (readyTimeout === null) return;\n\n clearTimeout(readyTimeout);\n readyTimeout = null;\n }\n\n function supersedePendingRender(): void {\n clearReadyTimeout();\n currentRender?.resolve();\n currentRender = null;\n bridgeReady = false;\n }\n\n function broadcast(message: SandboxMessage): void {\n for (const listener of listeners) listener(message);\n }\n\n function handleMessage(event: MessageEvent): void {\n if (!iframe || event.source !== iframe.contentWindow) return;\n\n const bootstrap = currentBootstrap();\n\n if (!isProtocolMessage(event.data, bootstrap)) return;\n\n switch (event.data.type) {\n case MSG_CUSTOM:\n if (typeof event.data.event === 'string') {\n broadcast({ detail: event.data.detail, event: event.data.event, type: MSG_CUSTOM });\n }\n\n break;\n case MSG_ERROR:\n if (typeof event.data.message === 'string') {\n broadcast({\n message: event.data.message,\n ...(typeof event.data.stack === 'string' ? { stack: event.data.stack } : {}),\n type: MSG_ERROR,\n });\n }\n\n break;\n case MSG_READY:\n supersedePendingRender();\n resolveReady();\n bridgeReady = true;\n break;\n case MSG_RESIZE:\n if (typeof event.data.height === 'number' && Number.isFinite(event.data.height) && event.data.height >= 0) {\n broadcast({ height: event.data.height, type: MSG_RESIZE });\n }\n\n break;\n }\n }\n\n function ensureIframe(): HTMLIFrameElement {\n if (iframe) return iframe;\n\n iframe = document.createElement('iframe');\n iframe.setAttribute('sandbox', 'allow-scripts');\n iframe.setAttribute('referrerpolicy', 'no-referrer');\n iframe.dataset.sandboxChannel = channel;\n container.appendChild(iframe);\n window.addEventListener('message', handleMessage);\n\n return iframe;\n }\n\n function dispose(): void {\n if (disposed) return;\n\n disposed = true;\n supersedePendingRender();\n controller.abort();\n resolveReady();\n\n if (iframe) {\n window.removeEventListener('message', handleMessage);\n iframe.remove();\n iframe = null;\n }\n\n listeners.clear();\n }\n\n function onMessage(handler: (message: SandboxMessage) => void): Unsubscribe {\n if (disposed) {\n warn('onMessage() called on a disposed sandbox — handler will never fire.');\n\n return () => {};\n }\n\n listeners.add(handler);\n\n return () => listeners.delete(handler);\n }\n\n function render(html: string, renderOptions?: { signal?: AbortSignal }): Promise<void> {\n if (disposed) {\n warn('render() called on a disposed sandbox.');\n\n return Promise.resolve();\n }\n\n if (renderOptions?.signal?.aborted) return Promise.resolve();\n\n if (!html.trim()) warn('render() called with empty HTML.');\n\n supersedePendingRender();\n generation += 1;\n\n const current = ensureIframe();\n const bootstrap = currentBootstrap();\n const documentOptions = { ...normalized, namedStyles: { ...namedStyles } };\n\n current.dataset.sandboxGeneration = String(generation);\n current.srcdoc = buildRuntimeDocument(html, documentOptions, bootstrap);\n\n const promise = new Promise<void>((resolve, reject) => {\n currentRender = { reject, resolve };\n });\n\n readyTimeout = setTimeout(() => {\n if (!currentRender) return;\n\n currentRender.reject(\n new SandboxTimeoutError(\n `render() did not receive a 'ready' signal from the sandbox document within ${READY_TIMEOUT_MS}ms. ` +\n 'The document is likely missing the bridge script — use buildDocument() to generate documents that include it.',\n ),\n );\n currentRender = null;\n readyTimeout = null;\n }, READY_TIMEOUT_MS);\n\n return promise;\n }\n\n function send(message: Record<string, unknown>): void {\n iframe?.contentWindow?.postMessage(envelope(currentBootstrap(), message), '*');\n }\n\n function replaceBody(html: string): void {\n if (disposed) {\n warn('replaceBody() called on a disposed sandbox.');\n\n return;\n }\n\n if (!bridgeReady || !iframe?.contentWindow) {\n warn('replaceBody() called before render() has resolved — bridge is not ready. Await render() first.');\n\n return;\n }\n\n send({ html, type: MSG_HTML_REPLACE });\n }\n\n function setState(key: string, value: unknown): void {\n if (disposed) {\n warn('setState() called on a disposed sandbox.');\n\n return;\n }\n\n if (!iframe?.contentWindow) {\n warn('setState() called before render() — sandbox has no document yet.');\n\n return;\n }\n\n if (!bridgeReady) {\n warn('setState() called before ready — state update may be lost. Await render() first.');\n }\n\n send({ key, type: MSG_STATE_UPDATE, value });\n }\n\n function setStateAll(record: Record<string, unknown>): void {\n if (disposed) {\n warn('setStateAll() called on a disposed sandbox.');\n\n return;\n }\n\n if (!iframe?.contentWindow) {\n warn('setStateAll() called before render() — sandbox has no document yet.');\n\n return;\n }\n\n if (!bridgeReady) {\n warn('setStateAll() called before ready — state updates may be lost. Await render() first.');\n }\n\n send({ record, type: MSG_STATE_UPDATE_ALL });\n }\n\n function updateStyle(id: string, css: string): void {\n if (disposed) return;\n\n devOnly(() => {\n if (!(id in namedStyles)) {\n warn(`updateStyle('${id}', …) — '${id}' is not a known namedStyles key.`);\n }\n });\n\n namedStyles[id] = css;\n\n if (bridgeReady && iframe?.contentWindow) send({ css, id, type: MSG_STYLE_PATCH });\n }\n\n return {\n get disposalSignal() {\n return controller.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n onMessage,\n ready,\n render,\n replaceBody,\n setState,\n setStateAll,\n [Symbol.dispose]() {\n dispose();\n },\n updateStyle,\n };\n}\n"],"mappings":"iJAqBA,IAAM,EAAmB,IAEzB,SAAgB,EAAc,EAAwB,EAA0B,CAAC,EAAkB,CACjG,IAAM,EAAa,EAAA,wBAAwB,CAAO,EAC5C,EAAU,EAAA,cAAc,EACxB,EAAsC,CAAE,GAAG,EAAW,WAAY,EAClE,EAAY,IAAI,IAChB,EAAa,IAAI,gBACnB,EAAmC,KACnC,EAAW,GACX,EAAc,GACd,EAAa,EACb,EAAqD,KACrD,EAAkF,KAElF,EACE,EAAQ,IAAI,QAAe,GAAY,CAC3C,EAAe,CACjB,CAAC,EAED,SAAS,GAAoC,CAC3C,MAAO,CAAE,UAAS,YAAW,CAC/B,CAEA,SAAS,GAA0B,CAC7B,IAAiB,OAErB,aAAa,CAAY,EACzB,EAAe,KACjB,CAEA,SAAS,GAA+B,CACtC,EAAkB,EAClB,GAAe,QAAQ,EACvB,EAAgB,KAChB,EAAc,EAChB,CAEA,SAAS,EAAU,EAA+B,CAChD,IAAK,IAAM,KAAY,EAAW,EAAS,CAAO,CACpD,CAEA,SAAS,EAAc,EAA2B,CAChD,GAAI,CAAC,GAAU,EAAM,SAAW,EAAO,cAAe,OAEtD,IAAM,EAAY,EAAiB,EAE9B,KAAA,kBAAkB,EAAM,KAAM,CAAS,EAE5C,OAAQ,EAAM,KAAK,KAAnB,CACE,KAAK,EAAA,WACC,OAAO,EAAM,KAAK,OAAU,UAC9B,EAAU,CAAE,OAAQ,EAAM,KAAK,OAAQ,MAAO,EAAM,KAAK,MAAO,KAAM,EAAA,UAAW,CAAC,EAGpF,MACF,KAAK,EAAA,UACC,OAAO,EAAM,KAAK,SAAY,UAChC,EAAU,CACR,QAAS,EAAM,KAAK,QACpB,GAAI,OAAO,EAAM,KAAK,OAAU,SAAW,CAAE,MAAO,EAAM,KAAK,KAAM,EAAI,CAAC,EAC1E,KAAM,EAAA,SACR,CAAC,EAGH,MACF,KAAK,EAAA,UACH,EAAuB,EACvB,EAAa,EACb,EAAc,GACd,MACF,KAAK,EAAA,WACC,OAAO,EAAM,KAAK,QAAW,UAAY,OAAO,SAAS,EAAM,KAAK,MAAM,GAAK,EAAM,KAAK,QAAU,GACtG,EAAU,CAAE,OAAQ,EAAM,KAAK,OAAQ,KAAM,EAAA,UAAW,CAAC,CAI/D,CACF,CAEA,SAAS,GAAkC,CAUzC,OATI,IAEJ,EAAS,SAAS,cAAc,QAAQ,EACxC,EAAO,aAAa,UAAW,eAAe,EAC9C,EAAO,aAAa,iBAAkB,aAAa,EACnD,EAAO,QAAQ,eAAiB,EAChC,EAAU,YAAY,CAAM,EAC5B,OAAO,iBAAiB,UAAW,CAAa,EAEzC,EACT,CAEA,SAAS,GAAgB,CACnB,IAEJ,EAAW,GACX,EAAuB,EACvB,EAAW,MAAM,EACjB,EAAa,EAEb,AAGE,KAFA,OAAO,oBAAoB,UAAW,CAAa,EACnD,EAAO,OAAO,EACL,MAGX,EAAU,MAAM,EAClB,CAEA,SAAS,EAAU,EAAyD,CAS1E,OARI,MAGW,CAAC,GAGhB,EAAU,IAAI,CAAO,MAER,EAAU,OAAO,CAAO,EACvC,CAEA,SAAS,EAAO,EAAc,EAAyD,CAOrF,GANI,GAMA,GAAe,QAAQ,QAAS,OAAO,QAAQ,QAAQ,EAEtD,EAAK,KAAK,EAEf,EAAuB,EACvB,GAAc,EAEd,IAAM,EAAU,EAAa,EACvB,EAAY,EAAiB,EAC7B,EAAkB,CAAE,GAAG,EAAY,YAAa,CAAE,GAAG,CAAY,CAAE,EAEzE,EAAQ,QAAQ,kBAAoB,OAAO,CAAU,EACrD,EAAQ,OAAS,EAAA,qBAAqB,EAAM,EAAiB,CAAS,EAEtE,IAAM,EAAU,IAAI,SAAe,EAAS,IAAW,CACrD,EAAgB,CAAE,SAAQ,SAAQ,CACpC,CAAC,EAeD,MAbA,GAAe,eAAiB,CACzB,IAEL,EAAc,OACZ,IAAI,EAAA,oBACF,8EAA8E,EAAiB,kHAEjG,CACF,EACA,EAAgB,KAChB,EAAe,KACjB,EAAG,CAAgB,EAEZ,CACT,CAEA,SAAS,EAAK,EAAwC,CACpD,GAAQ,eAAe,YAAY,EAAA,SAAS,EAAiB,EAAG,CAAO,EAAG,GAAG,CAC/E,CAEA,SAAS,EAAY,EAAoB,CACnC,GAMA,CAAC,GAAe,CAAC,GAAQ,eAM7B,EAAK,CAAE,OAAM,KAAM,EAAA,gBAAiB,CAAC,CACvC,CAEA,SAAS,EAAS,EAAa,EAAsB,CAC/C,GAMC,GAAQ,eAUb,EAAK,CAAE,MAAK,KAAM,EAAA,iBAAkB,OAAM,CAAC,CAC7C,CAEA,SAAS,EAAY,EAAuC,CACtD,GAMC,GAAQ,eAUb,EAAK,CAAE,SAAQ,KAAM,EAAA,oBAAqB,CAAC,CAC7C,CAEA,SAAS,EAAY,EAAY,EAAmB,CAC9C,IAQJ,EAAY,GAAM,EAEd,GAAe,GAAQ,eAAe,EAAK,CAAE,MAAK,KAAI,KAAM,EAAA,eAAgB,CAAC,EACnF,CAEA,MAAO,CACL,IAAI,gBAAiB,CACnB,OAAO,EAAW,MACpB,EACA,UACA,IAAI,UAAW,CACb,OAAO,CACT,EACA,YACA,QACA,SACA,cACA,WACA,cACA,CAAC,OAAO,UAAW,CACjB,EAAQ,CACV,EACA,aACF,CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_runtime.d.ts","sourceRoot":"","sources":["../src/_runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAkB,cAAc,EAAe,MAAM,YAAY,CAAC;AAuB7F,wBAAgB,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA8PjG"}
|