@symbo.ls/brender 3.8.8 → 3.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cjs/env.js +6 -1
- package/dist/cjs/hydrate.js +28 -39
- package/dist/cjs/load.js +19 -4
- package/dist/cjs/prefetch.js +0 -2
- package/dist/cjs/render.js +65 -63
- package/dist/esm/env.js +6 -1
- package/dist/esm/hydrate.js +28 -39
- package/dist/esm/load.js +19 -4
- package/dist/esm/prefetch.js +0 -2
- package/dist/esm/render.js +65 -63
- package/env.js +7 -2
- package/hydrate.js +32 -42
- package/load.js +23 -4
- package/package.json +13 -18
- package/prefetch.js +1 -3
- package/render.js +70 -77
package/README.md
CHANGED
|
@@ -113,14 +113,14 @@ const result = await render(data, { route: '/about' })
|
|
|
113
113
|
|
|
114
114
|
// result.html -> full page HTML with data-br keys
|
|
115
115
|
// result.metadata -> { title, description, og:image, ... }
|
|
116
|
-
// result.
|
|
116
|
+
// result.css -> array of CSS rule strings from the atomic CSS engine
|
|
117
117
|
// result.registry -> { br-key: domqlElement }
|
|
118
118
|
// result.element -> root DOMQL element
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
### `renderPage(data, route, options?)`
|
|
122
122
|
|
|
123
|
-
Renders a complete, ready-to-serve HTML page. Combines `render()` output with metadata, CSS (
|
|
123
|
+
Renders a complete, ready-to-serve HTML page. Combines `render()` output with metadata, CSS (atomic + global), fonts, and optional ISR client bundle.
|
|
124
124
|
|
|
125
125
|
```js
|
|
126
126
|
import { renderPage, loadProject } from '@symbo.ls/brender'
|
|
@@ -345,11 +345,11 @@ This means the server and client don't need to exchange the registry — as long
|
|
|
345
345
|
|
|
346
346
|
- `renderElement()` uses `@domql/element` create directly — lightweight, no smbls bootstrap. Good for individual components
|
|
347
347
|
- `render()` uses the full `smbls/src/createDomql.js` pipeline — handles routing, designSystem initialization, uikit defaults, the works. Needed for complete apps
|
|
348
|
-
- The smbls source is bundled with esbuild (cached after first call) because the monorepo uses extensionless/directory imports that Node.js ESM can't resolve natively. The esbuild plugin patches SSR-incompatible code (window references, createRequire, circular imports) and stubs out browser-only packages
|
|
348
|
+
- The smbls source is bundled with esbuild (cached after first call) because the monorepo uses extensionless/directory imports that Node.js ESM can't resolve natively. The esbuild plugin patches SSR-incompatible code (window references, createRequire, circular imports) and stubs out browser-only packages
|
|
349
349
|
- `render()` sets `globalThis.document` and `globalThis.location` before each render to match the linkedom virtual env, then restores them after. This allows the bundled smbls code (which reads `window = globalThis`) to work in SSR
|
|
350
350
|
- `hydrate.js` is browser-only code (no linkedom dependency) — it's exported separately via `@symbo.ls/brender/hydrate`
|
|
351
351
|
- `createEnv()` sets `globalThis.window/document/Node/HTMLElement` because `@domql/utils` `isDOMNode` uses `instanceof` checks against global constructors
|
|
352
|
-
-
|
|
352
|
+
- CSS is extracted from the atomic CSS engine's generated rules
|
|
353
353
|
- `onRender` callbacks that do network requests or call `s.update()` will error during SSR — this is expected and harmless since the HTML is already produced before those callbacks fire
|
|
354
354
|
- Data prefetching (`prefetch.js`) walks page definitions to find `fetch` declarations, then executes them against the DB adapter before rendering. Fetched data is injected into page state so components render with real content
|
|
355
355
|
|
package/dist/cjs/env.js
CHANGED
|
@@ -24,7 +24,11 @@ var import_linkedom = require("linkedom");
|
|
|
24
24
|
const createEnv = (html = "<!DOCTYPE html><html><head></head><body></body></html>") => {
|
|
25
25
|
const { window, document } = (0, import_linkedom.parseHTML)(html);
|
|
26
26
|
if (!window.requestAnimationFrame) {
|
|
27
|
-
window.requestAnimationFrame = (fn) =>
|
|
27
|
+
window.requestAnimationFrame = (fn) => {
|
|
28
|
+
const id = setTimeout(fn, 0);
|
|
29
|
+
if (id?.unref) id.unref();
|
|
30
|
+
return id;
|
|
31
|
+
};
|
|
28
32
|
}
|
|
29
33
|
if (!window.cancelAnimationFrame) {
|
|
30
34
|
window.cancelAnimationFrame = (id) => clearTimeout(id);
|
|
@@ -87,6 +91,7 @@ const createEnv = (html = "<!DOCTYPE html><html><head></head><body></body></html
|
|
|
87
91
|
globalThis.window = window;
|
|
88
92
|
globalThis.document = document;
|
|
89
93
|
globalThis.Node = window.Node || globalThis.Node;
|
|
94
|
+
globalThis.Element = window.Element || globalThis.Element;
|
|
90
95
|
globalThis.HTMLElement = window.HTMLElement || globalThis.HTMLElement;
|
|
91
96
|
globalThis.MutationObserver = window.MutationObserver;
|
|
92
97
|
globalThis.Window = window.constructor;
|
package/dist/cjs/hydrate.js
CHANGED
|
@@ -76,12 +76,12 @@ const hydrate = (element, options = {}) => {
|
|
|
76
76
|
return { element, linked, unlinked };
|
|
77
77
|
};
|
|
78
78
|
const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
79
|
-
const { node
|
|
80
|
-
if (!node
|
|
79
|
+
const { node } = el;
|
|
80
|
+
if (!node) return;
|
|
81
81
|
const css = {};
|
|
82
82
|
let hasCss = false;
|
|
83
|
-
for (const key in
|
|
84
|
-
const val =
|
|
83
|
+
for (const key in el) {
|
|
84
|
+
const val = el[key];
|
|
85
85
|
if (key.charCodeAt(0) === 64) {
|
|
86
86
|
const breakpoint = mediaMap[key.slice(1)];
|
|
87
87
|
if (breakpoint && typeof val === "object") {
|
|
@@ -135,7 +135,7 @@ const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
|
135
135
|
if (typeof el.key === "string" && el.key.charCodeAt(0) === 95 && el.key.charCodeAt(1) !== 95) {
|
|
136
136
|
classes.push(el.key.slice(1));
|
|
137
137
|
}
|
|
138
|
-
if (
|
|
138
|
+
if (el.class) classes.push(el.class);
|
|
139
139
|
if (el.attr?.class) classes.push(el.attr.class);
|
|
140
140
|
const classlist = el.classlist;
|
|
141
141
|
if (classlist) {
|
|
@@ -152,7 +152,7 @@ const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
|
152
152
|
if (classes.length) {
|
|
153
153
|
node.setAttribute("class", classes.join(" "));
|
|
154
154
|
}
|
|
155
|
-
for (const key in
|
|
155
|
+
for (const key in el) {
|
|
156
156
|
if (isCSS(key) && node.hasAttribute(key)) {
|
|
157
157
|
node.removeAttribute(key);
|
|
158
158
|
}
|
|
@@ -503,47 +503,36 @@ const DOMQL_LIFECYCLE = /* @__PURE__ */ new Set([
|
|
|
503
503
|
"error"
|
|
504
504
|
]);
|
|
505
505
|
const bindEvents = (el) => {
|
|
506
|
-
const { node
|
|
506
|
+
const { node } = el;
|
|
507
507
|
if (!node) return;
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (props) {
|
|
518
|
-
for (const key in props) {
|
|
519
|
-
if (key.length <= 2 || key[0] !== "o" || key[1] !== "n") continue;
|
|
520
|
-
if (typeof props[key] !== "function") continue;
|
|
521
|
-
const third = key[2];
|
|
522
|
-
if (third !== third.toUpperCase()) continue;
|
|
523
|
-
const eventName = third.toLowerCase() + key.slice(3);
|
|
524
|
-
if (handled.has(eventName) || DOMQL_LIFECYCLE.has(eventName)) continue;
|
|
525
|
-
addListener(node, eventName, props[key], el);
|
|
526
|
-
}
|
|
508
|
+
if (!el.__ref.__eventCleanup) el.__ref.__eventCleanup = [];
|
|
509
|
+
for (const key in el) {
|
|
510
|
+
if (key.length <= 2 || key[0] !== "o" || key[1] !== "n") continue;
|
|
511
|
+
if (typeof el[key] !== "function") continue;
|
|
512
|
+
const third = key[2];
|
|
513
|
+
if (third !== third.toUpperCase()) continue;
|
|
514
|
+
const eventName = third.toLowerCase() + key.slice(3);
|
|
515
|
+
if (DOMQL_LIFECYCLE.has(eventName)) continue;
|
|
516
|
+
addListener(node, eventName, el[key], el);
|
|
527
517
|
}
|
|
528
518
|
};
|
|
529
519
|
const addListener = (node, eventName, handler, el) => {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
520
|
+
const listener = (event) => {
|
|
521
|
+
try {
|
|
522
|
+
handler.call(el, event, el, el.state, el.context);
|
|
523
|
+
} catch (e) {
|
|
524
|
+
console.warn("[brender hydrate]", eventName, e.message);
|
|
535
525
|
}
|
|
536
|
-
}
|
|
526
|
+
};
|
|
527
|
+
node.addEventListener(eventName, listener);
|
|
528
|
+
el.__ref.__eventCleanup.push(() => node.removeEventListener(eventName, listener));
|
|
537
529
|
};
|
|
538
530
|
const fireLifecycle = (el) => {
|
|
539
531
|
if (!el || !el.__ref || !el.node) return;
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
fireEvent(on.done, el);
|
|
545
|
-
fireEvent(on.create, el);
|
|
546
|
-
}
|
|
532
|
+
fireEvent(el.onRender, el);
|
|
533
|
+
fireEvent(el.onRenderRouter, el);
|
|
534
|
+
fireEvent(el.onDone, el);
|
|
535
|
+
fireEvent(el.onCreate, el);
|
|
547
536
|
if (el.__ref.__children) {
|
|
548
537
|
for (const childKey of el.__ref.__children) {
|
|
549
538
|
const child = el[childKey];
|
package/dist/cjs/load.js
CHANGED
|
@@ -88,7 +88,9 @@ const loadProject = async (projectPath) => {
|
|
|
88
88
|
functionsModule,
|
|
89
89
|
methodsModule,
|
|
90
90
|
designSystemModule,
|
|
91
|
-
filesModule
|
|
91
|
+
filesModule,
|
|
92
|
+
assetsModule,
|
|
93
|
+
sharedLibsModule
|
|
92
94
|
] = await Promise.all([
|
|
93
95
|
bundleAndImport((0, import_path.join)(symbolsDir, "app.js")),
|
|
94
96
|
bundleAndImport((0, import_path.join)(symbolsDir, "state.js")),
|
|
@@ -100,9 +102,11 @@ const loadProject = async (projectPath) => {
|
|
|
100
102
|
bundleAndImport((0, import_path.join)(symbolsDir, "functions", "index.js")),
|
|
101
103
|
bundleAndImport((0, import_path.join)(symbolsDir, "methods", "index.js")),
|
|
102
104
|
bundleAndImport((0, import_path.join)(symbolsDir, "designSystem", "index.js")),
|
|
103
|
-
bundleAndImport((0, import_path.join)(symbolsDir, "files", "index.js"))
|
|
105
|
+
bundleAndImport((0, import_path.join)(symbolsDir, "files", "index.js")),
|
|
106
|
+
bundleAndImport((0, import_path.join)(symbolsDir, "assets", "index.js")).catch(() => null),
|
|
107
|
+
bundleAndImport((0, import_path.join)(symbolsDir, "sharedLibraries.js")).catch(() => null)
|
|
104
108
|
]);
|
|
105
|
-
|
|
109
|
+
const result = {
|
|
106
110
|
app: { ...appModule?.default || {} },
|
|
107
111
|
state: { ...stateModule?.default || {} },
|
|
108
112
|
dependencies: { ...depsModule?.default || {} },
|
|
@@ -113,8 +117,19 @@ const loadProject = async (projectPath) => {
|
|
|
113
117
|
methods: { ...methodsModule || {} },
|
|
114
118
|
designSystem: { ...designSystemModule?.default || {} },
|
|
115
119
|
files: { ...filesModule?.default || {} },
|
|
116
|
-
|
|
120
|
+
assets: { ...assetsModule?.default || {} },
|
|
121
|
+
config: { ...configModule?.default || {} },
|
|
122
|
+
sharedLibraries: sharedLibsModule?.default || []
|
|
117
123
|
};
|
|
124
|
+
if (result.sharedLibraries.length) {
|
|
125
|
+
const { resolveSharedLibraries, mergeSharedLibraries } = await import("@symbo.ls/utils");
|
|
126
|
+
const hasStrings = result.sharedLibraries.some((lib) => typeof lib === "string");
|
|
127
|
+
if (hasStrings) {
|
|
128
|
+
result.sharedLibraries = await resolveSharedLibraries(result.sharedLibraries);
|
|
129
|
+
}
|
|
130
|
+
mergeSharedLibraries(result, result.sharedLibraries);
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
118
133
|
};
|
|
119
134
|
const loadAndRenderAll = async (projectPath, renderFn) => {
|
|
120
135
|
const data = await loadProject(projectPath);
|
package/dist/cjs/prefetch.js
CHANGED
|
@@ -41,7 +41,6 @@ const resolveParams = (params, mockState) => {
|
|
|
41
41
|
try {
|
|
42
42
|
const mockEl = {
|
|
43
43
|
state: mockState || {},
|
|
44
|
-
props: {},
|
|
45
44
|
call: () => void 0,
|
|
46
45
|
__ref: {}
|
|
47
46
|
};
|
|
@@ -225,7 +224,6 @@ const preEvaluateChildren = (def, inheritedState) => {
|
|
|
225
224
|
try {
|
|
226
225
|
const mockEl = {
|
|
227
226
|
state: effectiveState,
|
|
228
|
-
props: {},
|
|
229
227
|
call: (fn) => {
|
|
230
228
|
if (fn === "getActiveLang" || fn === "getLang") return effectiveState?.lang || "ka";
|
|
231
229
|
if (fn === "polyglot") return arguments[1] || "";
|
package/dist/cjs/render.js
CHANGED
|
@@ -47,13 +47,13 @@ var import_metadata = require("./metadata.js");
|
|
|
47
47
|
var import_hydrate = require("./hydrate.js");
|
|
48
48
|
var import_prefetch = require("./prefetch.js");
|
|
49
49
|
var import_linkedom = require("linkedom");
|
|
50
|
-
var
|
|
50
|
+
var import_css = require("@symbo.ls/css");
|
|
51
51
|
const import_meta = {};
|
|
52
52
|
let _funcqlPlugin = null;
|
|
53
53
|
const getFuncqlPlugin = async () => {
|
|
54
54
|
if (_funcqlPlugin) return _funcqlPlugin;
|
|
55
55
|
try {
|
|
56
|
-
const mod = await import("@
|
|
56
|
+
const mod = await import("@symbo.ls/funcql");
|
|
57
57
|
_funcqlPlugin = mod.funcqlPlugin;
|
|
58
58
|
return _funcqlPlugin;
|
|
59
59
|
} catch {
|
|
@@ -232,7 +232,7 @@ const resolveDomqlPackage = (ws, pkg, ...subpath) => {
|
|
|
232
232
|
if (ws.isMonorepo) {
|
|
233
233
|
return (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, ...subpath);
|
|
234
234
|
}
|
|
235
|
-
const pkgJson = tryRequireResolve(ws, `@
|
|
235
|
+
const pkgJson = tryRequireResolve(ws, `@symbo.ls/${pkg}/package.json`);
|
|
236
236
|
if (pkgJson) return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
|
|
237
237
|
return null;
|
|
238
238
|
};
|
|
@@ -327,7 +327,7 @@ const bundleCreateDomql = async () => {
|
|
|
327
327
|
}
|
|
328
328
|
});
|
|
329
329
|
build.onResolve({ filter: /^@domql\// }, (args) => {
|
|
330
|
-
const pkg = args.path.replace("@
|
|
330
|
+
const pkg = args.path.replace("@symbo.ls/", "");
|
|
331
331
|
if (ws.isMonorepo) {
|
|
332
332
|
const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
|
|
333
333
|
if ((0, import_fs.existsSync)(src)) return { path: src };
|
|
@@ -425,7 +425,7 @@ export const supabaseAdapter = () => ({name:'supabase'});
|
|
|
425
425
|
let contents = (0, import_fs.readFileSync)(args.path, "utf8");
|
|
426
426
|
contents = contents.replace(
|
|
427
427
|
/import\s*\{\s*Link\s*\}\s*from\s*['"]smbls['"]/,
|
|
428
|
-
`const Link = { tag: 'a', attr: { href: (el) => el.
|
|
428
|
+
`const Link = { tag: 'a', attr: { href: (el) => el.href } }`
|
|
429
429
|
);
|
|
430
430
|
return { contents, loader: "js" };
|
|
431
431
|
});
|
|
@@ -515,9 +515,9 @@ const UIKIT_STUBS = {
|
|
|
515
515
|
Link: {
|
|
516
516
|
tag: "a",
|
|
517
517
|
attr: {
|
|
518
|
-
href: (el) => el.
|
|
519
|
-
target: (el) => el.
|
|
520
|
-
rel: (el) => el.
|
|
518
|
+
href: (el) => el.href,
|
|
519
|
+
target: (el) => el.target,
|
|
520
|
+
rel: (el) => el.rel
|
|
521
521
|
}
|
|
522
522
|
},
|
|
523
523
|
A: { extends: "Link" },
|
|
@@ -526,14 +526,14 @@ const UIKIT_STUBS = {
|
|
|
526
526
|
tag: "img",
|
|
527
527
|
attr: {
|
|
528
528
|
src: (el) => {
|
|
529
|
-
let src = el.
|
|
529
|
+
let src = el.src;
|
|
530
530
|
if (typeof src === "string" && src.includes("{{")) {
|
|
531
531
|
src = el.call("replaceLiteralsWithObjectFields", src, el.state);
|
|
532
532
|
}
|
|
533
533
|
return src;
|
|
534
534
|
},
|
|
535
|
-
alt: (el) => el.
|
|
536
|
-
loading: (el) => el.
|
|
535
|
+
alt: (el) => el.alt,
|
|
536
|
+
loading: (el) => el.loading
|
|
537
537
|
}
|
|
538
538
|
},
|
|
539
539
|
Image: { extends: "Img" },
|
|
@@ -671,11 +671,7 @@ const render = async (data, options = {}) => {
|
|
|
671
671
|
};
|
|
672
672
|
}
|
|
673
673
|
}
|
|
674
|
-
|
|
675
|
-
key: "smbls",
|
|
676
|
-
container: document.head,
|
|
677
|
-
speedy: false
|
|
678
|
-
});
|
|
674
|
+
(0, import_css.reset)();
|
|
679
675
|
const ctx = {
|
|
680
676
|
state: baseState,
|
|
681
677
|
...stateOverrides ? { state: { ...baseState, ...stateOverrides } } : {},
|
|
@@ -693,6 +689,7 @@ const render = async (data, options = {}) => {
|
|
|
693
689
|
methods: data.methods || {},
|
|
694
690
|
designSystem: structuredCloneDeep(data.designSystem || {}),
|
|
695
691
|
files: data.files || {},
|
|
692
|
+
sharedLibraries: data.sharedLibraries || [],
|
|
696
693
|
...config,
|
|
697
694
|
// Override polyglot with SSR-enriched version
|
|
698
695
|
...polyglotConfig ? { polyglot: polyglotConfig } : {},
|
|
@@ -700,8 +697,7 @@ const render = async (data, options = {}) => {
|
|
|
700
697
|
document,
|
|
701
698
|
window,
|
|
702
699
|
parent: { node: body },
|
|
703
|
-
|
|
704
|
-
initOptions: { emotion: ssrEmotion },
|
|
700
|
+
initOptions: {},
|
|
705
701
|
// Disable sourcemap tracking in SSR — it causes stack overflows
|
|
706
702
|
// when state contains large data arrays (articles, events, etc.)
|
|
707
703
|
domqlOptions: { sourcemap: false },
|
|
@@ -724,38 +720,17 @@ const render = async (data, options = {}) => {
|
|
|
724
720
|
const brRegistry = buildPathRegistry(element);
|
|
725
721
|
const metadata = (0, import_metadata.extractMetadata)(data, route, element, element?.state);
|
|
726
722
|
const emotionCSS = [];
|
|
727
|
-
const
|
|
728
|
-
if (
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (typeof rule === "string" && rule) emotionCSS.push(rule);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
if (cache.sheet && cache.sheet.tags) {
|
|
737
|
-
for (const tag of cache.sheet.tags) {
|
|
738
|
-
if (tag.sheet && tag.sheet.cssRules) {
|
|
739
|
-
for (const rule of tag.sheet.cssRules) {
|
|
740
|
-
if (rule.cssText) emotionCSS.push(rule.cssText);
|
|
741
|
-
}
|
|
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);
|
|
742
729
|
}
|
|
743
730
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
const head = document.head || document.querySelector("head");
|
|
748
|
-
if (head) {
|
|
749
|
-
for (const style of head.querySelectorAll("style")) {
|
|
750
|
-
if (style.sheet && style.sheet.cssRules) {
|
|
751
|
-
for (const rule of style.sheet.cssRules) {
|
|
752
|
-
if (rule.cssText) emotionCSS.push(rule.cssText);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
if (!emotionCSS.length) {
|
|
756
|
-
const content = style.textContent || "";
|
|
757
|
-
if (content) emotionCSS.push(content);
|
|
758
|
-
}
|
|
731
|
+
if (!emotionCSS.length) {
|
|
732
|
+
const content = style.textContent || "";
|
|
733
|
+
if (content) emotionCSS.push(content);
|
|
759
734
|
}
|
|
760
735
|
}
|
|
761
736
|
}
|
|
@@ -778,8 +753,8 @@ const renderElement = async (elementDef, options = {}) => {
|
|
|
778
753
|
const { context = {} } = options;
|
|
779
754
|
const { window, document } = (0, import_env.createEnv)();
|
|
780
755
|
const body = document.body;
|
|
781
|
-
const { create } = await import("@
|
|
782
|
-
const domqlUtils = await import("@
|
|
756
|
+
const { create } = await import("@symbo.ls/element");
|
|
757
|
+
const domqlUtils = await import("@symbo.ls/utils");
|
|
783
758
|
const components = { ...UIKIT_STUBS, ...context.components || {} };
|
|
784
759
|
const utils = {
|
|
785
760
|
...domqlUtils,
|
|
@@ -812,6 +787,36 @@ const fixSvgContent = (html) => {
|
|
|
812
787
|
);
|
|
813
788
|
};
|
|
814
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
|
+
};
|
|
815
820
|
const generateGlobalCSS = async (ds, config) => {
|
|
816
821
|
if (_cachedGlobalCSS) return _cachedGlobalCSS;
|
|
817
822
|
try {
|
|
@@ -894,7 +899,7 @@ const generateGlobalCSS = async (ds, config) => {
|
|
|
894
899
|
}
|
|
895
900
|
});
|
|
896
901
|
build.onResolve({ filter: /^@domql\// }, (args) => {
|
|
897
|
-
const pkg = args.path.replace("@
|
|
902
|
+
const pkg = args.path.replace("@symbo.ls/", "");
|
|
898
903
|
if (ws.isMonorepo) {
|
|
899
904
|
const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
|
|
900
905
|
if (existsSync2(src)) return { path: src };
|
|
@@ -1002,7 +1007,7 @@ const renderRoute = async (data, options = {}) => {
|
|
|
1002
1007
|
const result = await render(data, { route, pathname, prefetch: true });
|
|
1003
1008
|
if (!result) return null;
|
|
1004
1009
|
const ds = data.designSystem || {};
|
|
1005
|
-
const globalCSS = await generateGlobalCSS(ds, data
|
|
1010
|
+
const globalCSS = await generateGlobalCSS(ds, pickProjectConfig(data));
|
|
1006
1011
|
let prefetchedState = null;
|
|
1007
1012
|
let activeLang = null;
|
|
1008
1013
|
try {
|
|
@@ -1061,7 +1066,7 @@ const renderPage = async (data, route = "/", options = {}) => {
|
|
|
1061
1066
|
}
|
|
1062
1067
|
const emotionCSS = Array.from(_accumulatedEmotionCSS).join("\n");
|
|
1063
1068
|
const ds = data.designSystem || {};
|
|
1064
|
-
const globalCSS = await generateGlobalCSS(ds, data
|
|
1069
|
+
const globalCSS = await generateGlobalCSS(ds, pickProjectConfig(data));
|
|
1065
1070
|
const fontLinks = generateFontLinks(ds);
|
|
1066
1071
|
const brKeyCount = Object.keys(result.registry).length;
|
|
1067
1072
|
let isrBody = "";
|
|
@@ -1479,32 +1484,29 @@ const getExtendsCSS = (el) => {
|
|
|
1479
1484
|
return null;
|
|
1480
1485
|
};
|
|
1481
1486
|
const resolveElementProps = (el) => {
|
|
1482
|
-
const { props } = el;
|
|
1483
|
-
if (!props) return props;
|
|
1484
1487
|
let resolved;
|
|
1485
|
-
for (const key in
|
|
1486
|
-
if (typeof
|
|
1488
|
+
for (const key in el) {
|
|
1489
|
+
if (typeof el[key] !== "function") continue;
|
|
1487
1490
|
if (NON_CSS_PROPS.has(key)) continue;
|
|
1488
1491
|
if (key.charCodeAt(0) >= 65 && key.charCodeAt(0) <= 90) continue;
|
|
1489
1492
|
if (key.startsWith("on")) continue;
|
|
1490
|
-
if (
|
|
1493
|
+
if (key.startsWith("__")) continue;
|
|
1494
|
+
if (!resolved) resolved = {};
|
|
1491
1495
|
let result;
|
|
1492
1496
|
try {
|
|
1493
|
-
result =
|
|
1497
|
+
result = el[key](el, el.state || {});
|
|
1494
1498
|
} catch {
|
|
1495
1499
|
try {
|
|
1496
1500
|
const mockState = { root: {}, ...el.state || {} };
|
|
1497
|
-
result =
|
|
1501
|
+
result = el[key](el, mockState);
|
|
1498
1502
|
} catch {
|
|
1499
1503
|
}
|
|
1500
1504
|
}
|
|
1501
1505
|
if (result !== void 0 && result !== null && result !== false) {
|
|
1502
1506
|
resolved[key] = result;
|
|
1503
|
-
} else {
|
|
1504
|
-
delete resolved[key];
|
|
1505
1507
|
}
|
|
1506
1508
|
}
|
|
1507
|
-
return resolved ||
|
|
1509
|
+
return resolved || el;
|
|
1508
1510
|
};
|
|
1509
1511
|
const extractCSS = (element, ds) => {
|
|
1510
1512
|
const mediaMap = ds?.media || {};
|
package/dist/esm/env.js
CHANGED
|
@@ -2,7 +2,11 @@ import { parseHTML } from "linkedom";
|
|
|
2
2
|
const createEnv = (html = "<!DOCTYPE html><html><head></head><body></body></html>") => {
|
|
3
3
|
const { window, document } = parseHTML(html);
|
|
4
4
|
if (!window.requestAnimationFrame) {
|
|
5
|
-
window.requestAnimationFrame = (fn) =>
|
|
5
|
+
window.requestAnimationFrame = (fn) => {
|
|
6
|
+
const id = setTimeout(fn, 0);
|
|
7
|
+
if (id?.unref) id.unref();
|
|
8
|
+
return id;
|
|
9
|
+
};
|
|
6
10
|
}
|
|
7
11
|
if (!window.cancelAnimationFrame) {
|
|
8
12
|
window.cancelAnimationFrame = (id) => clearTimeout(id);
|
|
@@ -65,6 +69,7 @@ const createEnv = (html = "<!DOCTYPE html><html><head></head><body></body></html
|
|
|
65
69
|
globalThis.window = window;
|
|
66
70
|
globalThis.document = document;
|
|
67
71
|
globalThis.Node = window.Node || globalThis.Node;
|
|
72
|
+
globalThis.Element = window.Element || globalThis.Element;
|
|
68
73
|
globalThis.HTMLElement = window.HTMLElement || globalThis.HTMLElement;
|
|
69
74
|
globalThis.MutationObserver = window.MutationObserver;
|
|
70
75
|
globalThis.Window = window.constructor;
|
package/dist/esm/hydrate.js
CHANGED
|
@@ -53,12 +53,12 @@ const hydrate = (element, options = {}) => {
|
|
|
53
53
|
return { element, linked, unlinked };
|
|
54
54
|
};
|
|
55
55
|
const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
56
|
-
const { node
|
|
57
|
-
if (!node
|
|
56
|
+
const { node } = el;
|
|
57
|
+
if (!node) return;
|
|
58
58
|
const css = {};
|
|
59
59
|
let hasCss = false;
|
|
60
|
-
for (const key in
|
|
61
|
-
const val =
|
|
60
|
+
for (const key in el) {
|
|
61
|
+
const val = el[key];
|
|
62
62
|
if (key.charCodeAt(0) === 64) {
|
|
63
63
|
const breakpoint = mediaMap[key.slice(1)];
|
|
64
64
|
if (breakpoint && typeof val === "object") {
|
|
@@ -112,7 +112,7 @@ const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
|
112
112
|
if (typeof el.key === "string" && el.key.charCodeAt(0) === 95 && el.key.charCodeAt(1) !== 95) {
|
|
113
113
|
classes.push(el.key.slice(1));
|
|
114
114
|
}
|
|
115
|
-
if (
|
|
115
|
+
if (el.class) classes.push(el.class);
|
|
116
116
|
if (el.attr?.class) classes.push(el.attr.class);
|
|
117
117
|
const classlist = el.classlist;
|
|
118
118
|
if (classlist) {
|
|
@@ -129,7 +129,7 @@ const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
|
129
129
|
if (classes.length) {
|
|
130
130
|
node.setAttribute("class", classes.join(" "));
|
|
131
131
|
}
|
|
132
|
-
for (const key in
|
|
132
|
+
for (const key in el) {
|
|
133
133
|
if (isCSS(key) && node.hasAttribute(key)) {
|
|
134
134
|
node.removeAttribute(key);
|
|
135
135
|
}
|
|
@@ -480,47 +480,36 @@ const DOMQL_LIFECYCLE = /* @__PURE__ */ new Set([
|
|
|
480
480
|
"error"
|
|
481
481
|
]);
|
|
482
482
|
const bindEvents = (el) => {
|
|
483
|
-
const { node
|
|
483
|
+
const { node } = el;
|
|
484
484
|
if (!node) return;
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
if (props) {
|
|
495
|
-
for (const key in props) {
|
|
496
|
-
if (key.length <= 2 || key[0] !== "o" || key[1] !== "n") continue;
|
|
497
|
-
if (typeof props[key] !== "function") continue;
|
|
498
|
-
const third = key[2];
|
|
499
|
-
if (third !== third.toUpperCase()) continue;
|
|
500
|
-
const eventName = third.toLowerCase() + key.slice(3);
|
|
501
|
-
if (handled.has(eventName) || DOMQL_LIFECYCLE.has(eventName)) continue;
|
|
502
|
-
addListener(node, eventName, props[key], el);
|
|
503
|
-
}
|
|
485
|
+
if (!el.__ref.__eventCleanup) el.__ref.__eventCleanup = [];
|
|
486
|
+
for (const key in el) {
|
|
487
|
+
if (key.length <= 2 || key[0] !== "o" || key[1] !== "n") continue;
|
|
488
|
+
if (typeof el[key] !== "function") continue;
|
|
489
|
+
const third = key[2];
|
|
490
|
+
if (third !== third.toUpperCase()) continue;
|
|
491
|
+
const eventName = third.toLowerCase() + key.slice(3);
|
|
492
|
+
if (DOMQL_LIFECYCLE.has(eventName)) continue;
|
|
493
|
+
addListener(node, eventName, el[key], el);
|
|
504
494
|
}
|
|
505
495
|
};
|
|
506
496
|
const addListener = (node, eventName, handler, el) => {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
497
|
+
const listener = (event) => {
|
|
498
|
+
try {
|
|
499
|
+
handler.call(el, event, el, el.state, el.context);
|
|
500
|
+
} catch (e) {
|
|
501
|
+
console.warn("[brender hydrate]", eventName, e.message);
|
|
512
502
|
}
|
|
513
|
-
}
|
|
503
|
+
};
|
|
504
|
+
node.addEventListener(eventName, listener);
|
|
505
|
+
el.__ref.__eventCleanup.push(() => node.removeEventListener(eventName, listener));
|
|
514
506
|
};
|
|
515
507
|
const fireLifecycle = (el) => {
|
|
516
508
|
if (!el || !el.__ref || !el.node) return;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
fireEvent(on.done, el);
|
|
522
|
-
fireEvent(on.create, el);
|
|
523
|
-
}
|
|
509
|
+
fireEvent(el.onRender, el);
|
|
510
|
+
fireEvent(el.onRenderRouter, el);
|
|
511
|
+
fireEvent(el.onDone, el);
|
|
512
|
+
fireEvent(el.onCreate, el);
|
|
524
513
|
if (el.__ref.__children) {
|
|
525
514
|
for (const childKey of el.__ref.__children) {
|
|
526
515
|
const child = el[childKey];
|
package/dist/esm/load.js
CHANGED
|
@@ -55,7 +55,9 @@ const loadProject = async (projectPath) => {
|
|
|
55
55
|
functionsModule,
|
|
56
56
|
methodsModule,
|
|
57
57
|
designSystemModule,
|
|
58
|
-
filesModule
|
|
58
|
+
filesModule,
|
|
59
|
+
assetsModule,
|
|
60
|
+
sharedLibsModule
|
|
59
61
|
] = await Promise.all([
|
|
60
62
|
bundleAndImport(join(symbolsDir, "app.js")),
|
|
61
63
|
bundleAndImport(join(symbolsDir, "state.js")),
|
|
@@ -67,9 +69,11 @@ const loadProject = async (projectPath) => {
|
|
|
67
69
|
bundleAndImport(join(symbolsDir, "functions", "index.js")),
|
|
68
70
|
bundleAndImport(join(symbolsDir, "methods", "index.js")),
|
|
69
71
|
bundleAndImport(join(symbolsDir, "designSystem", "index.js")),
|
|
70
|
-
bundleAndImport(join(symbolsDir, "files", "index.js"))
|
|
72
|
+
bundleAndImport(join(symbolsDir, "files", "index.js")),
|
|
73
|
+
bundleAndImport(join(symbolsDir, "assets", "index.js")).catch(() => null),
|
|
74
|
+
bundleAndImport(join(symbolsDir, "sharedLibraries.js")).catch(() => null)
|
|
71
75
|
]);
|
|
72
|
-
|
|
76
|
+
const result = {
|
|
73
77
|
app: { ...appModule?.default || {} },
|
|
74
78
|
state: { ...stateModule?.default || {} },
|
|
75
79
|
dependencies: { ...depsModule?.default || {} },
|
|
@@ -80,8 +84,19 @@ const loadProject = async (projectPath) => {
|
|
|
80
84
|
methods: { ...methodsModule || {} },
|
|
81
85
|
designSystem: { ...designSystemModule?.default || {} },
|
|
82
86
|
files: { ...filesModule?.default || {} },
|
|
83
|
-
|
|
87
|
+
assets: { ...assetsModule?.default || {} },
|
|
88
|
+
config: { ...configModule?.default || {} },
|
|
89
|
+
sharedLibraries: sharedLibsModule?.default || []
|
|
84
90
|
};
|
|
91
|
+
if (result.sharedLibraries.length) {
|
|
92
|
+
const { resolveSharedLibraries, mergeSharedLibraries } = await import("@symbo.ls/utils");
|
|
93
|
+
const hasStrings = result.sharedLibraries.some((lib) => typeof lib === "string");
|
|
94
|
+
if (hasStrings) {
|
|
95
|
+
result.sharedLibraries = await resolveSharedLibraries(result.sharedLibraries);
|
|
96
|
+
}
|
|
97
|
+
mergeSharedLibraries(result, result.sharedLibraries);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
85
100
|
};
|
|
86
101
|
const loadAndRenderAll = async (projectPath, renderFn) => {
|
|
87
102
|
const data = await loadProject(projectPath);
|