@preprio/toolkit 0.4.3 → 0.5.0-rc.10
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 +416 -23
- package/dist/astro/index.cjs +1290 -1
- package/dist/astro/index.d.cts +47 -1
- package/dist/astro/index.d.ts +47 -1
- package/dist/astro/index.js +1297 -1
- package/dist/chunk-F46GJS6Y.js +26 -0
- package/dist/{chunk-H7VA7NGY.js → chunk-IDEC77LZ.js} +1480 -621
- package/dist/chunk-IPMB32AZ.js +246 -0
- package/dist/chunk-KD3GK6TO.js +1221 -0
- package/dist/chunk-S3VT4UWM.js +75 -0
- package/dist/chunk-TBBU3LDD.js +184 -0
- package/dist/chunk-URXSDJOU.js +356 -0
- package/dist/codegen/index.cjs +82 -0
- package/dist/codegen/index.d.cts +70 -0
- package/dist/codegen/index.d.ts +70 -0
- package/dist/codegen/index.js +64 -0
- package/dist/index.cjs +3412 -409
- package/dist/index.d.cts +287 -5
- package/dist/index.d.ts +287 -5
- package/dist/index.js +307 -144
- package/dist/live-preview-DLXGXRE5.js +18 -0
- package/dist/nextjs/components.cjs +1662 -388
- package/dist/nextjs/components.d.cts +1 -1
- package/dist/nextjs/components.d.ts +1 -1
- package/dist/nextjs/components.js +4 -1
- package/dist/nextjs/index.cjs +1181 -6
- package/dist/nextjs/index.d.cts +83 -3
- package/dist/nextjs/index.d.ts +83 -3
- package/dist/nextjs/index.js +1179 -7
- package/dist/nextjs/live-action.cjs +285 -0
- package/dist/nextjs/live-action.d.cts +12 -0
- package/dist/nextjs/live-action.d.ts +12 -0
- package/dist/nextjs/live-action.js +68 -0
- package/dist/nextjs/live.cjs +1899 -0
- package/dist/nextjs/live.d.cts +54 -0
- package/dist/nextjs/live.d.ts +54 -0
- package/dist/nextjs/live.js +268 -0
- package/dist/nuxt/chunk-BWPGO25E.js +340 -0
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/nuxt/live-preview-2RCU35W5.js +1189 -0
- package/dist/nuxt/live.cjs +1816 -0
- package/dist/nuxt/live.d.cts +43 -0
- package/dist/nuxt/live.d.ts +43 -0
- package/dist/nuxt/live.js +198 -0
- package/dist/{pixel-e1fUWl2Y.d.cts → pixel-CX422dCO.d.cts} +18 -3
- package/dist/{pixel-e1fUWl2Y.d.ts → pixel-CX422dCO.d.ts} +18 -3
- package/dist/react/components.cjs +1662 -388
- package/dist/react/components.d.cts +17 -2
- package/dist/react/components.d.ts +17 -2
- package/dist/react/components.js +1662 -388
- package/dist/sveltekit/chunk-BWPGO25E.js +340 -0
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/dist/sveltekit/live-preview-2RCU35W5.js +1189 -0
- package/dist/sveltekit/live.cjs +1830 -0
- package/dist/sveltekit/live.d.cts +59 -0
- package/dist/sveltekit/live.d.ts +59 -0
- package/dist/sveltekit/live.js +204 -0
- package/package.json +37 -11
- package/src/astro/PreprToolbar.astro +7 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/core/utils.ts
|
|
2
|
+
var trustedParentOrigin = null;
|
|
3
|
+
function setTrustedParentOrigin(origin) {
|
|
4
|
+
trustedParentOrigin = origin;
|
|
5
|
+
}
|
|
6
|
+
function getTrustedParentOrigin() {
|
|
7
|
+
return trustedParentOrigin;
|
|
8
|
+
}
|
|
9
|
+
function sendPreprEvent(event, data, options) {
|
|
10
|
+
if (typeof window !== "undefined") {
|
|
11
|
+
const message = {
|
|
12
|
+
name: "prepr_preview_bar",
|
|
13
|
+
event,
|
|
14
|
+
...data
|
|
15
|
+
};
|
|
16
|
+
window.dispatchEvent(
|
|
17
|
+
new CustomEvent("prepr_preview_bar", { detail: message })
|
|
18
|
+
);
|
|
19
|
+
if (window.parent && window.parent !== window) {
|
|
20
|
+
if (trustedParentOrigin) {
|
|
21
|
+
window.parent.postMessage(message, trustedParentOrigin);
|
|
22
|
+
} else if (options?.allowUntrustedTarget) {
|
|
23
|
+
window.parent.postMessage(message, "*");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
var DebugLogger = class {
|
|
29
|
+
constructor(options) {
|
|
30
|
+
this.options = {
|
|
31
|
+
prefix: "[Prepr]",
|
|
32
|
+
...options
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// A local `enabled` wins; otherwise defer to the global logger so scoped
|
|
36
|
+
// loggers created before initDebugLogger() still pick up the setting.
|
|
37
|
+
isEnabled() {
|
|
38
|
+
if (this.options.enabled !== void 0) {
|
|
39
|
+
return this.options.enabled;
|
|
40
|
+
}
|
|
41
|
+
return globalDebugLogger?.options?.enabled ?? false;
|
|
42
|
+
}
|
|
43
|
+
log(message, ...args) {
|
|
44
|
+
if (!this.isEnabled()) return;
|
|
45
|
+
const prefix = this.options.prefix;
|
|
46
|
+
console.log(`${prefix} ${message}`, ...args);
|
|
47
|
+
}
|
|
48
|
+
warn(message, ...args) {
|
|
49
|
+
if (!this.isEnabled()) return;
|
|
50
|
+
const prefix = this.options.prefix;
|
|
51
|
+
console.warn(`${prefix} ${message}`, ...args);
|
|
52
|
+
}
|
|
53
|
+
error(message, ...args) {
|
|
54
|
+
if (!this.isEnabled()) return;
|
|
55
|
+
const prefix = this.options.prefix;
|
|
56
|
+
console.error(`${prefix} ${message}`, ...args);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var globalDebugLogger = null;
|
|
60
|
+
function initDebugLogger(enabled = false) {
|
|
61
|
+
globalDebugLogger = new DebugLogger({ enabled });
|
|
62
|
+
}
|
|
63
|
+
function createScopedLogger(scopeName) {
|
|
64
|
+
return new DebugLogger({
|
|
65
|
+
prefix: `[Prepr][${scopeName}]`
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
setTrustedParentOrigin,
|
|
71
|
+
getTrustedParentOrigin,
|
|
72
|
+
sendPreprEvent,
|
|
73
|
+
initDebugLogger,
|
|
74
|
+
createScopedLogger
|
|
75
|
+
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VERSION,
|
|
3
|
+
resolveFeatures
|
|
4
|
+
} from "./chunk-F46GJS6Y.js";
|
|
5
|
+
|
|
6
|
+
// src/core/server.ts
|
|
7
|
+
var PreprError = class extends Error {
|
|
8
|
+
constructor(message, code, context, originalError) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.context = context;
|
|
12
|
+
this.originalError = originalError;
|
|
13
|
+
this.name = "PreprError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function getPreprUUIDFromHeaders(headers) {
|
|
17
|
+
return headers.get("prepr-customer-id");
|
|
18
|
+
}
|
|
19
|
+
function getActiveSegmentFromHeaders(headers) {
|
|
20
|
+
return headers.get("Prepr-Segments");
|
|
21
|
+
}
|
|
22
|
+
function getActiveVariantFromHeaders(headers) {
|
|
23
|
+
return headers.get("Prepr-ABtesting");
|
|
24
|
+
}
|
|
25
|
+
var PREVIEW_PACKAGE_PART = /(?:^|;)\s*preview=true\s*(?:;|$)/;
|
|
26
|
+
function isPreviewFromHeaders(headers) {
|
|
27
|
+
return PREVIEW_PACKAGE_PART.test(headers.get("Prepr-Package") ?? "");
|
|
28
|
+
}
|
|
29
|
+
var PREPR_HEADER_KEYS = [
|
|
30
|
+
"prepr-customer-id",
|
|
31
|
+
"Prepr-Segments",
|
|
32
|
+
"Prepr-ABtesting",
|
|
33
|
+
"Prepr-Preview-Bar",
|
|
34
|
+
"Prepr-Context-utm_source",
|
|
35
|
+
"Prepr-Context-utm_medium",
|
|
36
|
+
"Prepr-Context-utm_term",
|
|
37
|
+
"Prepr-Context-utm_content",
|
|
38
|
+
"Prepr-Context-utm_campaign",
|
|
39
|
+
"Prepr-Context-initial_referral",
|
|
40
|
+
"Prepr-Visitor-IP",
|
|
41
|
+
"Prepr-Hubspot-Id",
|
|
42
|
+
"Prepr-Customer-Id-Created",
|
|
43
|
+
"User-Agent",
|
|
44
|
+
"Prepr-Package"
|
|
45
|
+
];
|
|
46
|
+
function getPreprHeadersFromHeaders(headers) {
|
|
47
|
+
const preprHeaders = {};
|
|
48
|
+
const copy = (key) => {
|
|
49
|
+
const value = headers.get(key);
|
|
50
|
+
if (value !== null) {
|
|
51
|
+
preprHeaders[key] = value;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
for (const key of PREPR_HEADER_KEYS) {
|
|
55
|
+
copy(key);
|
|
56
|
+
}
|
|
57
|
+
return preprHeaders;
|
|
58
|
+
}
|
|
59
|
+
function validatePreprToken(token) {
|
|
60
|
+
if (!token) {
|
|
61
|
+
throw new PreprError(
|
|
62
|
+
"Token is required",
|
|
63
|
+
"MISSING_TOKEN",
|
|
64
|
+
"validatePreprToken"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (!token.startsWith("https://")) {
|
|
68
|
+
throw new PreprError(
|
|
69
|
+
"Token must be a valid HTTPS URL",
|
|
70
|
+
"INVALID_TOKEN",
|
|
71
|
+
"validatePreprToken"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function extractAccessToken(graphqlUrl) {
|
|
76
|
+
let url;
|
|
77
|
+
try {
|
|
78
|
+
url = new URL(graphqlUrl);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new PreprError(
|
|
81
|
+
"Token must be a valid URL",
|
|
82
|
+
"INVALID_TOKEN",
|
|
83
|
+
"extractAccessToken",
|
|
84
|
+
error instanceof Error ? error : new Error(String(error))
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (url.hostname !== "graphql.prepr.io") {
|
|
88
|
+
throw new PreprError(
|
|
89
|
+
"Token must be a graphql.prepr.io URL",
|
|
90
|
+
"INVALID_TOKEN",
|
|
91
|
+
"extractAccessToken"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
const pathParts = url.pathname.split("/");
|
|
95
|
+
const token = pathParts[pathParts.length - 1];
|
|
96
|
+
if (!token) {
|
|
97
|
+
throw new PreprError(
|
|
98
|
+
"Token URL is missing an access token segment",
|
|
99
|
+
"INVALID_TOKEN",
|
|
100
|
+
"extractAccessToken"
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return token;
|
|
104
|
+
}
|
|
105
|
+
async function getPreprEnvironmentSegments(token) {
|
|
106
|
+
validatePreprToken(token);
|
|
107
|
+
try {
|
|
108
|
+
const response = await fetch(token, {
|
|
109
|
+
headers: {
|
|
110
|
+
"Prepr-Package": `@preprio/toolkit@${VERSION}`,
|
|
111
|
+
// Duplicates the version in Prepr-Package. It keeps the User-Agent
|
|
112
|
+
// format used by `@preprio/prepr-nextjs`, for Prepr API consumers that
|
|
113
|
+
// still identify the toolbar by that string.
|
|
114
|
+
"User-Agent": `Prepr-Preview-Bar/${VERSION}`,
|
|
115
|
+
"Content-Type": "application/json"
|
|
116
|
+
},
|
|
117
|
+
method: "POST",
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
query: `{
|
|
120
|
+
_Segments {
|
|
121
|
+
_id
|
|
122
|
+
name
|
|
123
|
+
}
|
|
124
|
+
}`
|
|
125
|
+
})
|
|
126
|
+
});
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
throw new PreprError(
|
|
129
|
+
`HTTP ${response.status}: ${response.statusText}`,
|
|
130
|
+
"HTTP_ERROR",
|
|
131
|
+
"getPreprEnvironmentSegments"
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const json = await response.json();
|
|
135
|
+
if (!json || !json.data || !json.data._Segments) {
|
|
136
|
+
throw new PreprError(
|
|
137
|
+
"Invalid response format from Prepr API",
|
|
138
|
+
"INVALID_RESPONSE",
|
|
139
|
+
"getPreprEnvironmentSegments"
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return json.data._Segments;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof PreprError) {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
throw new PreprError(
|
|
148
|
+
"Failed to fetch segments from Prepr API",
|
|
149
|
+
"FETCH_ERROR",
|
|
150
|
+
"getPreprEnvironmentSegments",
|
|
151
|
+
error instanceof Error ? error : new Error(String(error))
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async function getToolbarPropsFromHeaders(headers, token, features) {
|
|
156
|
+
const resolved = resolveFeatures(features);
|
|
157
|
+
let segments = [];
|
|
158
|
+
if (resolved.segments) {
|
|
159
|
+
try {
|
|
160
|
+
segments = await getPreprEnvironmentSegments(token);
|
|
161
|
+
} catch {
|
|
162
|
+
segments = [];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
activeSegment: resolved.segments ? getActiveSegmentFromHeaders(headers) : null,
|
|
167
|
+
activeVariant: resolved.abTesting ? getActiveVariantFromHeaders(headers) : null,
|
|
168
|
+
segments,
|
|
169
|
+
data: segments
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export {
|
|
174
|
+
PreprError,
|
|
175
|
+
getPreprUUIDFromHeaders,
|
|
176
|
+
getActiveSegmentFromHeaders,
|
|
177
|
+
getActiveVariantFromHeaders,
|
|
178
|
+
isPreviewFromHeaders,
|
|
179
|
+
getPreprHeadersFromHeaders,
|
|
180
|
+
validatePreprToken,
|
|
181
|
+
extractAccessToken,
|
|
182
|
+
getPreprEnvironmentSegments,
|
|
183
|
+
getToolbarPropsFromHeaders
|
|
184
|
+
};
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createScopedLogger,
|
|
3
|
+
sendPreprEvent,
|
|
4
|
+
setTrustedParentOrigin
|
|
5
|
+
} from "./chunk-S3VT4UWM.js";
|
|
6
|
+
|
|
7
|
+
// src/core/locales/de.json
|
|
8
|
+
var de_default = {
|
|
9
|
+
common: {
|
|
10
|
+
viewingAs: "Ansicht als:",
|
|
11
|
+
user: "Benutzer",
|
|
12
|
+
off: "Aus",
|
|
13
|
+
on: "An",
|
|
14
|
+
reset: "Zur\xFCcksetzen",
|
|
15
|
+
toolbar: "Symbolleiste"
|
|
16
|
+
},
|
|
17
|
+
adaptiveContent: {
|
|
18
|
+
adaptiveContent: "Adaptive Inhalte",
|
|
19
|
+
enablePreview: "Vorschaumodus",
|
|
20
|
+
segment: "Segment",
|
|
21
|
+
ABVariant: "A/B-Variante",
|
|
22
|
+
chooseSegment: "Segment w\xE4hlen",
|
|
23
|
+
searchSegments: "Segmente suchen",
|
|
24
|
+
none: "Keine Segmente",
|
|
25
|
+
allOtherUsers: "Alle anderen Benutzer",
|
|
26
|
+
offDescription: "Die Website als echter Benutzer ansehen (Cookies verwenden)",
|
|
27
|
+
onDescription: "Mit der Symbolleiste Segmente und A/B-Varianten simulieren"
|
|
28
|
+
},
|
|
29
|
+
editingTools: {
|
|
30
|
+
editingTools: "Bearbeitungswerkzeuge",
|
|
31
|
+
editMode: "Bearbeitungsmodus",
|
|
32
|
+
ariaCloseEditMode: "Bearbeitungsmodus schlie\xDFen"
|
|
33
|
+
},
|
|
34
|
+
visualEditor: {
|
|
35
|
+
edit: "Bearbeiten",
|
|
36
|
+
otherItem: "anderes Element",
|
|
37
|
+
linkedItem: "verkn\xFCpftes Element"
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/core/locales/en.json
|
|
42
|
+
var en_default = {
|
|
43
|
+
common: {
|
|
44
|
+
viewingAs: "Viewing as:",
|
|
45
|
+
user: "User",
|
|
46
|
+
off: "Off",
|
|
47
|
+
on: "On",
|
|
48
|
+
reset: "Reset",
|
|
49
|
+
toolbar: "Toolbar"
|
|
50
|
+
},
|
|
51
|
+
adaptiveContent: {
|
|
52
|
+
adaptiveContent: "Adaptive content",
|
|
53
|
+
enablePreview: "Preview mode",
|
|
54
|
+
segment: "Segment",
|
|
55
|
+
ABVariant: "A/B variant",
|
|
56
|
+
chooseSegment: "Choose segment",
|
|
57
|
+
searchSegments: "Search segments",
|
|
58
|
+
none: "No segments",
|
|
59
|
+
allOtherUsers: "All other users",
|
|
60
|
+
offDescription: "View the site as a real user (use cookies)",
|
|
61
|
+
onDescription: "Use the toolbar to simulate segments and A/B variants"
|
|
62
|
+
},
|
|
63
|
+
editingTools: {
|
|
64
|
+
editingTools: "Editing tools",
|
|
65
|
+
editMode: "Edit mode",
|
|
66
|
+
ariaCloseEditMode: "Close edit mode"
|
|
67
|
+
},
|
|
68
|
+
visualEditor: {
|
|
69
|
+
edit: "Edit",
|
|
70
|
+
otherItem: "other item",
|
|
71
|
+
linkedItem: "linked item"
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/core/locales/fr.json
|
|
76
|
+
var fr_default = {
|
|
77
|
+
common: {
|
|
78
|
+
viewingAs: "Affichage en tant que :",
|
|
79
|
+
user: "Utilisateur",
|
|
80
|
+
off: "D\xE9sactiv\xE9",
|
|
81
|
+
on: "Activ\xE9",
|
|
82
|
+
reset: "R\xE9initialiser",
|
|
83
|
+
toolbar: "Barre d'outils"
|
|
84
|
+
},
|
|
85
|
+
adaptiveContent: {
|
|
86
|
+
adaptiveContent: "Contenu adaptatif",
|
|
87
|
+
enablePreview: "Mode aper\xE7u",
|
|
88
|
+
segment: "Segment",
|
|
89
|
+
ABVariant: "Variante A/B",
|
|
90
|
+
chooseSegment: "Choisir un segment",
|
|
91
|
+
searchSegments: "Rechercher des segments",
|
|
92
|
+
none: "Aucun segment",
|
|
93
|
+
allOtherUsers: "Tous les autres utilisateurs",
|
|
94
|
+
offDescription: "Voir le site comme un vrai utilisateur (utiliser les cookies)",
|
|
95
|
+
onDescription: "Utilisez la barre d'outils pour simuler des segments et des variantes A/B"
|
|
96
|
+
},
|
|
97
|
+
editingTools: {
|
|
98
|
+
editingTools: "Outils d'\xE9dition",
|
|
99
|
+
editMode: "Mode \xE9dition",
|
|
100
|
+
ariaCloseEditMode: "Fermer le mode \xE9dition"
|
|
101
|
+
},
|
|
102
|
+
visualEditor: {
|
|
103
|
+
edit: "Modifier",
|
|
104
|
+
otherItem: "autre \xE9l\xE9ment",
|
|
105
|
+
linkedItem: "\xE9l\xE9ment li\xE9"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/core/locales/nl.json
|
|
110
|
+
var nl_default = {
|
|
111
|
+
common: {
|
|
112
|
+
viewingAs: "Bekijken als:",
|
|
113
|
+
user: "Gebruiker",
|
|
114
|
+
off: "Uit",
|
|
115
|
+
on: "Aan",
|
|
116
|
+
reset: "Resetten",
|
|
117
|
+
toolbar: "Toolbar"
|
|
118
|
+
},
|
|
119
|
+
adaptiveContent: {
|
|
120
|
+
adaptiveContent: "Adaptieve inhoud",
|
|
121
|
+
enablePreview: "Preview modus",
|
|
122
|
+
segment: "Segment",
|
|
123
|
+
ABVariant: "A/B-variant",
|
|
124
|
+
chooseSegment: "Kies segment",
|
|
125
|
+
searchSegments: "Zoek segmenten",
|
|
126
|
+
none: "Geen segmenten",
|
|
127
|
+
allOtherUsers: "Alle andere gebruikers",
|
|
128
|
+
offDescription: "Bekijk de site als een echte gebruiker (gebruik cookies)",
|
|
129
|
+
onDescription: "Gebruik de werkbalk om segmenten en A/B-varianten te simuleren"
|
|
130
|
+
},
|
|
131
|
+
editingTools: {
|
|
132
|
+
editingTools: "Editing Tools",
|
|
133
|
+
editMode: "Edit mode",
|
|
134
|
+
ariaCloseEditMode: "Edit mode sluiten"
|
|
135
|
+
},
|
|
136
|
+
visualEditor: {
|
|
137
|
+
edit: "Bewerken",
|
|
138
|
+
otherItem: "ander item",
|
|
139
|
+
linkedItem: "gekoppeld item"
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/core/i18n.ts
|
|
144
|
+
var dictionaries = {
|
|
145
|
+
en: en_default,
|
|
146
|
+
nl: nl_default,
|
|
147
|
+
fr: fr_default,
|
|
148
|
+
de: de_default
|
|
149
|
+
};
|
|
150
|
+
var LOCALES = Object.keys(dictionaries);
|
|
151
|
+
function isLocale(value) {
|
|
152
|
+
return typeof value === "string" && value in dictionaries;
|
|
153
|
+
}
|
|
154
|
+
function getDict(locale) {
|
|
155
|
+
return isLocale(locale) ? dictionaries[locale] : dictionaries.en;
|
|
156
|
+
}
|
|
157
|
+
function getFromPath(obj, path) {
|
|
158
|
+
return path.split(".").reduce(
|
|
159
|
+
(acc, key) => acc && typeof acc === "object" ? acc[key] : void 0,
|
|
160
|
+
obj
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
function format(message, vars) {
|
|
164
|
+
if (!vars) return message;
|
|
165
|
+
return Object.keys(vars).reduce(
|
|
166
|
+
(acc, k) => acc.replace(new RegExp(`\\{${k}\\}`, "g"), String(vars[k])),
|
|
167
|
+
message
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
function t(key, locale, vars) {
|
|
171
|
+
const dict = getDict(locale);
|
|
172
|
+
const msg = getFromPath(dict, key);
|
|
173
|
+
if (typeof msg === "string") return format(msg, vars);
|
|
174
|
+
return key;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/core/iframe-bridge.ts
|
|
178
|
+
var debug = createScopedLogger("iframe-bridge");
|
|
179
|
+
var MAX_REFERENCES = 500;
|
|
180
|
+
var MAX_HREF_LENGTH = 8192;
|
|
181
|
+
var MAX_ASSETS = 500;
|
|
182
|
+
var MAX_ASSET_KEY_LENGTH = 2048;
|
|
183
|
+
var MAX_ASSET_FIELD_LENGTH = 512;
|
|
184
|
+
function parseIds(value) {
|
|
185
|
+
if (!Array.isArray(value)) return void 0;
|
|
186
|
+
return value.slice(0, MAX_REFERENCES).filter((id) => typeof id === "string" && id.length > 0);
|
|
187
|
+
}
|
|
188
|
+
function parseReferences(value) {
|
|
189
|
+
if (!Array.isArray(value)) return void 0;
|
|
190
|
+
const list = [];
|
|
191
|
+
for (const entry of value.slice(0, MAX_REFERENCES)) {
|
|
192
|
+
const id = entry?.id;
|
|
193
|
+
const field = entry?.field;
|
|
194
|
+
if (typeof id === "string" && id && typeof field === "string" && field) {
|
|
195
|
+
list.push({ id, field });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return list;
|
|
199
|
+
}
|
|
200
|
+
function boundedString(value, max) {
|
|
201
|
+
return typeof value === "string" && value && value.length <= max ? value : void 0;
|
|
202
|
+
}
|
|
203
|
+
function parseAssets(value) {
|
|
204
|
+
if (!Array.isArray(value)) return void 0;
|
|
205
|
+
const list = [];
|
|
206
|
+
for (const entry of value.slice(0, MAX_ASSETS)) {
|
|
207
|
+
if (!entry || typeof entry !== "object") continue;
|
|
208
|
+
const raw = entry;
|
|
209
|
+
const key = boundedString(raw.key, MAX_ASSET_KEY_LENGTH);
|
|
210
|
+
const field = boundedString(raw.field, MAX_ASSET_FIELD_LENGTH);
|
|
211
|
+
if (!key || !field) continue;
|
|
212
|
+
const entryId = boundedString(raw.entryId, MAX_ASSET_FIELD_LENGTH);
|
|
213
|
+
list.push(entryId ? { key, field, entryId } : { key, field });
|
|
214
|
+
}
|
|
215
|
+
return list;
|
|
216
|
+
}
|
|
217
|
+
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
218
|
+
function isAllowedEditorOrigin(origin, allowed) {
|
|
219
|
+
if (allowed) {
|
|
220
|
+
if (allowed.includes("*")) return origin !== "null";
|
|
221
|
+
return allowed.includes(origin);
|
|
222
|
+
}
|
|
223
|
+
let url;
|
|
224
|
+
try {
|
|
225
|
+
url = new URL(origin);
|
|
226
|
+
} catch {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
if (url.protocol !== "https:" || url.port !== "") return false;
|
|
230
|
+
const suffix = `.${EDITOR_BASE_DOMAIN}`;
|
|
231
|
+
if (!url.hostname.endsWith(suffix)) return false;
|
|
232
|
+
const label = url.hostname.slice(0, -suffix.length);
|
|
233
|
+
return label.length > 0 && !label.includes(".");
|
|
234
|
+
}
|
|
235
|
+
function createIframeBridge(store, options = {}) {
|
|
236
|
+
const allowedOrigins = options.allowedEditorOrigins;
|
|
237
|
+
const onScrollToField = options.onScrollToField;
|
|
238
|
+
const onHandshake = options.onHandshake;
|
|
239
|
+
const onReferences = options.onReferences;
|
|
240
|
+
const onAssets = options.onAssets;
|
|
241
|
+
const onAllowNavigation = options.onAllowNavigation;
|
|
242
|
+
let parentOrigin = null;
|
|
243
|
+
const onKeyDown = (event) => {
|
|
244
|
+
const key = event.key.toLowerCase();
|
|
245
|
+
const blocked = (event.ctrlKey || event.metaKey) && ["s", "p", "l"].includes(key);
|
|
246
|
+
if (blocked) event.preventDefault();
|
|
247
|
+
};
|
|
248
|
+
const onMessage = (evt) => {
|
|
249
|
+
const data = evt?.data;
|
|
250
|
+
if (data?.event === "prepr:initVE" && !parentOrigin) {
|
|
251
|
+
if (!isAllowedEditorOrigin(evt.origin, allowedOrigins)) {
|
|
252
|
+
debug.warn("ignored editor handshake from origin", evt.origin);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
parentOrigin = evt.origin;
|
|
256
|
+
setTrustedParentOrigin(parentOrigin);
|
|
257
|
+
if (data.scrollPosition != null) {
|
|
258
|
+
const top = data.scrollPosition;
|
|
259
|
+
setTimeout(() => window.scrollTo(0, top), 1);
|
|
260
|
+
}
|
|
261
|
+
store?.set({ previewMode: true, editMode: data.editMode ?? true });
|
|
262
|
+
const itemId = typeof data.itemId === "string" && data.itemId ? data.itemId : void 0;
|
|
263
|
+
const referencedIds = parseReferences(data.referencedIds);
|
|
264
|
+
const componentIds = parseIds(data.componentIds);
|
|
265
|
+
const uiLocale = isLocale(data.uiLocale) ? data.uiLocale : void 0;
|
|
266
|
+
const navigationGuard = data.navigationGuard === true;
|
|
267
|
+
const assets = parseAssets(data.assets);
|
|
268
|
+
try {
|
|
269
|
+
onHandshake?.({
|
|
270
|
+
...itemId && { itemId },
|
|
271
|
+
...referencedIds && { referencedIds },
|
|
272
|
+
...componentIds && { componentIds },
|
|
273
|
+
...uiLocale && { uiLocale },
|
|
274
|
+
...navigationGuard && { navigationGuard },
|
|
275
|
+
...assets && { assets }
|
|
276
|
+
});
|
|
277
|
+
} catch (error) {
|
|
278
|
+
debug.warn("handshake handler failed", error);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (!parentOrigin || evt.origin !== parentOrigin) return;
|
|
282
|
+
if (data?.event === "prepr:references") {
|
|
283
|
+
const assets = parseAssets(data.assets);
|
|
284
|
+
if (assets) {
|
|
285
|
+
try {
|
|
286
|
+
onAssets?.(assets);
|
|
287
|
+
} catch (error) {
|
|
288
|
+
debug.warn("assets handler failed", error);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const referencedIds = parseReferences(data.referencedIds);
|
|
292
|
+
if (!referencedIds) return;
|
|
293
|
+
try {
|
|
294
|
+
onReferences?.(referencedIds, parseIds(data.componentIds));
|
|
295
|
+
} catch (error) {
|
|
296
|
+
debug.warn("references handler failed", error);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (data?.event === "prepr:getScrollPosition") {
|
|
300
|
+
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
301
|
+
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
302
|
+
}
|
|
303
|
+
if (data?.event === "prepr:scrollToField") {
|
|
304
|
+
if (typeof data.field !== "string" || !data.field) return;
|
|
305
|
+
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
306
|
+
const block = typeof data.block === "number" && Number.isInteger(data.block) ? data.block : void 0;
|
|
307
|
+
const entryId = typeof data.entryId === "string" && data.entryId ? data.entryId : void 0;
|
|
308
|
+
const fieldById = typeof data.fieldById === "string" && data.fieldById ? data.fieldById : void 0;
|
|
309
|
+
try {
|
|
310
|
+
onScrollToField?.({
|
|
311
|
+
field: data.field,
|
|
312
|
+
id: data.id,
|
|
313
|
+
block,
|
|
314
|
+
entryId,
|
|
315
|
+
fieldById
|
|
316
|
+
});
|
|
317
|
+
} catch (error) {
|
|
318
|
+
debug.warn("scrollToField handler failed", error);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (data?.event === "prepr:allowNavigation") {
|
|
322
|
+
const href = data.href;
|
|
323
|
+
if (typeof href !== "string" || !href || href.length > MAX_HREF_LENGTH) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
onAllowNavigation?.(href);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
debug.warn("allowNavigation handler failed", error);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
return {
|
|
334
|
+
start() {
|
|
335
|
+
const features = store?.get().features;
|
|
336
|
+
sendPreprEvent("loaded", features ? { features } : void 0, {
|
|
337
|
+
allowUntrustedTarget: true
|
|
338
|
+
});
|
|
339
|
+
window.addEventListener("keydown", onKeyDown);
|
|
340
|
+
window.addEventListener("message", onMessage);
|
|
341
|
+
},
|
|
342
|
+
stop() {
|
|
343
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
344
|
+
window.removeEventListener("message", onMessage);
|
|
345
|
+
parentOrigin = null;
|
|
346
|
+
setTrustedParentOrigin(null);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export {
|
|
352
|
+
isLocale,
|
|
353
|
+
t,
|
|
354
|
+
isAllowedEditorOrigin,
|
|
355
|
+
createIframeBridge
|
|
356
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/codegen/index.ts
|
|
21
|
+
var codegen_exports = {};
|
|
22
|
+
__export(codegen_exports, {
|
|
23
|
+
addPreprIds: () => addPreprIds,
|
|
24
|
+
createPreprIds: () => createPreprIds,
|
|
25
|
+
preprIds: () => preprIds
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(codegen_exports);
|
|
28
|
+
var import_graphql = require("graphql");
|
|
29
|
+
function field(name) {
|
|
30
|
+
return { kind: import_graphql.Kind.FIELD, name: { kind: import_graphql.Kind.NAME, value: name } };
|
|
31
|
+
}
|
|
32
|
+
function hasResponseKey(set, key) {
|
|
33
|
+
return set.selections.some(
|
|
34
|
+
(s) => s.kind === import_graphql.Kind.FIELD && (s.alias ?? s.name).value === key
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function addPreprIds(document, schema, options = {}) {
|
|
38
|
+
const typename = options.typename ?? false;
|
|
39
|
+
const roots = new Set(
|
|
40
|
+
[
|
|
41
|
+
schema.getQueryType(),
|
|
42
|
+
schema.getMutationType(),
|
|
43
|
+
schema.getSubscriptionType()
|
|
44
|
+
].filter(Boolean)
|
|
45
|
+
);
|
|
46
|
+
const typeInfo = new import_graphql.TypeInfo(schema);
|
|
47
|
+
return (0, import_graphql.visit)(
|
|
48
|
+
document,
|
|
49
|
+
(0, import_graphql.visitWithTypeInfo)(typeInfo, {
|
|
50
|
+
SelectionSet(node) {
|
|
51
|
+
const type = typeInfo.getParentType();
|
|
52
|
+
if (!type || !(0, import_graphql.isCompositeType)(type) || roots.has(type)) return;
|
|
53
|
+
const added = [];
|
|
54
|
+
if (((0, import_graphql.isObjectType)(type) || (0, import_graphql.isInterfaceType)(type)) && "_id" in type.getFields() && !hasResponseKey(node, "_id")) {
|
|
55
|
+
added.push(field("_id"));
|
|
56
|
+
}
|
|
57
|
+
if (typename && !hasResponseKey(node, "__typename")) {
|
|
58
|
+
added.push(field("__typename"));
|
|
59
|
+
}
|
|
60
|
+
if (!added.length) return;
|
|
61
|
+
return { ...node, selections: [...added, ...node.selections] };
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
function createPreprIds(options = {}) {
|
|
67
|
+
return {
|
|
68
|
+
transform({ documents, schema }) {
|
|
69
|
+
const built = (0, import_graphql.buildASTSchema)(schema, { assumeValidSDL: true });
|
|
70
|
+
return documents.map(
|
|
71
|
+
(file) => file.document ? { ...file, document: addPreprIds(file.document, built, options) } : file
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
var preprIds = createPreprIds();
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
addPreprIds,
|
|
80
|
+
createPreprIds,
|
|
81
|
+
preprIds
|
|
82
|
+
});
|