@domql/brender 3.2.7
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 +282 -0
- package/dist/cjs/env.js +57 -0
- package/dist/cjs/hydrate.js +472 -0
- package/dist/cjs/index.js +58 -0
- package/dist/cjs/keys.js +62 -0
- package/dist/cjs/load.js +82 -0
- package/dist/cjs/metadata.js +102 -0
- package/dist/cjs/render.js +341 -0
- package/dist/esm/env.js +38 -0
- package/dist/esm/hydrate.js +453 -0
- package/dist/esm/index.js +39 -0
- package/dist/esm/keys.js +43 -0
- package/dist/esm/load.js +63 -0
- package/dist/esm/metadata.js +83 -0
- package/dist/esm/render.js +311 -0
- package/env.js +43 -0
- package/hydrate.js +388 -0
- package/index.js +40 -0
- package/keys.js +54 -0
- package/load.js +81 -0
- package/metadata.js +117 -0
- package/package.json +48 -0
- package/render.js +386 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
const collectBrNodes = (root) => {
|
|
2
|
+
const container = root || document;
|
|
3
|
+
const nodes = container.querySelectorAll("[data-br]");
|
|
4
|
+
const map = {};
|
|
5
|
+
nodes.forEach((node) => {
|
|
6
|
+
map[node.getAttribute("data-br")] = node;
|
|
7
|
+
});
|
|
8
|
+
return map;
|
|
9
|
+
};
|
|
10
|
+
const hydrate = (element, options = {}) => {
|
|
11
|
+
const {
|
|
12
|
+
root,
|
|
13
|
+
events: attachEvents = true,
|
|
14
|
+
renderEvents: fireRenderEvents = true,
|
|
15
|
+
emotion,
|
|
16
|
+
designSystem
|
|
17
|
+
} = options;
|
|
18
|
+
const brNodes = collectBrNodes(root);
|
|
19
|
+
const colorMap = designSystem?.color || {};
|
|
20
|
+
const mediaMap = designSystem?.media || {};
|
|
21
|
+
let linked = 0;
|
|
22
|
+
let unlinked = 0;
|
|
23
|
+
const walk = (el) => {
|
|
24
|
+
if (!el || !el.__ref) return;
|
|
25
|
+
const brKey = el.__ref.__brKey;
|
|
26
|
+
if (brKey) {
|
|
27
|
+
const node = brNodes[brKey];
|
|
28
|
+
if (node) {
|
|
29
|
+
el.node = node;
|
|
30
|
+
node.ref = el;
|
|
31
|
+
if (emotion) {
|
|
32
|
+
renderCSS(el, emotion, colorMap, mediaMap);
|
|
33
|
+
}
|
|
34
|
+
if (attachEvents) {
|
|
35
|
+
bindEvents(el);
|
|
36
|
+
}
|
|
37
|
+
linked++;
|
|
38
|
+
} else {
|
|
39
|
+
unlinked++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (el.__ref.__children) {
|
|
43
|
+
for (const childKey of el.__ref.__children) {
|
|
44
|
+
const child = el[childKey];
|
|
45
|
+
if (child && child.__ref) walk(child);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
walk(element);
|
|
50
|
+
if (fireRenderEvents) {
|
|
51
|
+
fireLifecycle(element);
|
|
52
|
+
}
|
|
53
|
+
return { element, linked, unlinked };
|
|
54
|
+
};
|
|
55
|
+
const renderCSS = (el, emotion, colorMap, mediaMap) => {
|
|
56
|
+
const { node, props } = el;
|
|
57
|
+
if (!node || !props) return;
|
|
58
|
+
const css = {};
|
|
59
|
+
let hasCss = false;
|
|
60
|
+
for (const key in props) {
|
|
61
|
+
const val = props[key];
|
|
62
|
+
if (key.charCodeAt(0) === 64) {
|
|
63
|
+
const breakpoint = mediaMap[key.slice(1)];
|
|
64
|
+
if (breakpoint && typeof val === "object") {
|
|
65
|
+
const mediaCss = resolvePropsToCSS(val, colorMap);
|
|
66
|
+
if (Object.keys(mediaCss).length) {
|
|
67
|
+
css[breakpoint] = mediaCss;
|
|
68
|
+
hasCss = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (key.charCodeAt(0) === 58) {
|
|
74
|
+
if (typeof val === "object") {
|
|
75
|
+
const pseudoCss = resolvePropsToCSS(val, colorMap);
|
|
76
|
+
if (Object.keys(pseudoCss).length) {
|
|
77
|
+
css["&" + key] = pseudoCss;
|
|
78
|
+
hasCss = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const expanded = resolveShorthand(key, val);
|
|
84
|
+
if (expanded) {
|
|
85
|
+
for (const ek in expanded) {
|
|
86
|
+
css[ek] = resolveValue(ek, expanded[ek], colorMap);
|
|
87
|
+
}
|
|
88
|
+
hasCss = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (!isCSS(key)) continue;
|
|
92
|
+
css[key] = resolveValue(key, val, colorMap);
|
|
93
|
+
hasCss = true;
|
|
94
|
+
}
|
|
95
|
+
if (el.style && typeof el.style === "object") {
|
|
96
|
+
Object.assign(css, el.style);
|
|
97
|
+
hasCss = true;
|
|
98
|
+
}
|
|
99
|
+
if (!hasCss) return;
|
|
100
|
+
const emotionClass = emotion.css(css);
|
|
101
|
+
const classes = [];
|
|
102
|
+
if (emotionClass) classes.push(emotionClass);
|
|
103
|
+
if (typeof el.key === "string" && el.key.charCodeAt(0) === 95 && el.key.charCodeAt(1) !== 95) {
|
|
104
|
+
classes.push(el.key.slice(1));
|
|
105
|
+
}
|
|
106
|
+
if (props.class) classes.push(props.class);
|
|
107
|
+
if (el.attr?.class) classes.push(el.attr.class);
|
|
108
|
+
const classlist = el.classlist;
|
|
109
|
+
if (classlist) {
|
|
110
|
+
if (typeof classlist === "string") classes.push(classlist);
|
|
111
|
+
else if (typeof classlist === "object") {
|
|
112
|
+
for (const k in classlist) {
|
|
113
|
+
const v = classlist[k];
|
|
114
|
+
if (typeof v === "boolean" && v) classes.push(k);
|
|
115
|
+
else if (typeof v === "string") classes.push(v);
|
|
116
|
+
else if (typeof v === "object" && v) classes.push(emotion.css(v));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (classes.length) {
|
|
121
|
+
node.setAttribute("class", classes.join(" "));
|
|
122
|
+
}
|
|
123
|
+
for (const key in props) {
|
|
124
|
+
if (isCSS(key) && node.hasAttribute(key)) {
|
|
125
|
+
node.removeAttribute(key);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const resolvePropsToCSS = (propsObj, colorMap) => {
|
|
130
|
+
const css = {};
|
|
131
|
+
for (const key in propsObj) {
|
|
132
|
+
const expanded = resolveShorthand(key, propsObj[key]);
|
|
133
|
+
if (expanded) {
|
|
134
|
+
for (const ek in expanded) css[ek] = resolveValue(ek, expanded[ek], colorMap);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (!isCSS(key)) continue;
|
|
138
|
+
css[key] = resolveValue(key, propsObj[key], colorMap);
|
|
139
|
+
}
|
|
140
|
+
return css;
|
|
141
|
+
};
|
|
142
|
+
const COLOR_PROPS = /* @__PURE__ */ new Set([
|
|
143
|
+
"color",
|
|
144
|
+
"background",
|
|
145
|
+
"backgroundColor",
|
|
146
|
+
"borderColor",
|
|
147
|
+
"borderTopColor",
|
|
148
|
+
"borderRightColor",
|
|
149
|
+
"borderBottomColor",
|
|
150
|
+
"borderLeftColor",
|
|
151
|
+
"outlineColor",
|
|
152
|
+
"fill",
|
|
153
|
+
"stroke",
|
|
154
|
+
"caretColor",
|
|
155
|
+
"columnRuleColor",
|
|
156
|
+
"textDecorationColor",
|
|
157
|
+
"boxShadow",
|
|
158
|
+
"textShadow"
|
|
159
|
+
]);
|
|
160
|
+
const resolveValue = (key, val, colorMap) => {
|
|
161
|
+
if (typeof val !== "string") return val;
|
|
162
|
+
if (COLOR_PROPS.has(key) && colorMap[val]) return colorMap[val];
|
|
163
|
+
return val;
|
|
164
|
+
};
|
|
165
|
+
const NON_CSS_PROPS = /* @__PURE__ */ new Set([
|
|
166
|
+
"href",
|
|
167
|
+
"src",
|
|
168
|
+
"alt",
|
|
169
|
+
"title",
|
|
170
|
+
"id",
|
|
171
|
+
"name",
|
|
172
|
+
"type",
|
|
173
|
+
"value",
|
|
174
|
+
"placeholder",
|
|
175
|
+
"target",
|
|
176
|
+
"rel",
|
|
177
|
+
"loading",
|
|
178
|
+
"srcset",
|
|
179
|
+
"sizes",
|
|
180
|
+
"media",
|
|
181
|
+
"role",
|
|
182
|
+
"tabindex",
|
|
183
|
+
"for",
|
|
184
|
+
"action",
|
|
185
|
+
"method",
|
|
186
|
+
"enctype",
|
|
187
|
+
"autocomplete",
|
|
188
|
+
"autofocus",
|
|
189
|
+
"theme",
|
|
190
|
+
"__element",
|
|
191
|
+
"update"
|
|
192
|
+
]);
|
|
193
|
+
const resolveShorthand = (key, val) => {
|
|
194
|
+
if (key === "flexAlign" && typeof val === "string") {
|
|
195
|
+
const [alignItems, justifyContent] = val.split(" ");
|
|
196
|
+
return { display: "flex", alignItems, justifyContent };
|
|
197
|
+
}
|
|
198
|
+
if (key === "gridAlign" && typeof val === "string") {
|
|
199
|
+
const [alignItems, justifyContent] = val.split(" ");
|
|
200
|
+
return { display: "grid", alignItems, justifyContent };
|
|
201
|
+
}
|
|
202
|
+
if (key === "round" && val) {
|
|
203
|
+
return { borderRadius: typeof val === "number" ? val + "px" : val };
|
|
204
|
+
}
|
|
205
|
+
if (key === "boxSize" && val) {
|
|
206
|
+
return { width: val, height: val };
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
};
|
|
210
|
+
const isCSS = (key) => {
|
|
211
|
+
const ch = key.charCodeAt(0);
|
|
212
|
+
if (ch === 95 || ch === 64 || ch === 58) return false;
|
|
213
|
+
if (ch >= 65 && ch <= 90) return false;
|
|
214
|
+
if (NON_CSS_PROPS.has(key)) return false;
|
|
215
|
+
return CSS_PROPERTIES.has(key);
|
|
216
|
+
};
|
|
217
|
+
const CSS_PROPERTIES = /* @__PURE__ */ new Set([
|
|
218
|
+
"display",
|
|
219
|
+
"position",
|
|
220
|
+
"top",
|
|
221
|
+
"right",
|
|
222
|
+
"bottom",
|
|
223
|
+
"left",
|
|
224
|
+
"width",
|
|
225
|
+
"height",
|
|
226
|
+
"minWidth",
|
|
227
|
+
"maxWidth",
|
|
228
|
+
"minHeight",
|
|
229
|
+
"maxHeight",
|
|
230
|
+
"margin",
|
|
231
|
+
"marginTop",
|
|
232
|
+
"marginRight",
|
|
233
|
+
"marginBottom",
|
|
234
|
+
"marginLeft",
|
|
235
|
+
"marginBlock",
|
|
236
|
+
"marginInline",
|
|
237
|
+
"padding",
|
|
238
|
+
"paddingTop",
|
|
239
|
+
"paddingRight",
|
|
240
|
+
"paddingBottom",
|
|
241
|
+
"paddingLeft",
|
|
242
|
+
"paddingBlock",
|
|
243
|
+
"paddingInline",
|
|
244
|
+
"border",
|
|
245
|
+
"borderTop",
|
|
246
|
+
"borderRight",
|
|
247
|
+
"borderBottom",
|
|
248
|
+
"borderLeft",
|
|
249
|
+
"borderRadius",
|
|
250
|
+
"borderColor",
|
|
251
|
+
"borderWidth",
|
|
252
|
+
"borderStyle",
|
|
253
|
+
"borderTopWidth",
|
|
254
|
+
"borderRightWidth",
|
|
255
|
+
"borderBottomWidth",
|
|
256
|
+
"borderLeftWidth",
|
|
257
|
+
"borderTopStyle",
|
|
258
|
+
"borderRightStyle",
|
|
259
|
+
"borderBottomStyle",
|
|
260
|
+
"borderLeftStyle",
|
|
261
|
+
"borderTopColor",
|
|
262
|
+
"borderRightColor",
|
|
263
|
+
"borderBottomColor",
|
|
264
|
+
"borderLeftColor",
|
|
265
|
+
"borderTopLeftRadius",
|
|
266
|
+
"borderTopRightRadius",
|
|
267
|
+
"borderBottomLeftRadius",
|
|
268
|
+
"borderBottomRightRadius",
|
|
269
|
+
"background",
|
|
270
|
+
"backgroundColor",
|
|
271
|
+
"backgroundImage",
|
|
272
|
+
"backgroundSize",
|
|
273
|
+
"backgroundPosition",
|
|
274
|
+
"backgroundRepeat",
|
|
275
|
+
"backgroundAttachment",
|
|
276
|
+
"color",
|
|
277
|
+
"fontSize",
|
|
278
|
+
"fontWeight",
|
|
279
|
+
"fontFamily",
|
|
280
|
+
"fontStyle",
|
|
281
|
+
"lineHeight",
|
|
282
|
+
"letterSpacing",
|
|
283
|
+
"textAlign",
|
|
284
|
+
"textDecoration",
|
|
285
|
+
"textTransform",
|
|
286
|
+
"textIndent",
|
|
287
|
+
"textOverflow",
|
|
288
|
+
"textShadow",
|
|
289
|
+
"opacity",
|
|
290
|
+
"overflow",
|
|
291
|
+
"overflowX",
|
|
292
|
+
"overflowY",
|
|
293
|
+
"zIndex",
|
|
294
|
+
"cursor",
|
|
295
|
+
"pointerEvents",
|
|
296
|
+
"userSelect",
|
|
297
|
+
"flex",
|
|
298
|
+
"flexDirection",
|
|
299
|
+
"flexWrap",
|
|
300
|
+
"flexFlow",
|
|
301
|
+
"flexGrow",
|
|
302
|
+
"flexShrink",
|
|
303
|
+
"flexBasis",
|
|
304
|
+
"alignItems",
|
|
305
|
+
"alignContent",
|
|
306
|
+
"alignSelf",
|
|
307
|
+
"justifyContent",
|
|
308
|
+
"justifyItems",
|
|
309
|
+
"justifySelf",
|
|
310
|
+
"gap",
|
|
311
|
+
"rowGap",
|
|
312
|
+
"columnGap",
|
|
313
|
+
"gridTemplateColumns",
|
|
314
|
+
"gridTemplateRows",
|
|
315
|
+
"gridColumn",
|
|
316
|
+
"gridRow",
|
|
317
|
+
"gridArea",
|
|
318
|
+
"gridAutoFlow",
|
|
319
|
+
"gridAutoColumns",
|
|
320
|
+
"gridAutoRows",
|
|
321
|
+
"transform",
|
|
322
|
+
"transformOrigin",
|
|
323
|
+
"transition",
|
|
324
|
+
"animation",
|
|
325
|
+
"animationDelay",
|
|
326
|
+
"boxShadow",
|
|
327
|
+
"outline",
|
|
328
|
+
"outlineColor",
|
|
329
|
+
"outlineWidth",
|
|
330
|
+
"outlineStyle",
|
|
331
|
+
"outlineOffset",
|
|
332
|
+
"whiteSpace",
|
|
333
|
+
"wordBreak",
|
|
334
|
+
"wordWrap",
|
|
335
|
+
"overflowWrap",
|
|
336
|
+
"visibility",
|
|
337
|
+
"boxSizing",
|
|
338
|
+
"objectFit",
|
|
339
|
+
"objectPosition",
|
|
340
|
+
"filter",
|
|
341
|
+
"backdropFilter",
|
|
342
|
+
"mixBlendMode",
|
|
343
|
+
"fill",
|
|
344
|
+
"stroke",
|
|
345
|
+
"strokeWidth",
|
|
346
|
+
"listStyle",
|
|
347
|
+
"listStyleType",
|
|
348
|
+
"listStylePosition",
|
|
349
|
+
"counterReset",
|
|
350
|
+
"counterIncrement",
|
|
351
|
+
"content",
|
|
352
|
+
"aspectRatio",
|
|
353
|
+
"resize",
|
|
354
|
+
"appearance",
|
|
355
|
+
"scrollBehavior",
|
|
356
|
+
"scrollMargin",
|
|
357
|
+
"scrollPadding",
|
|
358
|
+
"willChange",
|
|
359
|
+
"contain",
|
|
360
|
+
"isolation",
|
|
361
|
+
"caretColor",
|
|
362
|
+
"accentColor",
|
|
363
|
+
"columnCount",
|
|
364
|
+
"columnGap",
|
|
365
|
+
"columnRuleColor",
|
|
366
|
+
"columnRuleStyle",
|
|
367
|
+
"columnRuleWidth",
|
|
368
|
+
"textDecorationColor",
|
|
369
|
+
"textDecorationStyle",
|
|
370
|
+
"textDecorationThickness",
|
|
371
|
+
"clipPath",
|
|
372
|
+
"shapeOutside"
|
|
373
|
+
]);
|
|
374
|
+
const DOMQL_LIFECYCLE = /* @__PURE__ */ new Set([
|
|
375
|
+
"render",
|
|
376
|
+
"create",
|
|
377
|
+
"init",
|
|
378
|
+
"start",
|
|
379
|
+
"complete",
|
|
380
|
+
"done",
|
|
381
|
+
"beforeClassAssign",
|
|
382
|
+
"attachNode",
|
|
383
|
+
"stateInit",
|
|
384
|
+
"stateCreated",
|
|
385
|
+
"renderRouter",
|
|
386
|
+
"lazyLoad",
|
|
387
|
+
"error"
|
|
388
|
+
]);
|
|
389
|
+
const bindEvents = (el) => {
|
|
390
|
+
const { node, on, props } = el;
|
|
391
|
+
if (!node) return;
|
|
392
|
+
const handled = /* @__PURE__ */ new Set();
|
|
393
|
+
if (on) {
|
|
394
|
+
for (const param in on) {
|
|
395
|
+
if (DOMQL_LIFECYCLE.has(param)) continue;
|
|
396
|
+
if (typeof on[param] !== "function") continue;
|
|
397
|
+
handled.add(param);
|
|
398
|
+
addListener(node, param, on[param], el);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (props) {
|
|
402
|
+
for (const key in props) {
|
|
403
|
+
if (key.length <= 2 || key[0] !== "o" || key[1] !== "n") continue;
|
|
404
|
+
if (typeof props[key] !== "function") continue;
|
|
405
|
+
const third = key[2];
|
|
406
|
+
if (third !== third.toUpperCase()) continue;
|
|
407
|
+
const eventName = third.toLowerCase() + key.slice(3);
|
|
408
|
+
if (handled.has(eventName) || DOMQL_LIFECYCLE.has(eventName)) continue;
|
|
409
|
+
addListener(node, eventName, props[key], el);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const addListener = (node, eventName, handler, el) => {
|
|
414
|
+
node.addEventListener(eventName, (event) => {
|
|
415
|
+
const result = handler.call(el, event, el, el.state, el.context);
|
|
416
|
+
if (result && typeof result.then === "function") {
|
|
417
|
+
result.catch(() => {
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
const fireLifecycle = (el) => {
|
|
423
|
+
if (!el || !el.__ref || !el.node) return;
|
|
424
|
+
const on = el.on;
|
|
425
|
+
if (on) {
|
|
426
|
+
fireEvent(on.render, el);
|
|
427
|
+
fireEvent(on.renderRouter, el);
|
|
428
|
+
fireEvent(on.done, el);
|
|
429
|
+
fireEvent(on.create, el);
|
|
430
|
+
}
|
|
431
|
+
if (el.__ref.__children) {
|
|
432
|
+
for (const childKey of el.__ref.__children) {
|
|
433
|
+
const child = el[childKey];
|
|
434
|
+
if (child && child.__ref) fireLifecycle(child);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
const fireEvent = (fn, el) => {
|
|
439
|
+
if (typeof fn !== "function") return;
|
|
440
|
+
try {
|
|
441
|
+
const result = fn.call(el, el, el.state, el.context);
|
|
442
|
+
if (result && typeof result.then === "function") {
|
|
443
|
+
result.catch(() => {
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
} catch (e) {
|
|
447
|
+
console.warn("[brender hydrate]", el.key, e.message);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
export {
|
|
451
|
+
collectBrNodes,
|
|
452
|
+
hydrate
|
|
453
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createEnv } from "./env.js";
|
|
2
|
+
import { resetKeys, assignKeys, mapKeysToElements } from "./keys.js";
|
|
3
|
+
import { loadProject, loadAndRenderAll } from "./load.js";
|
|
4
|
+
import { render, renderElement, renderRoute, renderPage } from "./render.js";
|
|
5
|
+
import { extractMetadata, generateHeadHtml } from "./metadata.js";
|
|
6
|
+
import { collectBrNodes, hydrate } from "./hydrate.js";
|
|
7
|
+
var index_default = {
|
|
8
|
+
createEnv,
|
|
9
|
+
resetKeys,
|
|
10
|
+
assignKeys,
|
|
11
|
+
mapKeysToElements,
|
|
12
|
+
loadProject,
|
|
13
|
+
loadAndRenderAll,
|
|
14
|
+
render,
|
|
15
|
+
renderElement,
|
|
16
|
+
renderRoute,
|
|
17
|
+
renderPage,
|
|
18
|
+
extractMetadata,
|
|
19
|
+
generateHeadHtml,
|
|
20
|
+
collectBrNodes,
|
|
21
|
+
hydrate
|
|
22
|
+
};
|
|
23
|
+
export {
|
|
24
|
+
assignKeys,
|
|
25
|
+
collectBrNodes,
|
|
26
|
+
createEnv,
|
|
27
|
+
index_default as default,
|
|
28
|
+
extractMetadata,
|
|
29
|
+
generateHeadHtml,
|
|
30
|
+
hydrate,
|
|
31
|
+
loadAndRenderAll,
|
|
32
|
+
loadProject,
|
|
33
|
+
mapKeysToElements,
|
|
34
|
+
render,
|
|
35
|
+
renderElement,
|
|
36
|
+
renderPage,
|
|
37
|
+
renderRoute,
|
|
38
|
+
resetKeys
|
|
39
|
+
};
|
package/dist/esm/keys.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
let _keyCounter = 0;
|
|
2
|
+
const resetKeys = () => {
|
|
3
|
+
_keyCounter = 0;
|
|
4
|
+
};
|
|
5
|
+
const assignKeys = (node) => {
|
|
6
|
+
if (!node) return;
|
|
7
|
+
if (node.nodeType === 1) {
|
|
8
|
+
const key = `br-${_keyCounter++}`;
|
|
9
|
+
node.setAttribute("data-br", key);
|
|
10
|
+
}
|
|
11
|
+
const children = node.childNodes;
|
|
12
|
+
if (children) {
|
|
13
|
+
for (let i = 0; i < children.length; i++) {
|
|
14
|
+
assignKeys(children[i]);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const mapKeysToElements = (element, registry = {}) => {
|
|
19
|
+
if (!element) return registry;
|
|
20
|
+
const node = element.node;
|
|
21
|
+
if (node && node.getAttribute) {
|
|
22
|
+
const brKey = node.getAttribute("data-br");
|
|
23
|
+
if (brKey) {
|
|
24
|
+
if (!element.__ref) element.__ref = {};
|
|
25
|
+
element.__ref.__brKey = brKey;
|
|
26
|
+
registry[brKey] = element;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (element.__ref && element.__ref.__children) {
|
|
30
|
+
for (const childKey of element.__ref.__children) {
|
|
31
|
+
const child = element[childKey];
|
|
32
|
+
if (child && child.__ref) {
|
|
33
|
+
mapKeysToElements(child, registry);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return registry;
|
|
38
|
+
};
|
|
39
|
+
export {
|
|
40
|
+
assignKeys,
|
|
41
|
+
mapKeysToElements,
|
|
42
|
+
resetKeys
|
|
43
|
+
};
|
package/dist/esm/load.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolve, join } from "path";
|
|
2
|
+
const loadProject = async (projectPath) => {
|
|
3
|
+
const symbolsDir = resolve(projectPath, "symbols");
|
|
4
|
+
const tryImport = async (modulePath) => {
|
|
5
|
+
try {
|
|
6
|
+
return await import(modulePath);
|
|
7
|
+
} catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const [
|
|
12
|
+
appModule,
|
|
13
|
+
stateModule,
|
|
14
|
+
configModule,
|
|
15
|
+
depsModule,
|
|
16
|
+
componentsModule,
|
|
17
|
+
snippetsModule,
|
|
18
|
+
pagesModule,
|
|
19
|
+
functionsModule,
|
|
20
|
+
methodsModule,
|
|
21
|
+
designSystemModule,
|
|
22
|
+
filesModule
|
|
23
|
+
] = await Promise.all([
|
|
24
|
+
tryImport(join(symbolsDir, "app.js")),
|
|
25
|
+
tryImport(join(symbolsDir, "state.js")),
|
|
26
|
+
tryImport(join(symbolsDir, "config.js")),
|
|
27
|
+
tryImport(join(symbolsDir, "dependencies.js")),
|
|
28
|
+
tryImport(join(symbolsDir, "components", "index.js")),
|
|
29
|
+
tryImport(join(symbolsDir, "snippets", "index.js")),
|
|
30
|
+
tryImport(join(symbolsDir, "pages", "index.js")),
|
|
31
|
+
tryImport(join(symbolsDir, "functions", "index.js")),
|
|
32
|
+
tryImport(join(symbolsDir, "methods", "index.js")),
|
|
33
|
+
tryImport(join(symbolsDir, "designSystem", "index.js")),
|
|
34
|
+
tryImport(join(symbolsDir, "files", "index.js"))
|
|
35
|
+
]);
|
|
36
|
+
return {
|
|
37
|
+
app: appModule?.default || {},
|
|
38
|
+
state: stateModule?.default || {},
|
|
39
|
+
dependencies: depsModule?.default || {},
|
|
40
|
+
components: componentsModule || {},
|
|
41
|
+
snippets: snippetsModule || {},
|
|
42
|
+
pages: pagesModule?.default || {},
|
|
43
|
+
functions: functionsModule || {},
|
|
44
|
+
methods: methodsModule || {},
|
|
45
|
+
designSystem: designSystemModule?.default || {},
|
|
46
|
+
files: filesModule?.default || {},
|
|
47
|
+
config: configModule?.default || {}
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const loadAndRenderAll = async (projectPath, renderFn) => {
|
|
51
|
+
const data = await loadProject(projectPath);
|
|
52
|
+
const pages = data.pages || {};
|
|
53
|
+
const routes = Object.keys(pages);
|
|
54
|
+
const results = {};
|
|
55
|
+
for (const route of routes) {
|
|
56
|
+
results[route] = await renderFn(data, { route });
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
};
|
|
60
|
+
export {
|
|
61
|
+
loadAndRenderAll,
|
|
62
|
+
loadProject
|
|
63
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const extractMetadata = (data, route = "/") => {
|
|
2
|
+
const pages = data.pages || {};
|
|
3
|
+
const page = pages[route];
|
|
4
|
+
let metadata = {};
|
|
5
|
+
if (data.integrations?.seo) {
|
|
6
|
+
metadata = { ...data.integrations.seo };
|
|
7
|
+
}
|
|
8
|
+
if (page) {
|
|
9
|
+
const pageMeta = page.metadata || page.helmet || {};
|
|
10
|
+
metadata = { ...metadata, ...pageMeta };
|
|
11
|
+
if (!metadata.title && page.state?.title) {
|
|
12
|
+
metadata.title = page.state.title;
|
|
13
|
+
}
|
|
14
|
+
if (!metadata.description && page.state?.description) {
|
|
15
|
+
metadata.description = page.state.description;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (!metadata.title) {
|
|
19
|
+
metadata.title = data.name || "Symbols";
|
|
20
|
+
}
|
|
21
|
+
return metadata;
|
|
22
|
+
};
|
|
23
|
+
const generateHeadHtml = (metadata) => {
|
|
24
|
+
const esc = (text) => {
|
|
25
|
+
if (text === null || text === void 0) return "";
|
|
26
|
+
const map = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
27
|
+
return text.toString().replace(/[&<>"']/g, (m) => map[m]);
|
|
28
|
+
};
|
|
29
|
+
const tags = [
|
|
30
|
+
'<meta charset="UTF-8">',
|
|
31
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">'
|
|
32
|
+
];
|
|
33
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
34
|
+
if (!value && value !== 0 && value !== false) continue;
|
|
35
|
+
if (key === "title") {
|
|
36
|
+
tags.push(`<title>${esc(value)}</title>`);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (key === "canonical") {
|
|
40
|
+
tags.push(`<link rel="canonical" href="${esc(value)}">`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (key === "alternate" && Array.isArray(value)) {
|
|
44
|
+
value.forEach((alt) => {
|
|
45
|
+
if (typeof alt === "object") {
|
|
46
|
+
const attrs = Object.entries(alt).map(([k, v]) => `${k}="${esc(v)}"`).join(" ");
|
|
47
|
+
tags.push(`<link rel="alternate" ${attrs}>`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const propertyPrefixes = ["og:", "article:", "product:", "fb:", "profile:", "book:", "business:", "music:", "video:"];
|
|
53
|
+
const namePrefixes = ["twitter:", "DC:", "DCTERMS:"];
|
|
54
|
+
const isProperty = propertyPrefixes.some((p) => key.startsWith(p));
|
|
55
|
+
const isName = namePrefixes.some((p) => key.startsWith(p));
|
|
56
|
+
if (key.startsWith("http-equiv:")) {
|
|
57
|
+
const httpKey = key.replace("http-equiv:", "");
|
|
58
|
+
tags.push(`<meta http-equiv="${esc(httpKey)}" content="${esc(value)}">`);
|
|
59
|
+
} else if (key.startsWith("itemprop:")) {
|
|
60
|
+
const itemKey = key.replace("itemprop:", "");
|
|
61
|
+
tags.push(`<meta itemprop="${esc(itemKey)}" content="${esc(value)}">`);
|
|
62
|
+
} else if (isProperty) {
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
value.forEach((v) => tags.push(`<meta property="${esc(key)}" content="${esc(v)}">`));
|
|
65
|
+
} else {
|
|
66
|
+
tags.push(`<meta property="${esc(key)}" content="${esc(value)}">`);
|
|
67
|
+
}
|
|
68
|
+
} else if (isName) {
|
|
69
|
+
tags.push(`<meta name="${esc(key)}" content="${esc(value)}">`);
|
|
70
|
+
} else if (key !== "favicon" && key !== "favicons") {
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
value.forEach((v) => tags.push(`<meta name="${esc(key)}" content="${esc(v)}">`));
|
|
73
|
+
} else if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
74
|
+
tags.push(`<meta name="${esc(key)}" content="${esc(value)}">`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return tags.join("\n");
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
extractMetadata,
|
|
82
|
+
generateHeadHtml
|
|
83
|
+
};
|