@symbo.ls/brender 3.7.3 → 3.7.5
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/cjs/index.js +4 -0
- package/dist/cjs/load.js +11 -11
- package/dist/cjs/prefetch.js +79 -13
- package/dist/cjs/render.js +213 -50
- package/dist/esm/index.js +5 -1
- package/dist/esm/load.js +11 -11
- package/dist/esm/prefetch.js +79 -13
- package/dist/esm/render.js +215 -52
- package/index.js +5 -1
- package/load.js +13 -11
- package/package.json +2 -2
- package/prefetch.js +118 -11
- package/render.js +289 -67
package/dist/cjs/index.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
extractMetadata: () => import_metadata.extractMetadata,
|
|
25
25
|
generateHeadHtml: () => import_metadata.generateHeadHtml,
|
|
26
26
|
generateSitemap: () => import_sitemap.generateSitemap,
|
|
27
|
+
getAccumulatedEmotionCSS: () => import_render.getAccumulatedEmotionCSS,
|
|
27
28
|
hydrate: () => import_hydrate.hydrate,
|
|
28
29
|
injectPrefetchedState: () => import_prefetch.injectPrefetchedState,
|
|
29
30
|
loadAndRenderAll: () => import_load.loadAndRenderAll,
|
|
@@ -34,6 +35,7 @@ __export(index_exports, {
|
|
|
34
35
|
renderElement: () => import_render.renderElement,
|
|
35
36
|
renderPage: () => import_render.renderPage,
|
|
36
37
|
renderRoute: () => import_render.renderRoute,
|
|
38
|
+
replaceEmotionCSS: () => import_render.replaceEmotionCSS,
|
|
37
39
|
resetGlobalCSSCache: () => import_render.resetGlobalCSSCache,
|
|
38
40
|
resetKeys: () => import_keys.resetKeys
|
|
39
41
|
});
|
|
@@ -58,6 +60,8 @@ var index_default = {
|
|
|
58
60
|
renderRoute: import_render.renderRoute,
|
|
59
61
|
renderPage: import_render.renderPage,
|
|
60
62
|
resetGlobalCSSCache: import_render.resetGlobalCSSCache,
|
|
63
|
+
getAccumulatedEmotionCSS: import_render.getAccumulatedEmotionCSS,
|
|
64
|
+
replaceEmotionCSS: import_render.replaceEmotionCSS,
|
|
61
65
|
extractMetadata: import_metadata.extractMetadata,
|
|
62
66
|
generateHeadHtml: import_metadata.generateHeadHtml,
|
|
63
67
|
collectBrNodes: import_hydrate.collectBrNodes,
|
package/dist/cjs/load.js
CHANGED
|
@@ -103,17 +103,17 @@ const loadProject = async (projectPath) => {
|
|
|
103
103
|
bundleAndImport((0, import_path.join)(symbolsDir, "files", "index.js"))
|
|
104
104
|
]);
|
|
105
105
|
return {
|
|
106
|
-
app: appModule?.default || {},
|
|
107
|
-
state: stateModule?.default || {},
|
|
108
|
-
dependencies: depsModule?.default || {},
|
|
109
|
-
components: componentsModule || {},
|
|
110
|
-
snippets: snippetsModule || {},
|
|
111
|
-
pages: pagesModule?.default || {},
|
|
112
|
-
functions: functionsModule || {},
|
|
113
|
-
methods: methodsModule || {},
|
|
114
|
-
designSystem: designSystemModule?.default || {},
|
|
115
|
-
files: filesModule?.default || {},
|
|
116
|
-
config: configModule?.default || {}
|
|
106
|
+
app: { ...appModule?.default || {} },
|
|
107
|
+
state: { ...stateModule?.default || {} },
|
|
108
|
+
dependencies: { ...depsModule?.default || {} },
|
|
109
|
+
components: { ...componentsModule || {} },
|
|
110
|
+
snippets: { ...snippetsModule || {} },
|
|
111
|
+
pages: { ...pagesModule?.default || {} },
|
|
112
|
+
functions: { ...functionsModule || {} },
|
|
113
|
+
methods: { ...methodsModule || {} },
|
|
114
|
+
designSystem: { ...designSystemModule?.default || {} },
|
|
115
|
+
files: { ...filesModule?.default || {} },
|
|
116
|
+
config: { ...configModule?.default || {} }
|
|
117
117
|
};
|
|
118
118
|
};
|
|
119
119
|
const loadAndRenderAll = async (projectPath, renderFn) => {
|
package/dist/cjs/prefetch.js
CHANGED
|
@@ -27,6 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
var prefetch_exports = {};
|
|
29
29
|
__export(prefetch_exports, {
|
|
30
|
+
fetchSSRTranslations: () => fetchSSRTranslations,
|
|
30
31
|
injectPrefetchedState: () => injectPrefetchedState,
|
|
31
32
|
prefetchPageData: () => prefetchPageData
|
|
32
33
|
});
|
|
@@ -98,15 +99,14 @@ const createSSRAdapter = async (dbConfig) => {
|
|
|
98
99
|
if (adapter !== "supabase") return null;
|
|
99
100
|
const supabaseUrl = url || projectId && `https://${projectId}.supabase.co`;
|
|
100
101
|
if (!supabaseUrl || !key) return null;
|
|
101
|
-
let clientFactory
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
102
|
+
let clientFactory;
|
|
103
|
+
try {
|
|
104
|
+
const mod = await import("@supabase/supabase-js");
|
|
105
|
+
clientFactory = mod.createClient;
|
|
106
|
+
} catch {
|
|
107
|
+
clientFactory = createClient;
|
|
109
108
|
}
|
|
109
|
+
if (!clientFactory) return null;
|
|
110
110
|
const client = clientFactory(supabaseUrl, key);
|
|
111
111
|
return {
|
|
112
112
|
rpc: ({ from, params }) => client.rpc(from, params),
|
|
@@ -159,7 +159,8 @@ const prefetchPageData = async (data, route = "/", options = {}) => {
|
|
|
159
159
|
const pages = data.pages || {};
|
|
160
160
|
const pageDef = pages[route];
|
|
161
161
|
if (!pageDef) return /* @__PURE__ */ new Map();
|
|
162
|
-
const
|
|
162
|
+
const config = data.config || data.settings || {};
|
|
163
|
+
const dbConfig = config.fetch || data.fetch || config.db || data.db;
|
|
163
164
|
if (!dbConfig) return /* @__PURE__ */ new Map();
|
|
164
165
|
const adapter = await createSSRAdapter(dbConfig);
|
|
165
166
|
if (!adapter) return /* @__PURE__ */ new Map();
|
|
@@ -167,17 +168,81 @@ const prefetchPageData = async (data, route = "/", options = {}) => {
|
|
|
167
168
|
if (!declarations.length) return /* @__PURE__ */ new Map();
|
|
168
169
|
const stateUpdates = /* @__PURE__ */ new Map();
|
|
169
170
|
const results = await Promise.allSettled(
|
|
170
|
-
declarations.map(async ({ config, stateKey, path }) => {
|
|
171
|
-
const fetchedData = await executeSingle(adapter,
|
|
172
|
-
if (fetchedData !== null
|
|
171
|
+
declarations.map(async ({ config: config2, stateKey, path }) => {
|
|
172
|
+
const fetchedData = await executeSingle(adapter, config2);
|
|
173
|
+
if (fetchedData !== null) {
|
|
173
174
|
const existing = stateUpdates.get(path) || {};
|
|
174
|
-
|
|
175
|
+
if (stateKey) {
|
|
176
|
+
existing[stateKey] = fetchedData;
|
|
177
|
+
} else if (isObject(fetchedData)) {
|
|
178
|
+
Object.assign(existing, fetchedData);
|
|
179
|
+
}
|
|
175
180
|
stateUpdates.set(path, existing);
|
|
176
181
|
}
|
|
177
182
|
})
|
|
178
183
|
);
|
|
179
184
|
return stateUpdates;
|
|
180
185
|
};
|
|
186
|
+
const fetchSSRTranslations = async (data) => {
|
|
187
|
+
const config = data.config || {};
|
|
188
|
+
const polyglot = config.polyglot || data.polyglot;
|
|
189
|
+
if (!polyglot?.fetch) return null;
|
|
190
|
+
const dbConfig = config.fetch || data.fetch || config.db || data.db;
|
|
191
|
+
if (!dbConfig) return null;
|
|
192
|
+
const adapter = await createSSRAdapter(dbConfig);
|
|
193
|
+
if (!adapter) return null;
|
|
194
|
+
const fetchConfig = polyglot.fetch;
|
|
195
|
+
const rpcName = fetchConfig.rpc || fetchConfig.from || "get_translations_if_changed";
|
|
196
|
+
const languages = polyglot.languages || [polyglot.defaultLang || "en"];
|
|
197
|
+
const translations = {};
|
|
198
|
+
const results = await Promise.allSettled(
|
|
199
|
+
languages.map(async (lang) => {
|
|
200
|
+
try {
|
|
201
|
+
const res = await adapter.rpc({
|
|
202
|
+
from: rpcName,
|
|
203
|
+
params: { p_lang: lang, p_cached_version: 0 }
|
|
204
|
+
});
|
|
205
|
+
if (res.error || !res.data) return;
|
|
206
|
+
const result = res.data;
|
|
207
|
+
if (result.translations) {
|
|
208
|
+
translations[lang] = result.translations;
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
);
|
|
214
|
+
return Object.keys(translations).length ? translations : null;
|
|
215
|
+
};
|
|
216
|
+
const preEvaluateChildren = (def, inheritedState) => {
|
|
217
|
+
if (!def || typeof def !== "object") return;
|
|
218
|
+
for (const key in def) {
|
|
219
|
+
if (key === "state" || key === "fetch" || key === "props" || key === "attr" || key === "on" || key === "define" || key === "childExtends" || key === "childProps" || key === "childrenAs") continue;
|
|
220
|
+
if (key.charAt(0) >= "A" && key.charAt(0) <= "Z" && isObject(def[key])) {
|
|
221
|
+
const child = def[key];
|
|
222
|
+
const effectiveState = child.state && typeof child.state === "object" ? { ...inheritedState, ...child.state } : inheritedState;
|
|
223
|
+
if (isFunction(child.children)) {
|
|
224
|
+
try {
|
|
225
|
+
const mockEl = {
|
|
226
|
+
state: effectiveState,
|
|
227
|
+
props: {},
|
|
228
|
+
call: (fn) => {
|
|
229
|
+
if (fn === "getActiveLang" || fn === "getLang") return effectiveState?.lang || "ka";
|
|
230
|
+
if (fn === "polyglot") return arguments[1] || "";
|
|
231
|
+
return void 0;
|
|
232
|
+
},
|
|
233
|
+
__ref: {}
|
|
234
|
+
};
|
|
235
|
+
const result = child.children(mockEl, effectiveState);
|
|
236
|
+
if (isArray(result) && result.length > 0) {
|
|
237
|
+
child.children = result;
|
|
238
|
+
}
|
|
239
|
+
} catch {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
preEvaluateChildren(child, effectiveState);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
};
|
|
181
246
|
const injectPrefetchedState = (pageDef, stateUpdates) => {
|
|
182
247
|
if (!stateUpdates || !stateUpdates.size) return;
|
|
183
248
|
for (const [path, data] of stateUpdates) {
|
|
@@ -194,6 +259,7 @@ const injectPrefetchedState = (pageDef, stateUpdates) => {
|
|
|
194
259
|
target.state = {};
|
|
195
260
|
}
|
|
196
261
|
Object.assign(target.state, data);
|
|
262
|
+
preEvaluateChildren(target, target.state);
|
|
197
263
|
}
|
|
198
264
|
}
|
|
199
265
|
};
|
package/dist/cjs/render.js
CHANGED
|
@@ -27,10 +27,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
var render_exports = {};
|
|
29
29
|
__export(render_exports, {
|
|
30
|
+
getAccumulatedEmotionCSS: () => getAccumulatedEmotionCSS,
|
|
30
31
|
render: () => render,
|
|
31
32
|
renderElement: () => renderElement,
|
|
32
33
|
renderPage: () => renderPage,
|
|
33
34
|
renderRoute: () => renderRoute,
|
|
35
|
+
replaceEmotionCSS: () => replaceEmotionCSS,
|
|
34
36
|
resetGlobalCSSCache: () => resetGlobalCSSCache
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(render_exports);
|
|
@@ -44,7 +46,53 @@ var import_metadata = require("./metadata.js");
|
|
|
44
46
|
var import_hydrate = require("./hydrate.js");
|
|
45
47
|
var import_prefetch = require("./prefetch.js");
|
|
46
48
|
var import_linkedom = require("linkedom");
|
|
49
|
+
var import_create_instance = __toESM(require("@emotion/css/create-instance"), 1);
|
|
47
50
|
const import_meta = {};
|
|
51
|
+
const ssrResolve = (map, key) => {
|
|
52
|
+
if (!map || !key) return void 0;
|
|
53
|
+
if (map[key] !== void 0) return map[key];
|
|
54
|
+
const parts = key.split(".");
|
|
55
|
+
let v = map;
|
|
56
|
+
for (const p of parts) {
|
|
57
|
+
if (v == null || typeof v !== "object") return void 0;
|
|
58
|
+
v = v[p];
|
|
59
|
+
}
|
|
60
|
+
return v;
|
|
61
|
+
};
|
|
62
|
+
const ssrTranslate = function(key, lang) {
|
|
63
|
+
if (!key) return "";
|
|
64
|
+
const ctx = this?.context;
|
|
65
|
+
const poly = ctx?.polyglot;
|
|
66
|
+
const activeLang = lang || poly?.defaultLang || "ka";
|
|
67
|
+
if (poly?.translations) {
|
|
68
|
+
const langMap = poly.translations[activeLang];
|
|
69
|
+
if (langMap) {
|
|
70
|
+
const val = ssrResolve(langMap, key);
|
|
71
|
+
if (val !== void 0) return val;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const root = this?.state?.root || ctx?.state?.root;
|
|
75
|
+
if (root?.translations) {
|
|
76
|
+
const langMap = root.translations[activeLang];
|
|
77
|
+
if (langMap) {
|
|
78
|
+
const val = ssrResolve(langMap, key);
|
|
79
|
+
if (val !== void 0) return val;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const defaultLang = poly?.defaultLang || "en";
|
|
83
|
+
if (defaultLang !== activeLang && poly?.translations) {
|
|
84
|
+
const fallback = poly.translations[defaultLang];
|
|
85
|
+
if (fallback) {
|
|
86
|
+
const val = ssrResolve(fallback, key);
|
|
87
|
+
if (val !== void 0) return val;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return key;
|
|
91
|
+
};
|
|
92
|
+
const ssrGetActiveLang = function() {
|
|
93
|
+
const ctx = this?.context;
|
|
94
|
+
return this?.state?.root?.lang || ctx?.polyglot?.defaultLang || "ka";
|
|
95
|
+
};
|
|
48
96
|
const structuredCloneDeep = (obj, seen = /* @__PURE__ */ new WeakMap()) => {
|
|
49
97
|
if (obj === null || typeof obj !== "object") return obj;
|
|
50
98
|
if (seen.has(obj)) return seen.get(obj);
|
|
@@ -76,7 +124,7 @@ const safeJsonReplacer = () => {
|
|
|
76
124
|
let _cachedCreateDomql = null;
|
|
77
125
|
const bundleCreateDomql = async () => {
|
|
78
126
|
if (_cachedCreateDomql) return _cachedCreateDomql;
|
|
79
|
-
const brenderDir = new URL(".", import_meta.url).pathname;
|
|
127
|
+
const brenderDir = (0, import_fs.realpathSync)(new URL(".", import_meta.url).pathname);
|
|
80
128
|
const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
|
|
81
129
|
const entry = (0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "createDomql.js");
|
|
82
130
|
const esbuild = await import("esbuild");
|
|
@@ -320,7 +368,16 @@ const UIKIT_STUBS = {
|
|
|
320
368
|
Text: { tag: "span" }
|
|
321
369
|
};
|
|
322
370
|
const render = async (data, options = {}) => {
|
|
323
|
-
const { route = "/", state: stateOverrides, context: contextOverrides, prefetch = false } = options;
|
|
371
|
+
const { route = "/", pathname, state: stateOverrides, context: contextOverrides, prefetch = false } = options;
|
|
372
|
+
const locationPath = pathname || route;
|
|
373
|
+
const _prevLocPrefetch = globalThis.location;
|
|
374
|
+
const _prevWinPrefetch = globalThis.window;
|
|
375
|
+
if (!globalThis.location || globalThis.location.pathname !== locationPath) {
|
|
376
|
+
globalThis.location = { pathname: locationPath, href: locationPath, search: "", hash: "", origin: "" };
|
|
377
|
+
}
|
|
378
|
+
if (!globalThis.window) {
|
|
379
|
+
globalThis.window = { location: globalThis.location };
|
|
380
|
+
}
|
|
324
381
|
let prefetchedPages;
|
|
325
382
|
if (prefetch) {
|
|
326
383
|
try {
|
|
@@ -346,44 +403,102 @@ const render = async (data, options = {}) => {
|
|
|
346
403
|
(0, import_prefetch.injectPrefetchedState)(pageDef, stateUpdates);
|
|
347
404
|
prefetchedPages[route] = pageDef;
|
|
348
405
|
}
|
|
349
|
-
} catch {
|
|
406
|
+
} catch (prefetchErr) {
|
|
407
|
+
console.error("[brender] Prefetch error:", prefetchErr);
|
|
350
408
|
prefetchedPages = data.pages;
|
|
351
409
|
}
|
|
352
410
|
}
|
|
411
|
+
let ssrTranslations;
|
|
412
|
+
if (prefetch) {
|
|
413
|
+
try {
|
|
414
|
+
ssrTranslations = await (0, import_prefetch.fetchSSRTranslations)(data);
|
|
415
|
+
} catch {
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (_prevLocPrefetch !== void 0) globalThis.location = _prevLocPrefetch;
|
|
419
|
+
else delete globalThis.location;
|
|
420
|
+
if (_prevWinPrefetch !== void 0) globalThis.window = _prevWinPrefetch;
|
|
421
|
+
else delete globalThis.window;
|
|
353
422
|
const { window, document } = (0, import_env.createEnv)();
|
|
354
423
|
const body = document.body;
|
|
355
|
-
window.location.pathname =
|
|
424
|
+
window.location.pathname = locationPath;
|
|
356
425
|
const _prevDoc = globalThis.document;
|
|
357
426
|
const _prevLoc = globalThis.location;
|
|
358
427
|
globalThis.document = document;
|
|
359
428
|
globalThis.location = window.location;
|
|
360
429
|
const { createDomqlElement } = await bundleCreateDomql();
|
|
361
430
|
const app = structuredCloneDeep(data.app || {});
|
|
431
|
+
const config = { ...data.config || {} };
|
|
432
|
+
if (data.polyglot && !config.polyglot) config.polyglot = data.polyglot;
|
|
433
|
+
if (data.fetch && !config.fetch) config.fetch = data.fetch;
|
|
434
|
+
if (data.router && !config.router) config.router = data.router;
|
|
435
|
+
for (const k of ["useReset", "useVariable", "useFontImport", "useIconSprite", "useSvgSprite", "useDefaultConfig", "useDocumentTheme"]) {
|
|
436
|
+
if (data[k] != null && config[k] == null) config[k] = data[k];
|
|
437
|
+
}
|
|
438
|
+
const polyglotConfig = config.polyglot ? { ...config.polyglot } : void 0;
|
|
439
|
+
if (ssrTranslations && polyglotConfig) {
|
|
440
|
+
polyglotConfig.translations = {
|
|
441
|
+
...polyglotConfig.translations || {},
|
|
442
|
+
...ssrTranslations
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
const baseState = structuredCloneDeep(data.state || {});
|
|
446
|
+
if (ssrTranslations || polyglotConfig) {
|
|
447
|
+
if (!baseState.root) baseState.root = {};
|
|
448
|
+
if (polyglotConfig) {
|
|
449
|
+
baseState.root.lang = baseState.root.lang || polyglotConfig.defaultLang || "en";
|
|
450
|
+
}
|
|
451
|
+
if (ssrTranslations) {
|
|
452
|
+
baseState.root.translations = {
|
|
453
|
+
...baseState.root.translations || {},
|
|
454
|
+
...ssrTranslations
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const ssrEmotion = (0, import_create_instance.default)({
|
|
459
|
+
key: "smbls",
|
|
460
|
+
container: document.head,
|
|
461
|
+
speedy: false
|
|
462
|
+
});
|
|
362
463
|
const ctx = {
|
|
363
|
-
state:
|
|
364
|
-
...stateOverrides ? { state: { ...
|
|
464
|
+
state: baseState,
|
|
465
|
+
...stateOverrides ? { state: { ...baseState, ...stateOverrides } } : {},
|
|
365
466
|
dependencies: structuredCloneDeep(data.dependencies || {}),
|
|
366
467
|
components: structuredCloneDeep(data.components || {}),
|
|
367
468
|
snippets: structuredCloneDeep(data.snippets || {}),
|
|
368
469
|
pages: structuredCloneDeep(prefetchedPages || data.pages || {}),
|
|
369
|
-
functions:
|
|
470
|
+
functions: {
|
|
471
|
+
...data.functions || {},
|
|
472
|
+
// SSR polyglot functions — enable {{ key | polyglot }} resolution during render
|
|
473
|
+
polyglot: ssrTranslate,
|
|
474
|
+
getActiveLang: ssrGetActiveLang,
|
|
475
|
+
getLang: ssrGetActiveLang
|
|
476
|
+
},
|
|
370
477
|
methods: data.methods || {},
|
|
371
478
|
designSystem: structuredCloneDeep(data.designSystem || {}),
|
|
372
479
|
files: data.files || {},
|
|
373
|
-
...
|
|
480
|
+
...config,
|
|
481
|
+
// Override polyglot with SSR-enriched version
|
|
482
|
+
...polyglotConfig ? { polyglot: polyglotConfig } : {},
|
|
374
483
|
// Virtual DOM environment
|
|
375
484
|
document,
|
|
376
485
|
window,
|
|
377
486
|
parent: { node: body },
|
|
487
|
+
// Use SSR emotion instance (non-speedy) for proper @media rule extraction
|
|
488
|
+
initOptions: { emotion: ssrEmotion },
|
|
489
|
+
// Disable sourcemap tracking in SSR — it causes stack overflows
|
|
490
|
+
// when state contains large data arrays (articles, events, etc.)
|
|
491
|
+
domqlOptions: { sourcemap: false },
|
|
378
492
|
// Caller overrides
|
|
379
493
|
...contextOverrides || {}
|
|
380
494
|
};
|
|
381
495
|
(0, import_keys.resetKeys)();
|
|
382
496
|
const element = await createDomqlElement(app, ctx);
|
|
383
|
-
|
|
497
|
+
const flushDelay = prefetch ? 2e3 : 50;
|
|
498
|
+
await new Promise((r) => setTimeout(r, flushDelay));
|
|
384
499
|
(0, import_keys.assignKeys)(body);
|
|
385
500
|
const registry = (0, import_keys.mapKeysToElements)(element);
|
|
386
|
-
const metadata = (0, import_metadata.extractMetadata)(data, route);
|
|
501
|
+
const metadata = (0, import_metadata.extractMetadata)(data, route, element, element?.state);
|
|
387
502
|
const emotionCSS = [];
|
|
388
503
|
const emotionInstance = ctx.emotion || element && element.context && element.context.emotion;
|
|
389
504
|
if (emotionInstance && emotionInstance.cache) {
|
|
@@ -420,12 +535,20 @@ const render = async (data, options = {}) => {
|
|
|
420
535
|
}
|
|
421
536
|
}
|
|
422
537
|
}
|
|
423
|
-
|
|
538
|
+
let html = fixSvgContent(body.innerHTML);
|
|
539
|
+
if (ssrTranslations) {
|
|
540
|
+
const defaultLang = polyglotConfig?.defaultLang || "en";
|
|
541
|
+
const langMap = ssrTranslations[defaultLang] || Object.values(ssrTranslations)[0] || {};
|
|
542
|
+
html = html.replace(/\{\{\s*([^|{}]+?)\s*\|\s*polyglot\s*\}\}/g, (match, key) => {
|
|
543
|
+
const trimmed = key.trim();
|
|
544
|
+
return langMap[trimmed] ?? match;
|
|
545
|
+
});
|
|
546
|
+
}
|
|
424
547
|
if (_prevDoc !== void 0) globalThis.document = _prevDoc;
|
|
425
548
|
else delete globalThis.document;
|
|
426
549
|
if (_prevLoc !== void 0) globalThis.location = _prevLoc;
|
|
427
550
|
else delete globalThis.location;
|
|
428
|
-
return { html, metadata, registry, element, emotionCSS, document, window };
|
|
551
|
+
return { html, metadata, registry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
|
|
429
552
|
};
|
|
430
553
|
const renderElement = async (elementDef, options = {}) => {
|
|
431
554
|
const { context = {} } = options;
|
|
@@ -609,63 +732,82 @@ ${frameRules}
|
|
|
609
732
|
return _cachedGlobalCSS;
|
|
610
733
|
}
|
|
611
734
|
};
|
|
612
|
-
let
|
|
735
|
+
let _accumulatedEmotionCSS = /* @__PURE__ */ new Set();
|
|
613
736
|
const resetGlobalCSSCache = () => {
|
|
614
737
|
_cachedGlobalCSS = null;
|
|
615
|
-
|
|
738
|
+
_accumulatedEmotionCSS = /* @__PURE__ */ new Set();
|
|
739
|
+
};
|
|
740
|
+
const getAccumulatedEmotionCSS = () => Array.from(_accumulatedEmotionCSS).join("\n");
|
|
741
|
+
const replaceEmotionCSS = (html, newCSS) => {
|
|
742
|
+
return html.replace(
|
|
743
|
+
/<style data-emotion="smbls">[\s\S]*?<\/style>/,
|
|
744
|
+
newCSS ? `<style data-emotion="smbls">
|
|
745
|
+
${newCSS}
|
|
746
|
+
</style>` : ""
|
|
747
|
+
);
|
|
616
748
|
};
|
|
617
749
|
const renderRoute = async (data, options = {}) => {
|
|
618
|
-
const { route = "/" } = options;
|
|
750
|
+
const { route = "/", pathname } = options;
|
|
751
|
+
const result = await render(data, { route, pathname, prefetch: true });
|
|
752
|
+
if (!result) return null;
|
|
619
753
|
const ds = data.designSystem || {};
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
context: {
|
|
624
|
-
components: data.components || {},
|
|
625
|
-
snippets: data.snippets || {},
|
|
626
|
-
designSystem: ds,
|
|
627
|
-
state: data.state || {},
|
|
628
|
-
functions: data.functions || {},
|
|
629
|
-
methods: data.methods || {}
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
const { document: cssDoc } = (0, import_linkedom.parseHTML)(`<html><head></head><body>${result.html}</body></html>`);
|
|
633
|
-
let emotionInstance;
|
|
754
|
+
const globalCSS = await generateGlobalCSS(ds, data.config || data.settings);
|
|
755
|
+
let prefetchedState = null;
|
|
756
|
+
let activeLang = null;
|
|
634
757
|
try {
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
758
|
+
const el = result.element;
|
|
759
|
+
const polyglot = el?.context?.polyglot || data.polyglot || data.config?.polyglot;
|
|
760
|
+
activeLang = el?.state?.root?.lang || polyglot?.defaultLang || "en";
|
|
761
|
+
if (result.prefetchedPages && result.prefetchedPages[route]) {
|
|
762
|
+
const pageDef = result.prefetchedPages[route];
|
|
763
|
+
const collectStates = (def, result2 = {}) => {
|
|
764
|
+
if (!def || typeof def !== "object") return result2;
|
|
765
|
+
if (def.state && typeof def.state === "object") {
|
|
766
|
+
for (const [k, v] of Object.entries(def.state)) {
|
|
767
|
+
if (v !== void 0 && v !== null && typeof v !== "function") {
|
|
768
|
+
result2[k] = v;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
for (const [key, child] of Object.entries(def)) {
|
|
773
|
+
if (key === "state" || key === "props" || key === "attr" || key === "on" || key === "define" || key === "__ref" || key.startsWith("__")) continue;
|
|
774
|
+
if (child && typeof child === "object" && !Array.isArray(child)) {
|
|
775
|
+
collectStates(child, result2);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return result2;
|
|
779
|
+
};
|
|
780
|
+
prefetchedState = collectStates(pageDef);
|
|
781
|
+
}
|
|
782
|
+
} catch (e) {
|
|
638
783
|
}
|
|
639
|
-
(0, import_hydrate.hydrate)(result.element, {
|
|
640
|
-
root: cssDoc.body,
|
|
641
|
-
renderEvents: false,
|
|
642
|
-
events: false,
|
|
643
|
-
emotion: emotionInstance,
|
|
644
|
-
designSystem: ds
|
|
645
|
-
});
|
|
646
|
-
const globalCSS = await generateGlobalCSS(ds, data.config || data.settings);
|
|
647
784
|
return {
|
|
648
|
-
html:
|
|
649
|
-
css:
|
|
785
|
+
html: result.html,
|
|
786
|
+
css: result.emotionCSS ? result.emotionCSS.join("\n") : "",
|
|
650
787
|
globalCSS,
|
|
651
788
|
resetCss: globalCSS.resetRules || generateResetCSS(ds.reset),
|
|
652
789
|
fontLinks: generateFontLinks(ds),
|
|
653
|
-
metadata: (0, import_metadata.extractMetadata)(data, route),
|
|
654
|
-
brKeyCount: Object.keys(result.registry).length
|
|
790
|
+
metadata: result.metadata || (0, import_metadata.extractMetadata)(data, route),
|
|
791
|
+
brKeyCount: result.registry ? Object.keys(result.registry).length : 0,
|
|
792
|
+
ssrTranslations: result.ssrTranslations,
|
|
793
|
+
prefetchedState,
|
|
794
|
+
activeLang
|
|
655
795
|
};
|
|
656
796
|
};
|
|
657
797
|
const renderPage = async (data, route = "/", options = {}) => {
|
|
658
|
-
const { lang, themeColor, isr, prefetch = true } = options;
|
|
798
|
+
const { lang, themeColor, isr, hydrate: hydrate2 = true, prefetch = true } = options;
|
|
659
799
|
const htmlLang = lang || data.state?.lang || data.app?.metadata?.lang || "en";
|
|
660
800
|
const result = await render(data, { route, prefetch });
|
|
661
801
|
if (!result) return null;
|
|
662
802
|
const metadata = { ...result.metadata };
|
|
663
803
|
if (themeColor) metadata["theme-color"] = themeColor;
|
|
664
804
|
const headTags = (0, import_metadata.generateHeadHtml)(metadata);
|
|
665
|
-
if (
|
|
666
|
-
|
|
805
|
+
if (result.emotionCSS && result.emotionCSS.length) {
|
|
806
|
+
for (const rule of result.emotionCSS) {
|
|
807
|
+
if (rule) _accumulatedEmotionCSS.add(rule);
|
|
808
|
+
}
|
|
667
809
|
}
|
|
668
|
-
const emotionCSS =
|
|
810
|
+
const emotionCSS = Array.from(_accumulatedEmotionCSS).join("\n");
|
|
669
811
|
const ds = data.designSystem || {};
|
|
670
812
|
const globalCSS = await generateGlobalCSS(ds, data.config || data.settings);
|
|
671
813
|
const fontLinks = generateFontLinks(ds);
|
|
@@ -674,7 +816,11 @@ const renderPage = async (data, route = "/", options = {}) => {
|
|
|
674
816
|
if (isr && isr.clientScript) {
|
|
675
817
|
const depth = route === "/" ? 0 : route.replace(/^\/|\/$/g, "").split("/").length;
|
|
676
818
|
const prefix = depth > 0 ? "../".repeat(depth) : "./";
|
|
677
|
-
|
|
819
|
+
if (hydrate2) {
|
|
820
|
+
isrBody = `<script>window.__BRENDER__ = true<\/script>
|
|
821
|
+
<script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
|
|
822
|
+
} else {
|
|
823
|
+
isrBody = `<script type="module">
|
|
678
824
|
{
|
|
679
825
|
const brEls = document.querySelectorAll('body > :not(script):not(style)')
|
|
680
826
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -692,11 +838,28 @@ const renderPage = async (data, route = "/", options = {}) => {
|
|
|
692
838
|
}
|
|
693
839
|
<\/script>
|
|
694
840
|
<script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const headConfig = { ...data.config || {} };
|
|
844
|
+
if (data.polyglot && !headConfig.polyglot) headConfig.polyglot = data.polyglot;
|
|
845
|
+
const polyglotCfg = headConfig.polyglot;
|
|
846
|
+
let resolvedHeadTags = headTags;
|
|
847
|
+
if (polyglotCfg) {
|
|
848
|
+
const defaultLang = polyglotCfg.defaultLang || "en";
|
|
849
|
+
const translations = {
|
|
850
|
+
...polyglotCfg.translations || {},
|
|
851
|
+
...result.ssrTranslations || {}
|
|
852
|
+
};
|
|
853
|
+
const langMap = translations[defaultLang] || {};
|
|
854
|
+
resolvedHeadTags = headTags.replace(/\{\{\s*([^|{}]+?)\s*\|\s*polyglot\s*\}\}/g, (match, key) => {
|
|
855
|
+
const trimmed = key.trim();
|
|
856
|
+
return langMap[trimmed] ?? match;
|
|
857
|
+
});
|
|
695
858
|
}
|
|
696
859
|
const html = `<!DOCTYPE html>
|
|
697
860
|
<html lang="${htmlLang}">
|
|
698
861
|
<head>
|
|
699
|
-
${
|
|
862
|
+
${resolvedHeadTags}
|
|
700
863
|
${fontLinks}
|
|
701
864
|
${globalCSS.fontFaceCSS ? `<style>${globalCSS.fontFaceCSS}</style>` : ""}
|
|
702
865
|
<style>
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createEnv } from "./env.js";
|
|
2
2
|
import { resetKeys, assignKeys, mapKeysToElements } from "./keys.js";
|
|
3
3
|
import { loadProject, loadAndRenderAll } from "./load.js";
|
|
4
|
-
import { render, renderElement, renderRoute, renderPage, resetGlobalCSSCache } from "./render.js";
|
|
4
|
+
import { render, renderElement, renderRoute, renderPage, resetGlobalCSSCache, getAccumulatedEmotionCSS, replaceEmotionCSS } from "./render.js";
|
|
5
5
|
import { extractMetadata, generateHeadHtml } from "./metadata.js";
|
|
6
6
|
import { collectBrNodes, hydrate } from "./hydrate.js";
|
|
7
7
|
import { generateSitemap } from "./sitemap.js";
|
|
@@ -18,6 +18,8 @@ var index_default = {
|
|
|
18
18
|
renderRoute,
|
|
19
19
|
renderPage,
|
|
20
20
|
resetGlobalCSSCache,
|
|
21
|
+
getAccumulatedEmotionCSS,
|
|
22
|
+
replaceEmotionCSS,
|
|
21
23
|
extractMetadata,
|
|
22
24
|
generateHeadHtml,
|
|
23
25
|
collectBrNodes,
|
|
@@ -34,6 +36,7 @@ export {
|
|
|
34
36
|
extractMetadata,
|
|
35
37
|
generateHeadHtml,
|
|
36
38
|
generateSitemap,
|
|
39
|
+
getAccumulatedEmotionCSS,
|
|
37
40
|
hydrate,
|
|
38
41
|
injectPrefetchedState,
|
|
39
42
|
loadAndRenderAll,
|
|
@@ -44,6 +47,7 @@ export {
|
|
|
44
47
|
renderElement,
|
|
45
48
|
renderPage,
|
|
46
49
|
renderRoute,
|
|
50
|
+
replaceEmotionCSS,
|
|
47
51
|
resetGlobalCSSCache,
|
|
48
52
|
resetKeys
|
|
49
53
|
};
|
package/dist/esm/load.js
CHANGED
|
@@ -70,17 +70,17 @@ const loadProject = async (projectPath) => {
|
|
|
70
70
|
bundleAndImport(join(symbolsDir, "files", "index.js"))
|
|
71
71
|
]);
|
|
72
72
|
return {
|
|
73
|
-
app: appModule?.default || {},
|
|
74
|
-
state: stateModule?.default || {},
|
|
75
|
-
dependencies: depsModule?.default || {},
|
|
76
|
-
components: componentsModule || {},
|
|
77
|
-
snippets: snippetsModule || {},
|
|
78
|
-
pages: pagesModule?.default || {},
|
|
79
|
-
functions: functionsModule || {},
|
|
80
|
-
methods: methodsModule || {},
|
|
81
|
-
designSystem: designSystemModule?.default || {},
|
|
82
|
-
files: filesModule?.default || {},
|
|
83
|
-
config: configModule?.default || {}
|
|
73
|
+
app: { ...appModule?.default || {} },
|
|
74
|
+
state: { ...stateModule?.default || {} },
|
|
75
|
+
dependencies: { ...depsModule?.default || {} },
|
|
76
|
+
components: { ...componentsModule || {} },
|
|
77
|
+
snippets: { ...snippetsModule || {} },
|
|
78
|
+
pages: { ...pagesModule?.default || {} },
|
|
79
|
+
functions: { ...functionsModule || {} },
|
|
80
|
+
methods: { ...methodsModule || {} },
|
|
81
|
+
designSystem: { ...designSystemModule?.default || {} },
|
|
82
|
+
files: { ...filesModule?.default || {} },
|
|
83
|
+
config: { ...configModule?.default || {} }
|
|
84
84
|
};
|
|
85
85
|
};
|
|
86
86
|
const loadAndRenderAll = async (projectPath, renderFn) => {
|