@parhelia/editor-bridge-head 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const PARHELIA_BRIDGE_HEAD_READY_MESSAGE = "parhelia:bridge-head-ready";
|
|
2
|
+
export declare const PARHELIA_BRIDGE_URL_MESSAGE = "parhelia:bridge-url";
|
|
3
|
+
export type BridgeHeadReadyMessage = {
|
|
4
|
+
type: typeof PARHELIA_BRIDGE_HEAD_READY_MESSAGE;
|
|
5
|
+
href: string;
|
|
6
|
+
};
|
|
7
|
+
export type BridgeUrlMessage = {
|
|
8
|
+
type: typeof PARHELIA_BRIDGE_URL_MESSAGE;
|
|
9
|
+
bridgeUrl: string;
|
|
10
|
+
};
|
|
11
|
+
export type EditorBridgeHeadOptions = {
|
|
12
|
+
allowedOrigins?: readonly string[];
|
|
13
|
+
autoAnnounce?: boolean;
|
|
14
|
+
scriptId?: string;
|
|
15
|
+
};
|
|
16
|
+
export type EditorBridgeHeadHandle = {
|
|
17
|
+
announceReady: () => void;
|
|
18
|
+
dispose: () => void;
|
|
19
|
+
loadBridge: (bridgeUrl: string) => HTMLScriptElement | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare function installEditorBridgeHead(options?: EditorBridgeHeadOptions): EditorBridgeHeadHandle | undefined;
|
|
22
|
+
export declare function getAutoInstalledEditorBridgeHead(): EditorBridgeHeadHandle | undefined;
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,+BACjB,CAAC;AAC/B,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AAIjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,OAAO,kCAAkC,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,2BAA2B,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;CAClE,CAAC;AAIF,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,GAAG,SAAS,CA8CpC;AAiFD,wBAAgB,gCAAgC,uCAE/C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export const PARHELIA_BRIDGE_HEAD_READY_MESSAGE = "parhelia:bridge-head-ready";
|
|
2
|
+
export const PARHELIA_BRIDGE_URL_MESSAGE = "parhelia:bridge-url";
|
|
3
|
+
const DEFAULT_SCRIPT_ID = "parhelia-editor-bridge";
|
|
4
|
+
let autoInstalledHandle;
|
|
5
|
+
export function installEditorBridgeHead(options = {}) {
|
|
6
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const scriptId = options.scriptId ?? DEFAULT_SCRIPT_ID;
|
|
10
|
+
const allowedOrigins = options.allowedOrigins ?? getAllowedOrigins();
|
|
11
|
+
const scriptNonce = getCurrentScriptNonce();
|
|
12
|
+
const loadBridge = (bridgeUrl) => loadBridgeScript(bridgeUrl, scriptId, scriptNonce);
|
|
13
|
+
const handleMessage = (event) => {
|
|
14
|
+
if (event.source !== window.parent)
|
|
15
|
+
return;
|
|
16
|
+
if (allowedOrigins.length > 0 && !allowedOrigins.includes(event.origin)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const message = parseBridgeUrlMessage(event.data);
|
|
20
|
+
if (!message)
|
|
21
|
+
return;
|
|
22
|
+
loadBridge(message.bridgeUrl);
|
|
23
|
+
};
|
|
24
|
+
const announceReady = () => {
|
|
25
|
+
if (window.parent === window)
|
|
26
|
+
return;
|
|
27
|
+
const message = {
|
|
28
|
+
type: PARHELIA_BRIDGE_HEAD_READY_MESSAGE,
|
|
29
|
+
href: window.location.href,
|
|
30
|
+
};
|
|
31
|
+
window.parent.postMessage(message, "*");
|
|
32
|
+
};
|
|
33
|
+
window.addEventListener("message", handleMessage);
|
|
34
|
+
if (options.autoAnnounce !== false) {
|
|
35
|
+
announceReady();
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
announceReady,
|
|
39
|
+
dispose: () => window.removeEventListener("message", handleMessage),
|
|
40
|
+
loadBridge,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function loadBridgeScript(bridgeUrl, scriptId, scriptNonce) {
|
|
44
|
+
const normalizedUrl = normalizeBridgeUrl(bridgeUrl);
|
|
45
|
+
if (!normalizedUrl)
|
|
46
|
+
return undefined;
|
|
47
|
+
const existingScript = document.getElementById(scriptId);
|
|
48
|
+
if (existingScript instanceof HTMLScriptElement) {
|
|
49
|
+
if (existingScript.src === normalizedUrl)
|
|
50
|
+
return existingScript;
|
|
51
|
+
existingScript.remove();
|
|
52
|
+
}
|
|
53
|
+
const script = document.createElement("script");
|
|
54
|
+
script.id = scriptId;
|
|
55
|
+
script.async = true;
|
|
56
|
+
script.src = normalizedUrl;
|
|
57
|
+
if (scriptNonce)
|
|
58
|
+
script.nonce = scriptNonce;
|
|
59
|
+
const parent = document.head ?? document.documentElement;
|
|
60
|
+
parent.appendChild(script);
|
|
61
|
+
return script;
|
|
62
|
+
}
|
|
63
|
+
function normalizeBridgeUrl(bridgeUrl) {
|
|
64
|
+
try {
|
|
65
|
+
const url = new URL(bridgeUrl, window.location.href);
|
|
66
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return url.href;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function parseBridgeUrlMessage(data) {
|
|
76
|
+
if (!isRecord(data))
|
|
77
|
+
return undefined;
|
|
78
|
+
if (data.type !== PARHELIA_BRIDGE_URL_MESSAGE)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (typeof data.bridgeUrl !== "string" || data.bridgeUrl.length === 0) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
type: PARHELIA_BRIDGE_URL_MESSAGE,
|
|
85
|
+
bridgeUrl: data.bridgeUrl,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function getAllowedOrigins() {
|
|
89
|
+
const origins = document.currentScript instanceof HTMLScriptElement
|
|
90
|
+
? document.currentScript.dataset.parheliaAllowedOrigins
|
|
91
|
+
: undefined;
|
|
92
|
+
return (origins
|
|
93
|
+
?.split(",")
|
|
94
|
+
.map((origin) => origin.trim())
|
|
95
|
+
.filter(Boolean) ?? []);
|
|
96
|
+
}
|
|
97
|
+
function getCurrentScriptNonce() {
|
|
98
|
+
return document.currentScript instanceof HTMLScriptElement
|
|
99
|
+
? (document.currentScript.nonce ?? "")
|
|
100
|
+
: "";
|
|
101
|
+
}
|
|
102
|
+
function isRecord(value) {
|
|
103
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
104
|
+
}
|
|
105
|
+
autoInstalledHandle = installEditorBridgeHead();
|
|
106
|
+
export function getAutoInstalledEditorBridgeHead() {
|
|
107
|
+
return autoInstalledHandle;
|
|
108
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@parhelia/editor-bridge-head",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"development": "./src/index.ts",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": true,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -p tsconfig.build.json",
|
|
24
|
+
"build:native": "tsgo -p tsconfig.build.json",
|
|
25
|
+
"lint": "tsc --noEmit -p tsconfig.build.json",
|
|
26
|
+
"check-types": "tsc --noEmit -p tsconfig.build.json",
|
|
27
|
+
"check-types:native": "tsgo --noEmit -p tsconfig.build.json"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@repo/typescript-config": "*",
|
|
31
|
+
"typescript": "5.8.2"
|
|
32
|
+
}
|
|
33
|
+
}
|