@symbo.ls/brender 3.14.0 → 3.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1602 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
- var render_exports = {};
29
- __export(render_exports, {
30
- getAccumulatedEmotionCSS: () => getAccumulatedEmotionCSS,
31
- render: () => render,
32
- renderElement: () => renderElement,
33
- renderPage: () => renderPage,
34
- renderRoute: () => renderRoute,
35
- replaceEmotionCSS: () => replaceEmotionCSS,
36
- resetGlobalCSSCache: () => resetGlobalCSSCache
37
- });
38
- module.exports = __toCommonJS(render_exports);
39
- var import_path = require("path");
40
- var import_fs = require("fs");
41
- var import_os = require("os");
42
- var import_crypto = require("crypto");
43
- var import_module = require("module");
44
- var import_env = require("./env.js");
45
- var import_keys = require("./keys.js");
46
- var import_metadata = require("./metadata.js");
47
- var import_hydrate = require("./hydrate.js");
48
- var import_prefetch = require("./prefetch.js");
49
- var import_linkedom = require("linkedom");
50
- var import_css = require("@symbo.ls/css");
51
- const import_meta = {};
52
- let _funcqlPlugin = null;
53
- const getFuncqlPlugin = async () => {
54
- if (_funcqlPlugin) return _funcqlPlugin;
55
- try {
56
- const mod = await import("@symbo.ls/funcql");
57
- _funcqlPlugin = mod.funcqlPlugin;
58
- return _funcqlPlugin;
59
- } catch {
60
- return null;
61
- }
62
- };
63
- const ssrResolve = (map, key) => {
64
- if (!map || !key) return void 0;
65
- if (map[key] !== void 0) return map[key];
66
- const parts = key.split(".");
67
- let v = map;
68
- for (const p of parts) {
69
- if (v == null || typeof v !== "object") return void 0;
70
- v = v[p];
71
- }
72
- return v;
73
- };
74
- const ssrTranslate = function(key, lang) {
75
- if (!key) return "";
76
- const ctx = this?.context;
77
- const poly = ctx?.polyglot;
78
- const activeLang = lang || poly?.defaultLang || "ka";
79
- if (poly?.translations) {
80
- const langMap = poly.translations[activeLang];
81
- if (langMap) {
82
- const val = ssrResolve(langMap, key);
83
- if (val !== void 0) return val;
84
- }
85
- }
86
- const root = this?.state?.root || ctx?.state?.root;
87
- if (root?.translations) {
88
- const langMap = root.translations[activeLang];
89
- if (langMap) {
90
- const val = ssrResolve(langMap, key);
91
- if (val !== void 0) return val;
92
- }
93
- }
94
- const defaultLang = poly?.defaultLang || "en";
95
- if (defaultLang !== activeLang && poly?.translations) {
96
- const fallback = poly.translations[defaultLang];
97
- if (fallback) {
98
- const val = ssrResolve(fallback, key);
99
- if (val !== void 0) return val;
100
- }
101
- }
102
- return key;
103
- };
104
- const ssrGetActiveLang = function() {
105
- const ctx = this?.context;
106
- return this?.state?.root?.lang || ctx?.polyglot?.defaultLang || "ka";
107
- };
108
- const structuredCloneDeep = (obj, seen = /* @__PURE__ */ new WeakMap()) => {
109
- if (obj === null || typeof obj !== "object") return obj;
110
- if (seen.has(obj)) return seen.get(obj);
111
- if (Array.isArray(obj)) {
112
- const arr = [];
113
- seen.set(obj, arr);
114
- for (const v of obj) arr.push(typeof v === "object" && v !== null ? structuredCloneDeep(v, seen) : v);
115
- return arr;
116
- }
117
- const clone = {};
118
- seen.set(obj, clone);
119
- for (const k of Object.keys(obj)) {
120
- const v = obj[k];
121
- clone[k] = typeof v === "object" && v !== null ? structuredCloneDeep(v, seen) : v;
122
- }
123
- return clone;
124
- };
125
- const safeJsonReplacer = () => {
126
- const seen = /* @__PURE__ */ new WeakSet();
127
- return (key, value) => {
128
- if (typeof value === "function") return void 0;
129
- if (typeof value === "object" && value !== null) {
130
- if (seen.has(value)) return void 0;
131
- seen.add(value);
132
- }
133
- return value;
134
- };
135
- };
136
- let _brenderRequire = null;
137
- try {
138
- if (import_meta.url) {
139
- _brenderRequire = (0, import_module.createRequire)(import_meta.url);
140
- }
141
- } catch {
142
- }
143
- const detectWorkspace = () => {
144
- if (!import_meta.url || !_brenderRequire) {
145
- return { isMonorepo: false, monorepoRoot: null, resolvePackage: (pkg) => pkg };
146
- }
147
- const brenderDir = (0, import_fs.realpathSync)(new URL(".", import_meta.url).pathname);
148
- const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
149
- const isMonorepo = (0, import_fs.existsSync)((0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "createDomql.js"));
150
- if (isMonorepo) {
151
- return { isMonorepo: true, monorepoRoot };
152
- }
153
- let smblsRoot;
154
- try {
155
- const smblsPkg = _brenderRequire.resolve("smbls/package.json");
156
- smblsRoot = (0, import_path.dirname)(smblsPkg);
157
- } catch {
158
- let dir2 = brenderDir;
159
- while (dir2 !== (0, import_path.dirname)(dir2)) {
160
- const candidate = (0, import_path.resolve)(dir2, "node_modules", "smbls");
161
- if ((0, import_fs.existsSync)((0, import_path.resolve)(candidate, "package.json"))) {
162
- smblsRoot = candidate;
163
- break;
164
- }
165
- dir2 = (0, import_path.dirname)(dir2);
166
- }
167
- }
168
- let _smblsRequire = _brenderRequire;
169
- if (smblsRoot) {
170
- try {
171
- _smblsRequire = (0, import_module.createRequire)((0, import_path.resolve)(smblsRoot, "package.json"));
172
- } catch {
173
- }
174
- }
175
- let projectRoot;
176
- let dir = process.cwd();
177
- while (dir !== (0, import_path.dirname)(dir)) {
178
- if ((0, import_fs.existsSync)((0, import_path.resolve)(dir, "package.json"))) {
179
- projectRoot = dir;
180
- break;
181
- }
182
- dir = (0, import_path.dirname)(dir);
183
- }
184
- let _projectRequire = _smblsRequire;
185
- if (projectRoot) {
186
- try {
187
- _projectRequire = (0, import_module.createRequire)((0, import_path.resolve)(projectRoot, "package.json"));
188
- } catch {
189
- }
190
- }
191
- return { isMonorepo: false, smblsRoot, brenderDir, projectRoot, _smblsRequire, _projectRequire };
192
- };
193
- const tryRequireResolve = (ws, specifier) => {
194
- const requireFns = ws.isMonorepo ? [_brenderRequire] : [ws._smblsRequire, ws._projectRequire, _brenderRequire].filter(Boolean);
195
- for (const req of requireFns) {
196
- try {
197
- return req.resolve(specifier);
198
- } catch {
199
- }
200
- }
201
- return null;
202
- };
203
- const resolvePackagePath = (ws, pkgName, ...subpath) => {
204
- if (ws.isMonorepo) {
205
- return (0, import_path.resolve)(ws.monorepoRoot, "packages", pkgName, ...subpath);
206
- }
207
- const pkgJson = tryRequireResolve(ws, `${pkgName}/package.json`);
208
- if (pkgJson) return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
209
- return null;
210
- };
211
- const resolvePluginPath = (ws, pluginName, ...subpath) => {
212
- if (ws.isMonorepo) {
213
- return (0, import_path.resolve)(ws.monorepoRoot, "plugins", pluginName, ...subpath);
214
- }
215
- const pkgJson = tryRequireResolve(ws, `@symbo.ls/${pluginName}/package.json`);
216
- if (pkgJson) return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
217
- return null;
218
- };
219
- const resolveSymbolsPackage = (ws, pkg, ...subpath) => {
220
- if (ws.isMonorepo) {
221
- for (const dir of ["packages", "plugins"]) {
222
- const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, ...subpath);
223
- if ((0, import_fs.existsSync)(src)) return src;
224
- }
225
- return null;
226
- }
227
- const pkgJson = tryRequireResolve(ws, `@symbo.ls/${pkg}/package.json`);
228
- if (pkgJson) return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
229
- return null;
230
- };
231
- const resolveDomqlPackage = (ws, pkg, ...subpath) => {
232
- if (ws.isMonorepo) {
233
- return (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, ...subpath);
234
- }
235
- const pkgJson = tryRequireResolve(ws, `@symbo.ls/${pkg}/package.json`);
236
- if (pkgJson) return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
237
- return null;
238
- };
239
- let _cachedCreateDomql = null;
240
- const bundleCreateDomql = async () => {
241
- if (_cachedCreateDomql) return _cachedCreateDomql;
242
- const ws = detectWorkspace();
243
- if (!_brenderRequire) {
244
- try {
245
- const mod2 = await import("./dist/createDomql.bundled.mjs");
246
- _cachedCreateDomql = mod2;
247
- return mod2;
248
- } catch (err) {
249
- throw new Error(`brender: pre-bundled createDomql not available in bundled runtime: ${err.message}`);
250
- }
251
- }
252
- let entry;
253
- if (ws.isMonorepo) {
254
- entry = (0, import_path.resolve)(ws.monorepoRoot, "packages", "smbls", "src", "createDomql.js");
255
- } else if (ws.smblsRoot) {
256
- const srcEntry = (0, import_path.resolve)(ws.smblsRoot, "src", "createDomql.js");
257
- const distEntry = (0, import_path.resolve)(ws.smblsRoot, "dist", "esm", "src", "createDomql.js");
258
- entry = (0, import_fs.existsSync)(srcEntry) ? srcEntry : distEntry;
259
- }
260
- if (!entry || !(0, import_fs.existsSync)(entry)) {
261
- throw new Error(`brender: cannot find createDomql.js (isMonorepo=${ws.isMonorepo}, entry=${entry})`);
262
- }
263
- const esbuild = await import("esbuild");
264
- const outFile = (0, import_path.join)((0, import_os.tmpdir)(), `br_createDomql_${(0, import_crypto.randomBytes)(6).toString("hex")}.mjs`);
265
- const tryResolve = (base) => {
266
- if (!base) return null;
267
- const src = (0, import_path.resolve)(base, "src", "index.js");
268
- if ((0, import_fs.existsSync)(src)) return src;
269
- const idx = (0, import_path.resolve)(base, "index.js");
270
- if ((0, import_fs.existsSync)(idx)) return idx;
271
- return null;
272
- };
273
- const workspacePlugin = {
274
- name: "workspace-resolve",
275
- setup(build) {
276
- build.onResolve({ filter: /^smbls/ }, (args) => {
277
- const subpath = args.path.replace(/^smbls\/?/, "");
278
- const smblsBase = ws.isMonorepo ? (0, import_path.resolve)(ws.monorepoRoot, "packages", "smbls") : ws.smblsRoot;
279
- if (!smblsBase) return;
280
- if (!subpath) {
281
- const r = tryResolve(smblsBase);
282
- if (r) return { path: r };
283
- return;
284
- }
285
- const full = (0, import_path.resolve)(smblsBase, subpath);
286
- if ((0, import_fs.existsSync)(full)) return { path: full };
287
- if ((0, import_fs.existsSync)(full + ".js")) return { path: full + ".js" };
288
- const idx = (0, import_path.resolve)(full, "index.js");
289
- if ((0, import_fs.existsSync)(idx)) return { path: idx };
290
- });
291
- build.onResolve({ filter: /^domql$/ }, (args) => {
292
- if (ws.isMonorepo) {
293
- const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "src", "index.js");
294
- if ((0, import_fs.existsSync)(src)) return { path: src };
295
- const dist = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "index.js");
296
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
297
- } else {
298
- try {
299
- const pkgJson = _require.resolve("domql/package.json");
300
- const r = tryResolve((0, import_path.dirname)(pkgJson));
301
- if (r) return { path: r };
302
- } catch {
303
- }
304
- }
305
- });
306
- build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
307
- const pkg = args.path.replace("@symbo.ls/", "");
308
- if (pkg === "sync") return { path: "sync-stub", namespace: "brender-stub" };
309
- if (ws.isMonorepo) {
310
- for (const dir of ["packages", "plugins"]) {
311
- const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "src", "index.js");
312
- if ((0, import_fs.existsSync)(src)) return { path: src };
313
- const dist = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "index.js");
314
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
315
- }
316
- const blank = (0, import_path.resolve)(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
317
- if (pkg === "default-config" && (0, import_fs.existsSync)(blank)) return { path: blank };
318
- } else {
319
- const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
320
- if (resolved && (0, import_fs.existsSync)(resolved)) return { path: resolved };
321
- const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
322
- if (resolvedIdx && (0, import_fs.existsSync)(resolvedIdx)) return { path: resolvedIdx };
323
- if (pkg === "default-config") {
324
- const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
325
- if (blank && (0, import_fs.existsSync)(blank)) return { path: blank };
326
- }
327
- }
328
- });
329
- build.onResolve({ filter: /^@domql\// }, (args) => {
330
- const pkg = args.path.replace("@symbo.ls/", "");
331
- if (ws.isMonorepo) {
332
- const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
333
- if ((0, import_fs.existsSync)(src)) return { path: src };
334
- const dist = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "index.js");
335
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
336
- } else {
337
- const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
338
- if (resolved && (0, import_fs.existsSync)(resolved)) return { path: resolved };
339
- const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
340
- if (resolvedIdx && (0, import_fs.existsSync)(resolvedIdx)) return { path: resolvedIdx };
341
- }
342
- });
343
- build.onResolve({ filter: /^css-in-props/ }, (args) => {
344
- let base;
345
- if (ws.isMonorepo) {
346
- base = (0, import_path.resolve)(ws.monorepoRoot, "packages", "css-in-props");
347
- } else {
348
- const pkgJson = tryRequireResolve(ws, "css-in-props/package.json");
349
- if (pkgJson) base = (0, import_path.dirname)(pkgJson);
350
- }
351
- if (!base) return;
352
- const subpath = args.path.replace(/^css-in-props\/?/, "");
353
- if (subpath) {
354
- const full = (0, import_path.resolve)(base, subpath);
355
- const idx = (0, import_path.resolve)(full, "index.js");
356
- if ((0, import_fs.existsSync)(idx)) return { path: idx };
357
- if ((0, import_fs.existsSync)(full + ".js")) return { path: full + ".js" };
358
- if ((0, import_fs.existsSync)(full)) return { path: full };
359
- }
360
- const r = tryResolve(base);
361
- if (r) return { path: r };
362
- });
363
- build.onResolve({ filter: /^@emotion\// }, (args) => {
364
- let nm;
365
- if (ws.isMonorepo) {
366
- nm = (0, import_path.resolve)(ws.monorepoRoot, "node_modules", args.path);
367
- } else {
368
- const pkgJson = tryRequireResolve(ws, `${args.path}/package.json`);
369
- if (!pkgJson) return;
370
- nm = (0, import_path.dirname)(pkgJson);
371
- }
372
- if ((0, import_fs.existsSync)(nm)) {
373
- const pkg = (0, import_path.resolve)(nm, "package.json");
374
- if ((0, import_fs.existsSync)(pkg)) {
375
- try {
376
- const p = JSON.parse((0, import_fs.readFileSync)(pkg, "utf8"));
377
- const main = p.module || p.main || "dist/emotion-css.esm.js";
378
- return { path: (0, import_path.resolve)(nm, main) };
379
- } catch {
380
- }
381
- }
382
- return { path: nm };
383
- }
384
- });
385
- build.onResolve({ filter: /\.json$/ }, (args) => {
386
- if (args.resolveDir) {
387
- const full = (0, import_path.resolve)(args.resolveDir, args.path);
388
- if ((0, import_fs.existsSync)(full)) return { path: full };
389
- }
390
- });
391
- build.onLoad({ filter: /smbls\/.*options\.js$/ }, async (args) => {
392
- if (!args.path.includes("smbls/") || !args.path.endsWith("options.js")) return;
393
- let contents = (0, import_fs.readFileSync)(args.path, "utf8");
394
- contents = contents.replace(
395
- /import\s*\{[^}]*version[^}]*\}\s*from\s*['"][^'"]*package\.json['"][^;\n]*/,
396
- "const version = '0.0.0'"
397
- );
398
- contents = contents.replace(
399
- /import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,
400
- "// createRequire removed for brender build"
401
- );
402
- return { contents, loader: "js" };
403
- });
404
- build.onLoad({ filter: /smbls\/.*init\.js$/ }, async (args) => {
405
- if (!args.path.includes("smbls/") || !args.path.endsWith("init.js")) return;
406
- let contents = (0, import_fs.readFileSync)(args.path, "utf8");
407
- contents = contents.replace(
408
- /import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,
409
- "// createRequire removed for brender build"
410
- );
411
- return { contents, loader: "js" };
412
- });
413
- build.onLoad({ filter: /fetch\/adapters\/supabase\.js$/ }, () => {
414
- return {
415
- contents: `export const setup = async () => null;
416
- export const supabaseAdapter = () => ({name:'supabase'});
417
- `,
418
- loader: "js"
419
- };
420
- });
421
- build.onLoad({ filter: /.*/, namespace: "brender-stub" }, () => {
422
- return { contents: "export const SyncComponent = {}; export const Inspect = {}; export const Notifications = {}; export default {}", loader: "js" };
423
- });
424
- build.onLoad({ filter: /smbls\/src\/router\.js$/ }, async (args) => {
425
- let contents = (0, import_fs.readFileSync)(args.path, "utf8");
426
- contents = contents.replace(
427
- /import\s*\{\s*Link\s*\}\s*from\s*['"]smbls['"]/,
428
- `const Link = { tag: 'a', attr: { href: (el) => el.href } }`
429
- );
430
- return { contents, loader: "js" };
431
- });
432
- build.onLoad({ filter: /fetchOnCreate\.js$/ }, async (args) => {
433
- if (!args.path.includes("smbls/")) return;
434
- let contents = (0, import_fs.readFileSync)(args.path, "utf8");
435
- contents = contents.replace(
436
- /window\s*&&\s*window\.location\s*\?\s*window\.location\.host\.includes/g,
437
- "window && window.location && window.location.host ? window.location.host.includes"
438
- );
439
- return { contents, loader: "js" };
440
- });
441
- }
442
- };
443
- await esbuild.build({
444
- entryPoints: [entry],
445
- bundle: true,
446
- format: "esm",
447
- platform: "node",
448
- outfile: outFile,
449
- write: true,
450
- logLevel: "warning",
451
- plugins: [workspacePlugin],
452
- nodePaths: ws.isMonorepo ? [(0, import_path.resolve)(ws.monorepoRoot, "node_modules")] : [
453
- ...ws.smblsRoot ? [(0, import_path.resolve)(ws.smblsRoot, "node_modules")] : [],
454
- ...ws.projectRoot ? [(0, import_path.resolve)(ws.projectRoot, "node_modules")] : [],
455
- ...ws.smblsRoot ? [(0, import_path.resolve)(ws.smblsRoot, "..", "..", "node_modules")] : []
456
- ].filter((p) => (0, import_fs.existsSync)(p)),
457
- supported: { "import-attributes": false },
458
- external: [
459
- "fs",
460
- "path",
461
- "os",
462
- "crypto",
463
- "url",
464
- "http",
465
- "https",
466
- "stream",
467
- "util",
468
- "events",
469
- "buffer",
470
- "child_process",
471
- "worker_threads",
472
- "net",
473
- "tls",
474
- "dns",
475
- "dgram",
476
- "zlib",
477
- "assert",
478
- "querystring",
479
- "string_decoder",
480
- "readline",
481
- "perf_hooks",
482
- "async_hooks",
483
- "v8",
484
- "vm",
485
- "cluster",
486
- "inspector",
487
- "module",
488
- "process",
489
- "tty",
490
- "color-contrast-checker",
491
- "linkedom"
492
- ]
493
- });
494
- const mod = await import(`file://${outFile}`);
495
- if (!process.env.BRENDER_DEBUG) {
496
- try {
497
- (0, import_fs.unlinkSync)(outFile);
498
- } catch {
499
- }
500
- } else {
501
- console.log("[brender] Bundle saved:", outFile);
502
- }
503
- _cachedCreateDomql = mod;
504
- return mod;
505
- };
506
- const UIKIT_STUBS = {
507
- Box: {},
508
- Focusable: {},
509
- Block: { display: "block" },
510
- Inline: { display: "inline" },
511
- Flex: { display: "flex" },
512
- InlineFlex: { display: "inline-flex" },
513
- Grid: { display: "grid" },
514
- InlineGrid: { display: "inline-grid" },
515
- Link: {
516
- tag: "a",
517
- attr: {
518
- href: (el) => el.href,
519
- target: (el) => el.target,
520
- rel: (el) => el.rel
521
- }
522
- },
523
- A: { extends: "Link" },
524
- RouteLink: { extends: "Link" },
525
- Img: {
526
- tag: "img",
527
- attr: {
528
- src: (el) => {
529
- let src = el.src;
530
- if (typeof src === "string" && src.includes("{{")) {
531
- src = el.call("replaceLiteralsWithObjectFields", src, el.state);
532
- }
533
- return src;
534
- },
535
- alt: (el) => el.alt,
536
- loading: (el) => el.loading
537
- }
538
- },
539
- Image: { extends: "Img" },
540
- Button: { tag: "button" },
541
- FocusableComponent: { tag: "button" },
542
- Form: { tag: "form" },
543
- Input: { tag: "input" },
544
- TextArea: { tag: "textarea" },
545
- Textarea: { tag: "textarea" },
546
- Select: { tag: "select" },
547
- Label: { tag: "label" },
548
- Iframe: { tag: "iframe" },
549
- Video: { tag: "video" },
550
- Audio: { tag: "audio" },
551
- Canvas: { tag: "canvas" },
552
- Span: { tag: "span" },
553
- P: { tag: "p" },
554
- H1: { tag: "h1" },
555
- H2: { tag: "h2" },
556
- H3: { tag: "h3" },
557
- H4: { tag: "h4" },
558
- H5: { tag: "h5" },
559
- H6: { tag: "h6" },
560
- Svg: {
561
- tag: "svg",
562
- attr: {
563
- xmlns: "http://www.w3.org/2000/svg",
564
- "xmlns:xlink": "http://www.w3.org/1999/xlink"
565
- }
566
- },
567
- Text: { tag: "span" }
568
- };
569
- const buildPathRegistry = (element, path = "") => {
570
- if (!element || !element.__ref) return {};
571
- const registry = {};
572
- const brKey = element.__ref.__brKey;
573
- if (brKey) registry[path === "" ? "__root" : path] = brKey;
574
- if (element.__ref.__children) {
575
- for (const childKey of element.__ref.__children) {
576
- const child = element[childKey];
577
- if (child && child.__ref) {
578
- const childPath = path === "" ? childKey : `${path}.${childKey}`;
579
- Object.assign(registry, buildPathRegistry(child, childPath));
580
- }
581
- }
582
- }
583
- return registry;
584
- };
585
- const render = async (data, options = {}) => {
586
- const { route = "/", pathname, state: stateOverrides, context: contextOverrides, prefetch = false } = options;
587
- const locationPath = pathname || route;
588
- const _prevLocPrefetch = globalThis.location;
589
- const _prevWinPrefetch = globalThis.window;
590
- if (!globalThis.location || globalThis.location.pathname !== locationPath) {
591
- globalThis.location = { pathname: locationPath, href: locationPath, search: "", hash: "", origin: "" };
592
- }
593
- if (!globalThis.window) {
594
- globalThis.window = { location: globalThis.location };
595
- }
596
- let prefetchedPages;
597
- if (prefetch) {
598
- try {
599
- const pages = data.pages || {};
600
- prefetchedPages = { ...pages };
601
- const stateUpdates = await (0, import_prefetch.prefetchPageData)(data, route);
602
- if (stateUpdates.size) {
603
- const pageDef = JSON.parse(JSON.stringify(pages[route], (key, value) => {
604
- if (typeof value === "function") return void 0;
605
- return value;
606
- }));
607
- const copyFunctions = (src, dst) => {
608
- if (!src || !dst) return;
609
- for (const k in src) {
610
- if (typeof src[k] === "function") {
611
- dst[k] = src[k];
612
- } else if (typeof src[k] === "object" && src[k] !== null && !Array.isArray(src[k]) && typeof dst[k] === "object" && dst[k] !== null) {
613
- copyFunctions(src[k], dst[k]);
614
- }
615
- }
616
- };
617
- copyFunctions(pages[route], pageDef);
618
- (0, import_prefetch.injectPrefetchedState)(pageDef, stateUpdates);
619
- prefetchedPages[route] = pageDef;
620
- }
621
- } catch (prefetchErr) {
622
- console.error("[brender] Prefetch error:", prefetchErr);
623
- prefetchedPages = data.pages;
624
- }
625
- }
626
- let ssrTranslations;
627
- if (prefetch) {
628
- try {
629
- ssrTranslations = await (0, import_prefetch.fetchSSRTranslations)(data);
630
- } catch (e) {
631
- console.warn("[brender] SSR translation fetch failed:", e.message);
632
- }
633
- }
634
- if (_prevLocPrefetch !== void 0) globalThis.location = _prevLocPrefetch;
635
- else delete globalThis.location;
636
- if (_prevWinPrefetch !== void 0) globalThis.window = _prevWinPrefetch;
637
- else delete globalThis.window;
638
- const { window, document } = (0, import_env.createEnv)();
639
- const body = document.body;
640
- window.location.pathname = locationPath;
641
- const _prevDoc = globalThis.document;
642
- const _prevLoc = globalThis.location;
643
- globalThis.document = document;
644
- globalThis.location = window.location;
645
- const { createDomqlElement } = await bundleCreateDomql();
646
- const app = structuredCloneDeep(data.app || {});
647
- const config = { ...data.config || {} };
648
- if (data.polyglot && !config.polyglot) config.polyglot = data.polyglot;
649
- if (data.fetch && !config.fetch) config.fetch = data.fetch;
650
- if (data.router && !config.router) config.router = data.router;
651
- for (const k of ["useReset", "useVariable", "useFontImport", "useIconSprite", "useSvgSprite", "useDefaultConfig", "useDocumentTheme"]) {
652
- if (data[k] != null && config[k] == null) config[k] = data[k];
653
- }
654
- const polyglotConfig = config.polyglot ? { ...config.polyglot } : void 0;
655
- if (ssrTranslations && polyglotConfig) {
656
- polyglotConfig.translations = {
657
- ...polyglotConfig.translations || {},
658
- ...ssrTranslations
659
- };
660
- }
661
- const baseState = structuredCloneDeep(data.state || {});
662
- if (ssrTranslations || polyglotConfig) {
663
- if (!baseState.root) baseState.root = {};
664
- if (polyglotConfig) {
665
- baseState.root.lang = baseState.root.lang || polyglotConfig.defaultLang || "en";
666
- }
667
- if (ssrTranslations) {
668
- baseState.root.translations = {
669
- ...baseState.root.translations || {},
670
- ...ssrTranslations
671
- };
672
- }
673
- }
674
- (0, import_css.reset)();
675
- const ctx = {
676
- state: baseState,
677
- ...stateOverrides ? { state: { ...baseState, ...stateOverrides } } : {},
678
- dependencies: structuredCloneDeep(data.dependencies || {}),
679
- components: structuredCloneDeep(data.components || {}),
680
- snippets: structuredCloneDeep(data.snippets || {}),
681
- pages: structuredCloneDeep(prefetchedPages || data.pages || {}),
682
- functions: {
683
- ...data.functions || {},
684
- // SSR polyglot functions — enable {{ key | polyglot }} resolution during render
685
- polyglot: ssrTranslate,
686
- getActiveLang: ssrGetActiveLang,
687
- getLang: ssrGetActiveLang
688
- },
689
- methods: data.methods || {},
690
- designSystem: structuredCloneDeep(data.designSystem || {}),
691
- files: data.files || {},
692
- sharedLibraries: data.sharedLibraries || [],
693
- ...config,
694
- // Override polyglot with SSR-enriched version
695
- ...polyglotConfig ? { polyglot: polyglotConfig } : {},
696
- // Virtual DOM environment
697
- document,
698
- window,
699
- parent: { node: body },
700
- initOptions: {},
701
- // Disable sourcemap tracking in SSR — it causes stack overflows
702
- // when state contains large data arrays (articles, events, etc.)
703
- domqlOptions: { sourcemap: false },
704
- // Caller overrides
705
- ...contextOverrides || {}
706
- };
707
- const funcql = await getFuncqlPlugin();
708
- if (funcql) {
709
- ctx.plugins = ctx.plugins || [];
710
- if (!ctx.plugins.some((p) => p.name === "funcql")) {
711
- ctx.plugins.push(funcql);
712
- }
713
- }
714
- (0, import_keys.resetKeys)();
715
- const element = await createDomqlElement(app, ctx);
716
- const flushDelay = prefetch ? 2e3 : 50;
717
- await new Promise((r) => setTimeout(r, flushDelay));
718
- (0, import_keys.assignKeys)(body);
719
- const registry = (0, import_keys.mapKeysToElements)(element);
720
- const brRegistry = buildPathRegistry(element);
721
- const metadata = (0, import_metadata.extractMetadata)(data, route, element, element?.state);
722
- const emotionCSS = [];
723
- const head = document.head || document.querySelector("head");
724
- if (head) {
725
- for (const style of head.querySelectorAll("style")) {
726
- if (style.sheet && style.sheet.cssRules) {
727
- for (const rule of style.sheet.cssRules) {
728
- if (rule.cssText) emotionCSS.push(rule.cssText);
729
- }
730
- }
731
- if (!emotionCSS.length) {
732
- const content = style.textContent || "";
733
- if (content) emotionCSS.push(content);
734
- }
735
- }
736
- }
737
- let html = fixSvgContent(body.innerHTML);
738
- if (ssrTranslations) {
739
- const defaultLang = polyglotConfig?.defaultLang || "en";
740
- const langMap = ssrTranslations[defaultLang] || Object.values(ssrTranslations)[0] || {};
741
- html = html.replace(/\{\{\s*([^|{}]+?)\s*\|\s*polyglot\s*\}\}/g, (match, key) => {
742
- const trimmed = key.trim();
743
- return langMap[trimmed] ?? match;
744
- });
745
- }
746
- if (_prevDoc !== void 0) globalThis.document = _prevDoc;
747
- else delete globalThis.document;
748
- if (_prevLoc !== void 0) globalThis.location = _prevLoc;
749
- else delete globalThis.location;
750
- return { html, metadata, registry, brRegistry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
751
- };
752
- const renderElement = async (elementDef, options = {}) => {
753
- const { context = {} } = options;
754
- const { window, document } = (0, import_env.createEnv)();
755
- const body = document.body;
756
- const { create } = await import("@symbo.ls/element");
757
- const domqlUtils = await import("@symbo.ls/utils");
758
- const components = { ...UIKIT_STUBS, ...context.components || {} };
759
- const utils = {
760
- ...domqlUtils,
761
- ...context.utils || {},
762
- ...context.functions || {}
763
- };
764
- (0, import_keys.resetKeys)();
765
- let element;
766
- try {
767
- element = create(elementDef, { node: body }, "root", {
768
- context: { document, window, ...context, components, utils }
769
- });
770
- } catch (err) {
771
- }
772
- (0, import_keys.assignKeys)(body);
773
- const registry = element ? (0, import_keys.mapKeysToElements)(element) : {};
774
- const html = fixSvgContent(body.innerHTML);
775
- return { html, registry, element };
776
- };
777
- const fixSvgContent = (html) => {
778
- return html.replace(
779
- /(<svg\b[^>]*>)([\s\S]*?)(<\/svg>)/gi,
780
- (match, open, content, close) => {
781
- if (content.includes("&lt;")) {
782
- const unescaped = content.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#39;/g, "'");
783
- return open + unescaped + close;
784
- }
785
- return match;
786
- }
787
- );
788
- };
789
- let _cachedGlobalCSS = null;
790
- const SCRATCH_CONFIG_FLAGS = [
791
- "globalTheme",
792
- "themeStorageKey",
793
- "themeRoot",
794
- "useReset",
795
- "useVariable",
796
- "useFontImport",
797
- "useIconSprite",
798
- "useSvgSprite",
799
- "useDocumentTheme",
800
- "useDefaultConfig",
801
- "useDefaultIcons",
802
- "useThemeSuffixedVars",
803
- "verbose",
804
- "semanticIcons"
805
- ];
806
- const pickProjectConfig = (data) => {
807
- if (!data || typeof data !== "object") return null;
808
- if (data.config && typeof data.config === "object") return data.config;
809
- const out = {};
810
- let any = false;
811
- for (const flag of SCRATCH_CONFIG_FLAGS) {
812
- if (Object.prototype.hasOwnProperty.call(data, flag)) {
813
- out[flag] = data[flag];
814
- any = true;
815
- }
816
- }
817
- if (any) return out;
818
- return data.settings || null;
819
- };
820
- const generateGlobalCSS = async (ds, config) => {
821
- if (_cachedGlobalCSS) return _cachedGlobalCSS;
822
- try {
823
- const { existsSync: existsSync2, writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("fs");
824
- const { tmpdir: tmpdir2 } = await import("os");
825
- const { randomBytes: randomBytes2 } = await import("crypto");
826
- try {
827
- tmpdir2();
828
- } catch {
829
- return {};
830
- }
831
- const esbuild = await import("esbuild");
832
- const dsJson = JSON.stringify(ds || {}, safeJsonReplacer());
833
- const cfgJson = JSON.stringify(config || {}, safeJsonReplacer());
834
- const tmpEntry = (0, import_path.join)(tmpdir2(), `br_global_${randomBytes2(6).toString("hex")}.mjs`);
835
- const tmpOut = (0, import_path.join)(tmpdir2(), `br_global_${randomBytes2(6).toString("hex")}_out.mjs`);
836
- writeFileSync2(tmpEntry, `
837
- import { set, getActiveConfig, getFontFaceString } from '@symbo.ls/scratch'
838
- import { DEFAULT_CONFIG } from '@symbo.ls/default-config'
839
-
840
- const ds = ${dsJson}
841
- const cfg = ${cfgJson}
842
-
843
- // Merge with defaults (same as initEmotion)
844
- const merged = {}
845
- for (const k in DEFAULT_CONFIG) merged[k] = DEFAULT_CONFIG[k]
846
- for (const k in ds) {
847
- if (typeof ds[k] === 'object' && !Array.isArray(ds[k]) && typeof merged[k] === 'object' && !Array.isArray(merged[k])) {
848
- merged[k] = { ...merged[k], ...ds[k] }
849
- } else {
850
- merged[k] = ds[k]
851
- }
852
- }
853
-
854
- const conf = set({
855
- useReset: true,
856
- useVariable: true,
857
- useFontImport: true,
858
- useDocumentTheme: true,
859
- useDefaultConfig: true,
860
- globalTheme: 'auto',
861
- ...merged,
862
- ...cfg
863
- }, { newConfig: {} })
864
-
865
- const result = {
866
- CSS_VARS: conf.CSS_VARS || {},
867
- CSS_MEDIA_VARS: conf.CSS_MEDIA_VARS || {},
868
- reset: conf.reset || {},
869
- animation: conf.animation || {}
870
- }
871
- // Export as globalThis so we can read it
872
- globalThis.__BR_GLOBAL_CSS__ = result
873
- export default result
874
- `);
875
- const ws = detectWorkspace();
876
- const workspacePlugin = {
877
- name: "workspace-resolve",
878
- setup(build) {
879
- build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
880
- const pkg = args.path.replace("@symbo.ls/", "");
881
- if (ws.isMonorepo) {
882
- for (const dir of ["packages", "plugins"]) {
883
- const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "src", "index.js");
884
- if (existsSync2(src)) return { path: src };
885
- const dist = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "index.js");
886
- if (existsSync2(dist)) return { path: dist };
887
- }
888
- const blank = (0, import_path.resolve)(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
889
- if (pkg === "default-config" && existsSync2(blank)) return { path: blank };
890
- } else {
891
- const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
892
- if (resolved && existsSync2(resolved)) return { path: resolved };
893
- const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
894
- if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
895
- if (pkg === "default-config") {
896
- const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
897
- if (blank && existsSync2(blank)) return { path: blank };
898
- }
899
- }
900
- });
901
- build.onResolve({ filter: /^@domql\// }, (args) => {
902
- const pkg = args.path.replace("@symbo.ls/", "");
903
- if (ws.isMonorepo) {
904
- const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
905
- if (existsSync2(src)) return { path: src };
906
- } else {
907
- const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
908
- if (resolved && existsSync2(resolved)) return { path: resolved };
909
- const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
910
- if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
911
- }
912
- });
913
- }
914
- };
915
- await esbuild.build({
916
- entryPoints: [tmpEntry],
917
- bundle: true,
918
- format: "esm",
919
- platform: "node",
920
- outfile: tmpOut,
921
- write: true,
922
- logLevel: "silent",
923
- plugins: [workspacePlugin],
924
- nodePaths: ws.isMonorepo ? [(0, import_path.resolve)(ws.monorepoRoot, "node_modules")] : [
925
- ...ws.smblsRoot ? [(0, import_path.resolve)(ws.smblsRoot, "node_modules")] : [],
926
- ...ws.projectRoot ? [(0, import_path.resolve)(ws.projectRoot, "node_modules")] : [],
927
- ...ws.smblsRoot ? [(0, import_path.resolve)(ws.smblsRoot, "..", "..", "node_modules")] : []
928
- ].filter((p) => existsSync2(p)),
929
- external: ["fs", "path", "os", "crypto", "url", "http", "https", "stream", "util", "events", "buffer", "child_process", "worker_threads", "net", "tls", "dns", "dgram", "zlib", "assert", "querystring", "string_decoder", "readline", "perf_hooks", "async_hooks", "v8", "vm", "cluster", "inspector", "module", "process", "tty", "color-contrast-checker"]
930
- });
931
- const mod = await import(`file://${tmpOut}`);
932
- const data = mod.default || {};
933
- try {
934
- unlinkSync2(tmpEntry);
935
- } catch {
936
- }
937
- try {
938
- unlinkSync2(tmpOut);
939
- } catch {
940
- }
941
- const cssVars = data.CSS_VARS || {};
942
- const cssMediaVars = data.CSS_MEDIA_VARS || {};
943
- const reset = data.RESET || {};
944
- const animations = data.ANIMATION || {};
945
- const varDecls = Object.entries(cssVars).map(([k, v]) => ` ${k}: ${v}`).join(";\n");
946
- let rootRule = varDecls ? `:root {
947
- ${varDecls};
948
- }` : "";
949
- const themeVarRules = Object.entries(cssMediaVars).map(([key, vars]) => {
950
- const decls = Object.entries(vars).map(([k, v]) => ` ${k}: ${v}`).join(";\n");
951
- if (!decls) return "";
952
- if (key.startsWith("@media")) {
953
- return `${key} {
954
- :root:not([data-theme]) {
955
- ${decls};
956
- }
957
- }`;
958
- }
959
- return `${key} {
960
- ${decls};
961
- }`;
962
- }).filter(Boolean).join("\n\n");
963
- if (themeVarRules) rootRule += "\n\n" + themeVarRules;
964
- const resetRules = generateResetCSS(reset);
965
- const keyframeRules = [];
966
- for (const name in animations) {
967
- const frames = animations[name];
968
- if (!frames || typeof frames !== "object") continue;
969
- const frameRules = Object.entries(frames).map(([step, p]) => {
970
- if (typeof p !== "object") return "";
971
- const decls = Object.entries(p).map(([k, v]) => `${camelToKebab(k)}: ${v}`).join("; ");
972
- return ` ${step} { ${decls}; }`;
973
- }).join("\n");
974
- keyframeRules.push(`@keyframes ${name} {
975
- ${frameRules}
976
- }`);
977
- }
978
- _cachedGlobalCSS = {
979
- rootRule,
980
- resetRules,
981
- fontFaceCSS: "",
982
- keyframeRules: keyframeRules.join("\n")
983
- };
984
- return _cachedGlobalCSS;
985
- } catch (err) {
986
- console.warn("generateGlobalCSS failed:", err.message, err.stack);
987
- _cachedGlobalCSS = { rootRule: "", resetRules: "", fontFaceCSS: "", keyframeRules: "" };
988
- return _cachedGlobalCSS;
989
- }
990
- };
991
- let _accumulatedEmotionCSS = /* @__PURE__ */ new Set();
992
- const resetGlobalCSSCache = () => {
993
- _cachedGlobalCSS = null;
994
- _accumulatedEmotionCSS = /* @__PURE__ */ new Set();
995
- };
996
- const getAccumulatedEmotionCSS = () => Array.from(_accumulatedEmotionCSS).join("\n");
997
- const replaceEmotionCSS = (html, newCSS) => {
998
- return html.replace(
999
- /<style data-emotion="smbls">[\s\S]*?<\/style>/,
1000
- newCSS ? `<style data-emotion="smbls">
1001
- ${newCSS}
1002
- </style>` : ""
1003
- );
1004
- };
1005
- const renderRoute = async (data, options = {}) => {
1006
- const { route = "/", pathname } = options;
1007
- const result = await render(data, { route, pathname, prefetch: true });
1008
- if (!result) return null;
1009
- const ds = data.designSystem || {};
1010
- const globalCSS = await generateGlobalCSS(ds, pickProjectConfig(data));
1011
- let prefetchedState = null;
1012
- let activeLang = null;
1013
- try {
1014
- const el = result.element;
1015
- const polyglot = el?.context?.polyglot || data.polyglot || data.config?.polyglot;
1016
- activeLang = el?.state?.root?.lang || polyglot?.defaultLang || "en";
1017
- if (result.prefetchedPages && result.prefetchedPages[route]) {
1018
- const pageDef = result.prefetchedPages[route];
1019
- const collectStates = (def, result2 = {}) => {
1020
- if (!def || typeof def !== "object") return result2;
1021
- if (def.state && typeof def.state === "object") {
1022
- for (const [k, v] of Object.entries(def.state)) {
1023
- if (v !== void 0 && v !== null && typeof v !== "function") {
1024
- result2[k] = v;
1025
- }
1026
- }
1027
- }
1028
- for (const [key, child] of Object.entries(def)) {
1029
- if (key === "state" || key === "props" || key === "attr" || key === "on" || key === "define" || key === "__ref" || key.startsWith("__")) continue;
1030
- if (child && typeof child === "object" && !Array.isArray(child)) {
1031
- collectStates(child, result2);
1032
- }
1033
- }
1034
- return result2;
1035
- };
1036
- prefetchedState = collectStates(pageDef);
1037
- }
1038
- } catch (e) {
1039
- }
1040
- return {
1041
- html: result.html,
1042
- css: result.emotionCSS ? result.emotionCSS.join("\n") : "",
1043
- globalCSS,
1044
- resetCss: globalCSS.resetRules || generateResetCSS(ds.reset),
1045
- fontLinks: generateFontLinks(ds),
1046
- metadata: result.metadata || (0, import_metadata.extractMetadata)(data, route),
1047
- brKeyCount: result.registry ? Object.keys(result.registry).length : 0,
1048
- brRegistry: result.brRegistry || {},
1049
- ssrTranslations: result.ssrTranslations,
1050
- prefetchedState,
1051
- activeLang
1052
- };
1053
- };
1054
- const renderPage = async (data, route = "/", options = {}) => {
1055
- const { lang, themeColor, isr, hydrate: hydrate2 = true, prefetch = true } = options;
1056
- const htmlLang = lang || data.state?.lang || data.app?.metadata?.lang || "en";
1057
- const result = await render(data, { route, prefetch });
1058
- if (!result) return null;
1059
- const metadata = { ...result.metadata };
1060
- if (themeColor) metadata["theme-color"] = themeColor;
1061
- const headTags = (0, import_metadata.generateHeadHtml)(metadata);
1062
- if (result.emotionCSS && result.emotionCSS.length) {
1063
- for (const rule of result.emotionCSS) {
1064
- if (rule) _accumulatedEmotionCSS.add(rule);
1065
- }
1066
- }
1067
- const emotionCSS = Array.from(_accumulatedEmotionCSS).join("\n");
1068
- const ds = data.designSystem || {};
1069
- const globalCSS = await generateGlobalCSS(ds, pickProjectConfig(data));
1070
- const fontLinks = generateFontLinks(ds);
1071
- const brKeyCount = Object.keys(result.registry).length;
1072
- let isrBody = "";
1073
- if (isr && isr.clientScript) {
1074
- const depth = route === "/" ? 0 : route.replace(/^\/|\/$/g, "").split("/").length;
1075
- const prefix = depth > 0 ? "../".repeat(depth) : "./";
1076
- if (hydrate2) {
1077
- let translationSeed = "";
1078
- if (result.ssrTranslations) {
1079
- const polyglotCfg2 = data.polyglot || data.config?.polyglot;
1080
- const storagePrefix = polyglotCfg2?.storagePrefix || "";
1081
- const storageLangKey = polyglotCfg2?.storageLangKey || "";
1082
- const seedEntries = [];
1083
- for (const lang2 in result.ssrTranslations) {
1084
- const map = result.ssrTranslations[lang2];
1085
- if (map && typeof map === "object") {
1086
- seedEntries.push(`localStorage.setItem(${JSON.stringify(storagePrefix + lang2)},${JSON.stringify(JSON.stringify(map))})`);
1087
- }
1088
- }
1089
- if (storageLangKey) {
1090
- const defaultLang = polyglotCfg2?.defaultLang || "en";
1091
- seedEntries.push(`if(!localStorage.getItem(${JSON.stringify(storageLangKey)}))localStorage.setItem(${JSON.stringify(storageLangKey)},${JSON.stringify(defaultLang)})`);
1092
- }
1093
- if (seedEntries.length) {
1094
- translationSeed = `<script>try{${seedEntries.join(";")}}catch(e){}<\/script>
1095
- `;
1096
- }
1097
- }
1098
- const brRegistryJson = result.brRegistry && Object.keys(result.brRegistry).length ? JSON.stringify(result.brRegistry) : null;
1099
- const brRegistryScript = brRegistryJson ? `<script>window.__BR_REGISTRY__=${brRegistryJson}<\/script>
1100
- ` : "";
1101
- isrBody = `${translationSeed}${brRegistryScript}<script>window.__BRENDER__=true<\/script>
1102
- <script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
1103
- } else {
1104
- isrBody = `<script type="module">
1105
- {
1106
- const brEls = document.querySelectorAll('body > :not(script):not(style)')
1107
- const observer = new MutationObserver((mutations) => {
1108
- for (const m of mutations) {
1109
- for (const node of m.addedNodes) {
1110
- if (node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'STYLE' && !node.hasAttribute('data-br')) {
1111
- brEls.forEach(el => { if (el.hasAttribute('data-br') || el.querySelector('[data-br]')) el.remove() })
1112
- observer.disconnect()
1113
- return
1114
- }
1115
- }
1116
- }
1117
- })
1118
- observer.observe(document.body, { childList: true })
1119
- }
1120
- <\/script>
1121
- <script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
1122
- }
1123
- }
1124
- const headConfig = { ...data.config || {} };
1125
- if (data.polyglot && !headConfig.polyglot) headConfig.polyglot = data.polyglot;
1126
- const polyglotCfg = headConfig.polyglot;
1127
- let resolvedHeadTags = headTags;
1128
- if (polyglotCfg) {
1129
- const defaultLang = polyglotCfg.defaultLang || "en";
1130
- const translations = {
1131
- ...polyglotCfg.translations || {},
1132
- ...result.ssrTranslations || {}
1133
- };
1134
- const langMap = translations[defaultLang] || {};
1135
- resolvedHeadTags = headTags.replace(/\{\{\s*([^|{}]+?)\s*\|\s*polyglot\s*\}\}/g, (match, key) => {
1136
- const trimmed = key.trim();
1137
- return langMap[trimmed] ?? match;
1138
- });
1139
- }
1140
- const html = `<!DOCTYPE html>
1141
- <html lang="${htmlLang}">
1142
- <head>
1143
- ${resolvedHeadTags}
1144
- ${fontLinks}
1145
- ${globalCSS.fontFaceCSS ? `<style>${globalCSS.fontFaceCSS}</style>` : ""}
1146
- <style>
1147
- ${globalCSS.rootRule || ""}
1148
- ${globalCSS.resetRules || ""}
1149
- ${globalCSS.keyframeRules || ""}
1150
- </style>
1151
- ${emotionCSS ? `<style data-emotion="smbls">
1152
- ${emotionCSS}
1153
- </style>` : ""}
1154
- </head>
1155
- <body>
1156
- ${result.html}
1157
- ${isrBody}
1158
- </body>
1159
- </html>`;
1160
- return { html, route, brKeyCount };
1161
- };
1162
- const LETTER_TO_INDEX = {
1163
- U: -6,
1164
- V: -5,
1165
- W: -4,
1166
- X: -3,
1167
- Y: -2,
1168
- Z: -1,
1169
- A: 0,
1170
- B: 1,
1171
- C: 2,
1172
- D: 3,
1173
- E: 4,
1174
- F: 5,
1175
- G: 6,
1176
- H: 7,
1177
- I: 8,
1178
- J: 9,
1179
- K: 10,
1180
- L: 11,
1181
- M: 12,
1182
- N: 13,
1183
- O: 14,
1184
- P: 15
1185
- };
1186
- const SPACING_PROPS = /* @__PURE__ */ new Set([
1187
- "padding",
1188
- "paddingTop",
1189
- "paddingRight",
1190
- "paddingBottom",
1191
- "paddingLeft",
1192
- "paddingBlock",
1193
- "paddingInline",
1194
- "paddingBlockStart",
1195
- "paddingBlockEnd",
1196
- "paddingInlineStart",
1197
- "paddingInlineEnd",
1198
- "margin",
1199
- "marginTop",
1200
- "marginRight",
1201
- "marginBottom",
1202
- "marginLeft",
1203
- "marginBlock",
1204
- "marginInline",
1205
- "marginBlockStart",
1206
- "marginBlockEnd",
1207
- "marginInlineStart",
1208
- "marginInlineEnd",
1209
- "gap",
1210
- "rowGap",
1211
- "columnGap",
1212
- "top",
1213
- "right",
1214
- "bottom",
1215
- "left",
1216
- "width",
1217
- "height",
1218
- "minWidth",
1219
- "maxWidth",
1220
- "minHeight",
1221
- "maxHeight",
1222
- "flexBasis",
1223
- "fontSize",
1224
- "lineHeight",
1225
- "letterSpacing",
1226
- "borderWidth",
1227
- "borderRadius",
1228
- "outlineWidth",
1229
- "outlineOffset",
1230
- "inset",
1231
- "insetBlock",
1232
- "insetInline",
1233
- "boxSize",
1234
- "round"
1235
- ]);
1236
- const resolveSpacingToken = (token, spacingConfig) => {
1237
- if (!token || typeof token !== "string") return null;
1238
- if (!spacingConfig) return null;
1239
- const base = spacingConfig.base || 16;
1240
- const ratio = spacingConfig.ratio || 1.618;
1241
- const unit = spacingConfig.unit || "px";
1242
- const hasSubSequence = spacingConfig.subSequence !== false;
1243
- if (token.includes(" ")) {
1244
- const parts = token.split(" ").map((part) => {
1245
- if (part === "-" || part === "") return part;
1246
- return resolveSpacingToken(part, spacingConfig) || part;
1247
- });
1248
- return parts.join(" ");
1249
- }
1250
- if (/^(none|auto|inherit|initial|unset|0)$/i.test(token)) return null;
1251
- if (/\d+(px|em|rem|%|vh|vw|vmin|vmax|ch|ex|cm|mm|in|pt|pc|fr|s|ms)$/i.test(token)) return null;
1252
- if (/^(#|rgb|hsl|var\()/i.test(token)) return null;
1253
- const isNegative = token.startsWith("-");
1254
- const abs = isNegative ? token.slice(1) : token;
1255
- const m = abs.match(/^([A-Z])(\d)?$/i);
1256
- if (!m) return null;
1257
- const letter = m[1].toUpperCase();
1258
- const subStep = m[2] ? parseInt(m[2]) : 0;
1259
- const idx = LETTER_TO_INDEX[letter];
1260
- if (idx === void 0) return null;
1261
- let value = base * Math.pow(ratio, idx);
1262
- if (subStep > 0 && hasSubSequence) {
1263
- const next = base * Math.pow(ratio, idx + 1);
1264
- const diff = next - value;
1265
- const subRatio = diff / ratio;
1266
- const first = next - subRatio;
1267
- const second = value + subRatio;
1268
- const middle = (first + second) / 2;
1269
- const subs = ~~next - ~~value > 16 ? [first, middle, second] : [first, second];
1270
- if (subStep <= subs.length) {
1271
- value = subs[subStep - 1];
1272
- }
1273
- }
1274
- const rounded = Math.round(value * 100) / 100;
1275
- const sign = isNegative ? "-" : "";
1276
- return `${sign}${rounded}${unit}`;
1277
- };
1278
- const SPACING_PROPS_KEBAB = new Set(
1279
- [...SPACING_PROPS].map((k) => k.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()))
1280
- );
1281
- const resolveDSValue = (key, val, ds) => {
1282
- if (typeof val !== "string") return val;
1283
- if (CSS_COLOR_PROPS.has(key)) {
1284
- const colorMap = ds?.color || {};
1285
- if (colorMap[val]) return colorMap[val];
1286
- }
1287
- if (SPACING_PROPS.has(key) || SPACING_PROPS_KEBAB.has(key)) {
1288
- const spacing = ds?.spacing || {};
1289
- const resolved = resolveSpacingToken(val, spacing);
1290
- if (resolved) return resolved;
1291
- }
1292
- return val;
1293
- };
1294
- const CSS_COLOR_PROPS = /* @__PURE__ */ new Set([
1295
- "color",
1296
- "background",
1297
- "backgroundColor",
1298
- "borderColor",
1299
- "borderTopColor",
1300
- "borderRightColor",
1301
- "borderBottomColor",
1302
- "borderLeftColor",
1303
- "outlineColor",
1304
- "fill",
1305
- "stroke"
1306
- ]);
1307
- const NON_CSS_PROPS = /* @__PURE__ */ new Set([
1308
- "href",
1309
- "src",
1310
- "alt",
1311
- "title",
1312
- "id",
1313
- "name",
1314
- "type",
1315
- "value",
1316
- "placeholder",
1317
- "target",
1318
- "rel",
1319
- "loading",
1320
- "srcset",
1321
- "sizes",
1322
- "media",
1323
- "role",
1324
- "tabindex",
1325
- "for",
1326
- "action",
1327
- "method",
1328
- "enctype",
1329
- "autocomplete",
1330
- "autofocus",
1331
- "theme",
1332
- "__element",
1333
- "update",
1334
- "childrenAs",
1335
- "childExtends",
1336
- "childProps",
1337
- "children"
1338
- ]);
1339
- const camelToKebab = (str) => str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
1340
- const resolveShorthand = (key, val) => {
1341
- if (typeof val === "undefined" || val === null) return null;
1342
- if (key === "flow" && typeof val === "string") {
1343
- let [direction, wrap] = (val || "row").split(" ");
1344
- if (val.startsWith("x") || val === "row") direction = "row";
1345
- if (val.startsWith("y") || val === "column") direction = "column";
1346
- return { display: "flex", "flex-flow": (direction || "") + " " + (wrap || "") };
1347
- }
1348
- if (key === "wrap") {
1349
- return { display: "flex", "flex-wrap": val };
1350
- }
1351
- if ((key === "align" || key === "flexAlign") && typeof val === "string") {
1352
- const [alignItems, justifyContent] = val.split(" ");
1353
- const result = { display: "flex", "align-items": alignItems };
1354
- if (justifyContent) result["justify-content"] = justifyContent;
1355
- return result;
1356
- }
1357
- if (key === "gridAlign" && typeof val === "string") {
1358
- const [alignItems, justifyContent] = val.split(" ");
1359
- const result = { display: "grid", "align-items": alignItems };
1360
- if (justifyContent) result["justify-content"] = justifyContent;
1361
- return result;
1362
- }
1363
- if (key === "flexFlow" && typeof val === "string") {
1364
- let [direction, wrap] = (val || "row").split(" ");
1365
- if (val.startsWith("x") || val === "row") direction = "row";
1366
- if (val.startsWith("y") || val === "column") direction = "column";
1367
- return { display: "flex", "flex-flow": (direction || "") + " " + (wrap || "") };
1368
- }
1369
- if (key === "flexWrap") {
1370
- return { display: "flex", "flex-wrap": val };
1371
- }
1372
- if (key === "backgroundImage" && typeof val === "string" && !val.startsWith("url(") && !val.startsWith("linear-gradient") && !val.startsWith("radial-gradient") && !val.startsWith("none")) {
1373
- return { "background-image": `url(${val})` };
1374
- }
1375
- if (key === "round" || key === "borderRadius" && val) {
1376
- return { "border-radius": typeof val === "number" ? val + "px" : val };
1377
- }
1378
- if (key === "boxSize" && typeof val === "string") {
1379
- const [height, width] = val.split(" ");
1380
- return { height, width: width || height };
1381
- }
1382
- if (key === "widthRange" && typeof val === "string") {
1383
- const [minWidth, maxWidth] = val.split(" ");
1384
- return { "min-width": minWidth, "max-width": maxWidth || minWidth };
1385
- }
1386
- if (key === "heightRange" && typeof val === "string") {
1387
- const [minHeight, maxHeight] = val.split(" ");
1388
- return { "min-height": minHeight, "max-height": maxHeight || minHeight };
1389
- }
1390
- if (key === "column") return { "grid-column": val };
1391
- if (key === "columns") return { "grid-template-columns": val };
1392
- if (key === "templateColumns") return { "grid-template-columns": val };
1393
- if (key === "row") return { "grid-row": val };
1394
- if (key === "rows") return { "grid-template-rows": val };
1395
- if (key === "templateRows") return { "grid-template-rows": val };
1396
- if (key === "area") return { "grid-area": val };
1397
- if (key === "template") return { "grid-template": val };
1398
- if (key === "templateAreas") return { "grid-template-areas": val };
1399
- if (key === "autoColumns") return { "grid-auto-columns": val };
1400
- if (key === "autoRows") return { "grid-auto-rows": val };
1401
- if (key === "autoFlow") return { "grid-auto-flow": val };
1402
- if (key === "columnStart") return { "grid-column-start": val };
1403
- if (key === "rowStart") return { "grid-row-start": val };
1404
- return null;
1405
- };
1406
- const resolveInnerProps = (obj, ds) => {
1407
- const result = {};
1408
- for (const k in obj) {
1409
- const v = obj[k];
1410
- const expanded = resolveShorthand(k, v);
1411
- if (expanded) {
1412
- for (const ek in expanded) {
1413
- result[ek] = resolveDSValue(ek, expanded[ek], ds);
1414
- }
1415
- continue;
1416
- }
1417
- if (typeof v !== "string" && typeof v !== "number") continue;
1418
- result[camelToKebab(k)] = resolveDSValue(k, v, ds);
1419
- }
1420
- return result;
1421
- };
1422
- const buildCSSFromProps = (props, ds, mediaMap) => {
1423
- const base = {};
1424
- const mediaRules = {};
1425
- const pseudoRules = {};
1426
- for (const key in props) {
1427
- const val = props[key];
1428
- if (key.charCodeAt(0) === 64 && typeof val === "object") {
1429
- const bp = mediaMap?.[key.slice(1)];
1430
- if (bp) {
1431
- const inner = resolveInnerProps(val, ds);
1432
- if (Object.keys(inner).length) mediaRules[bp] = inner;
1433
- }
1434
- continue;
1435
- }
1436
- if (key.charCodeAt(0) === 58 && typeof val === "object") {
1437
- const inner = resolveInnerProps(val, ds);
1438
- if (Object.keys(inner).length) pseudoRules[key] = inner;
1439
- continue;
1440
- }
1441
- if (typeof val !== "string" && typeof val !== "number") continue;
1442
- if (key.charCodeAt(0) >= 65 && key.charCodeAt(0) <= 90) continue;
1443
- if (NON_CSS_PROPS.has(key)) continue;
1444
- const expanded = resolveShorthand(key, val);
1445
- if (expanded) {
1446
- for (const ek in expanded) {
1447
- base[ek] = resolveDSValue(ek, expanded[ek], ds);
1448
- }
1449
- continue;
1450
- }
1451
- base[camelToKebab(key)] = resolveDSValue(key, val, ds);
1452
- }
1453
- return { base, mediaRules, pseudoRules };
1454
- };
1455
- const renderCSSRule = (selector, { base, mediaRules, pseudoRules }) => {
1456
- const lines = [];
1457
- const baseDecls = Object.entries(base).map(([k, v]) => `${k}: ${v}`).join("; ");
1458
- if (baseDecls) lines.push(`${selector} { ${baseDecls}; }`);
1459
- for (const [pseudo, p] of Object.entries(pseudoRules)) {
1460
- const decls = Object.entries(p).map(([k, v]) => `${k}: ${v}`).join("; ");
1461
- if (decls) lines.push(`${selector}${pseudo} { ${decls}; }`);
1462
- }
1463
- for (const [query, p] of Object.entries(mediaRules)) {
1464
- const decls = Object.entries(p).map(([k, v]) => `${k}: ${v}`).join("; ");
1465
- const mq = query.startsWith("@") ? query : `@media ${query}`;
1466
- if (decls) lines.push(`${mq} { ${selector} { ${decls}; } }`);
1467
- }
1468
- return lines.join("\n");
1469
- };
1470
- const EXTENDS_CSS = {
1471
- Flex: { display: "flex" },
1472
- InlineFlex: { display: "inline-flex" },
1473
- Grid: { display: "grid" },
1474
- InlineGrid: { display: "inline-grid" },
1475
- Block: { display: "block" },
1476
- Inline: { display: "inline" }
1477
- };
1478
- const getExtendsCSS = (el) => {
1479
- const exts = el.__ref?.__extends;
1480
- if (!exts || !Array.isArray(exts)) return null;
1481
- for (const ext of exts) {
1482
- if (EXTENDS_CSS[ext]) return EXTENDS_CSS[ext];
1483
- }
1484
- return null;
1485
- };
1486
- const resolveElementProps = (el) => {
1487
- let resolved;
1488
- for (const key in el) {
1489
- if (typeof el[key] !== "function") continue;
1490
- if (NON_CSS_PROPS.has(key)) continue;
1491
- if (key.charCodeAt(0) >= 65 && key.charCodeAt(0) <= 90) continue;
1492
- if (key.startsWith("on")) continue;
1493
- if (key.startsWith("__")) continue;
1494
- if (!resolved) resolved = {};
1495
- let result;
1496
- try {
1497
- result = el[key](el, el.state || {});
1498
- } catch {
1499
- try {
1500
- const mockState = { root: {}, ...el.state || {} };
1501
- result = el[key](el, mockState);
1502
- } catch {
1503
- }
1504
- }
1505
- if (result !== void 0 && result !== null && result !== false) {
1506
- resolved[key] = result;
1507
- }
1508
- }
1509
- return resolved || el;
1510
- };
1511
- const extractCSS = (element, ds) => {
1512
- const mediaMap = ds?.media || {};
1513
- const animations = ds?.animation || {};
1514
- const rules = [];
1515
- const seen = /* @__PURE__ */ new Set();
1516
- const usedAnimations = /* @__PURE__ */ new Set();
1517
- const walk = (el) => {
1518
- if (!el || !el.__ref) return;
1519
- const props = resolveElementProps(el);
1520
- if (props && el.node) {
1521
- const cls = el.node.getAttribute?.("class");
1522
- if (cls && !seen.has(cls)) {
1523
- seen.add(cls);
1524
- const cssResult = buildCSSFromProps(props, ds, mediaMap);
1525
- const extsCss = getExtendsCSS(el);
1526
- if (extsCss) {
1527
- for (const [k, v] of Object.entries(extsCss)) {
1528
- const kebab = camelToKebab(k);
1529
- if (!cssResult.base[kebab]) cssResult.base[kebab] = v;
1530
- }
1531
- }
1532
- const has = Object.keys(cssResult.base).length || Object.keys(cssResult.mediaRules).length || Object.keys(cssResult.pseudoRules).length;
1533
- if (has) rules.push(renderCSSRule("." + cls.split(" ")[0], cssResult));
1534
- const anim = props.animation || props.animationName;
1535
- if (typeof anim === "string") {
1536
- const name = anim.split(" ")[0];
1537
- if (animations[name]) usedAnimations.add(name);
1538
- }
1539
- }
1540
- }
1541
- if (el.__ref?.__children) {
1542
- for (const ck of el.__ref.__children) {
1543
- if (el[ck]?.__ref) walk(el[ck]);
1544
- }
1545
- }
1546
- };
1547
- walk(element);
1548
- const keyframes = [];
1549
- for (const name of usedAnimations) {
1550
- const frames = animations[name];
1551
- const frameRules = Object.entries(frames).map(([step, p]) => {
1552
- const decls = Object.entries(p).map(([k, v]) => `${camelToKebab(k)}: ${v}`).join("; ");
1553
- return ` ${step} { ${decls}; }`;
1554
- }).join("\n");
1555
- keyframes.push(`@keyframes ${name} {
1556
- ${frameRules}
1557
- }`);
1558
- }
1559
- return [...keyframes, ...rules].join("\n");
1560
- };
1561
- const generateResetCSS = (reset) => {
1562
- if (!reset) return "";
1563
- const rules = [];
1564
- for (const [selector, props] of Object.entries(reset)) {
1565
- if (!props || typeof props !== "object") continue;
1566
- const baseDecls = [];
1567
- const mediaRules = [];
1568
- for (const [k, v] of Object.entries(props)) {
1569
- if (typeof v === "object" && v !== null) {
1570
- if (k.startsWith("@media") || k.startsWith("@")) {
1571
- const inner = Object.entries(v).filter(([, iv]) => typeof iv !== "object").map(([ik, iv]) => `${camelToKebab(ik)}: ${iv}`).join("; ");
1572
- if (inner) mediaRules.push(`${k} { ${selector} { ${inner}; } }`);
1573
- }
1574
- continue;
1575
- }
1576
- baseDecls.push(`${camelToKebab(k)}: ${v}`);
1577
- }
1578
- if (baseDecls.length) rules.push(`${selector} { ${baseDecls.join("; ")}; }`);
1579
- rules.push(...mediaRules);
1580
- }
1581
- return rules.join("\n");
1582
- };
1583
- const generateFontLinks = (ds) => {
1584
- if (!ds) return "";
1585
- const families = ds.font_family || ds.fontFamily || {};
1586
- const fontNames = /* @__PURE__ */ new Set();
1587
- for (const val of Object.values(families)) {
1588
- if (typeof val !== "string") continue;
1589
- const match = val.match(/'([^']+)'/);
1590
- if (match) fontNames.add(match[1]);
1591
- }
1592
- if (!fontNames.size) return "";
1593
- const params = [...fontNames].map((name) => {
1594
- const slug = name.replace(/\s+/g, "+");
1595
- return `family=${slug}:wght@300;400;500;600;700`;
1596
- }).join("&");
1597
- return [
1598
- '<link rel="preconnect" href="https://fonts.googleapis.com">',
1599
- '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',
1600
- `<link href="https://fonts.googleapis.com/css2?${params}&display=swap" rel="stylesheet">`
1601
- ].join("\n");
1602
- };