@jxsuite/compiler 0.19.0 → 0.21.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/dist/compiler.js +4 -4
- package/package.json +6 -4
- package/src/cli.js +1 -1
- package/src/compiler.js +2 -2
- package/src/shared.js +183 -145
- package/src/site/content-loader.js +106 -76
- package/src/site/context-injection.js +30 -24
- package/src/site/head-merger.js +13 -12
- package/src/site/image-optimizer.js +2 -2
- package/src/site/image-transform.js +5 -4
- package/src/site/layout-resolver.js +32 -25
- package/src/site/pages-discovery.js +6 -6
- package/src/site/prototype-resolver.js +1 -1
- package/src/site/site-build.js +71 -51
- package/src/site/site-loader.js +1 -1
- package/src/targets/compile-class.js +27 -21
- package/src/targets/compile-client.js +75 -33
- package/src/targets/compile-element.js +57 -39
- package/src/targets/compile-markdown.js +99 -78
- package/src/targets/compile-server.js +1 -1
- package/src/targets/compile-static.js +24 -13
|
@@ -65,10 +65,10 @@ const WRAPPER_TAGS = new Set([
|
|
|
65
65
|
* Convert a Jx node to an array of mdast nodes. Returns an array because wrapper unwrapping can
|
|
66
66
|
* produce multiple children.
|
|
67
67
|
*
|
|
68
|
-
* @param {
|
|
69
|
-
* @param {Map<string,
|
|
70
|
-
* @param {
|
|
71
|
-
* @returns {
|
|
68
|
+
* @param {JxElement | string} node
|
|
69
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
70
|
+
* @param {Record<string, unknown> | null} [scope] - Current resolution scope
|
|
71
|
+
* @returns {MdastNode[]}
|
|
72
72
|
*/
|
|
73
73
|
function nodeToMdast(node, componentDefs, scope) {
|
|
74
74
|
// Bare text
|
|
@@ -153,8 +153,8 @@ function nodeToMdast(node, componentDefs, scope) {
|
|
|
153
153
|
return [{ type: "inlineCode", value: text ?? "" }];
|
|
154
154
|
|
|
155
155
|
case "link": {
|
|
156
|
-
const href = node.attributes?.href ?? "";
|
|
157
|
-
const title = node.attributes?.title ?? null;
|
|
156
|
+
const href = String(node.attributes?.href ?? "");
|
|
157
|
+
const title = /** @type {string | null} */ (node.attributes?.title ?? null);
|
|
158
158
|
const children =
|
|
159
159
|
text != null
|
|
160
160
|
? [{ type: "text", value: text }]
|
|
@@ -163,9 +163,9 @@ function nodeToMdast(node, componentDefs, scope) {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
case "image": {
|
|
166
|
-
const src = node.attributes?.src ?? "";
|
|
167
|
-
const alt = node.attributes?.alt ?? "";
|
|
168
|
-
const title = node.attributes?.title ?? null;
|
|
166
|
+
const src = String(node.attributes?.src ?? "");
|
|
167
|
+
const alt = String(node.attributes?.alt ?? "");
|
|
168
|
+
const title = /** @type {string | null} */ (node.attributes?.title ?? null);
|
|
169
169
|
return [{ type: "image", url: src, alt, title }];
|
|
170
170
|
}
|
|
171
171
|
|
|
@@ -199,10 +199,16 @@ function nodeToMdast(node, componentDefs, scope) {
|
|
|
199
199
|
case "code": {
|
|
200
200
|
// pre > code → fenced code block
|
|
201
201
|
const codeChild = Array.isArray(node.children)
|
|
202
|
-
? node.children.find(
|
|
202
|
+
? node.children.find(
|
|
203
|
+
(/** @type {JxElement | string} */ c) =>
|
|
204
|
+
/** @type {JxMutableNode} */ (c)?.tagName === "code",
|
|
205
|
+
)
|
|
203
206
|
: null;
|
|
204
|
-
const value = codeChild?.textContent ?? text ?? "";
|
|
205
|
-
const lang = codeChild?.className?.replace(
|
|
207
|
+
const value = /** @type {JxElement | undefined} */ (codeChild)?.textContent ?? text ?? "";
|
|
208
|
+
const lang = /** @type {JxElement | undefined} */ (codeChild)?.className?.replace(
|
|
209
|
+
"language-",
|
|
210
|
+
"",
|
|
211
|
+
) ?? null;
|
|
206
212
|
return [{ type: "code", lang, value }];
|
|
207
213
|
}
|
|
208
214
|
|
|
@@ -250,10 +256,10 @@ function isInlineType(type) {
|
|
|
250
256
|
/**
|
|
251
257
|
* Convert a node's children to mdast nodes (block context).
|
|
252
258
|
*
|
|
253
|
-
* @param {
|
|
254
|
-
* @param {Map<string,
|
|
255
|
-
* @param {
|
|
256
|
-
* @returns {
|
|
259
|
+
* @param {JxElement} node
|
|
260
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
261
|
+
* @param {Record<string, unknown> | null} [scope]
|
|
262
|
+
* @returns {MdastNode[]}
|
|
257
263
|
*/
|
|
258
264
|
function convertChildren(node, componentDefs, scope) {
|
|
259
265
|
if (node.textContent != null) {
|
|
@@ -262,16 +268,18 @@ function convertChildren(node, componentDefs, scope) {
|
|
|
262
268
|
return [];
|
|
263
269
|
}
|
|
264
270
|
if (!Array.isArray(node.children)) return [];
|
|
265
|
-
return node.children.flatMap((/** @type {
|
|
271
|
+
return node.children.flatMap((/** @type {JxElement | string} */ c) =>
|
|
272
|
+
nodeToMdast(c, componentDefs, scope),
|
|
273
|
+
);
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
/**
|
|
269
277
|
* Convert children in inline context — same as convertChildren but for inline content.
|
|
270
278
|
*
|
|
271
|
-
* @param {
|
|
272
|
-
* @param {Map<string,
|
|
273
|
-
* @param {
|
|
274
|
-
* @returns {
|
|
279
|
+
* @param {JxElement} node
|
|
280
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
281
|
+
* @param {Record<string, unknown> | null} [scope]
|
|
282
|
+
* @returns {MdastNode[]}
|
|
275
283
|
*/
|
|
276
284
|
function convertChildrenInline(node, componentDefs, scope) {
|
|
277
285
|
if (node.textContent != null) {
|
|
@@ -280,7 +288,9 @@ function convertChildrenInline(node, componentDefs, scope) {
|
|
|
280
288
|
return [];
|
|
281
289
|
}
|
|
282
290
|
if (!Array.isArray(node.children)) return [];
|
|
283
|
-
return node.children.flatMap((/** @type {
|
|
291
|
+
return node.children.flatMap((/** @type {JxElement | string} */ c) =>
|
|
292
|
+
nodeToMdast(c, componentDefs, scope),
|
|
293
|
+
);
|
|
284
294
|
}
|
|
285
295
|
|
|
286
296
|
// ─── Component inlining ─────────────────────────────────────────────────────
|
|
@@ -288,10 +298,10 @@ function convertChildrenInline(node, componentDefs, scope) {
|
|
|
288
298
|
/**
|
|
289
299
|
* Inline a custom element by resolving its component definition.
|
|
290
300
|
*
|
|
291
|
-
* @param {
|
|
301
|
+
* @param {JxElement} node - The element instance (with $props, children, etc.)
|
|
292
302
|
* @param {string} tag - The tagName
|
|
293
|
-
* @param {Map<string,
|
|
294
|
-
* @returns {
|
|
303
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
304
|
+
* @returns {MdastNode[]}
|
|
295
305
|
*/
|
|
296
306
|
function inlineComponent(node, tag, componentDefs) {
|
|
297
307
|
const def = componentDefs.get(tag);
|
|
@@ -314,10 +324,10 @@ function inlineComponent(node, tag, componentDefs) {
|
|
|
314
324
|
) {
|
|
315
325
|
stateDefs[key] = { ...existing, default: value };
|
|
316
326
|
} else {
|
|
317
|
-
stateDefs[key] = value;
|
|
327
|
+
stateDefs[key] = /** @type {JxStateDefinition} */ (value);
|
|
318
328
|
}
|
|
319
329
|
} else {
|
|
320
|
-
stateDefs[key] = value;
|
|
330
|
+
stateDefs[key] = /** @type {JxStateDefinition} */ (value);
|
|
321
331
|
}
|
|
322
332
|
}
|
|
323
333
|
|
|
@@ -331,10 +341,15 @@ function inlineComponent(node, tag, componentDefs) {
|
|
|
331
341
|
|
|
332
342
|
// Convert to mdast, passing instance's own children as potential slot content
|
|
333
343
|
const instanceChildren = node.children;
|
|
334
|
-
return resolved.flatMap((/** @type {
|
|
344
|
+
return resolved.flatMap((/** @type {JxElement | string} */ child) => {
|
|
335
345
|
// Replace slot elements with instance children
|
|
336
|
-
if (
|
|
337
|
-
|
|
346
|
+
if (
|
|
347
|
+
/** @type {JxMutableNode} */ (child)?.tagName === "slot" &&
|
|
348
|
+
Array.isArray(instanceChildren)
|
|
349
|
+
) {
|
|
350
|
+
return instanceChildren.flatMap((/** @type {JxElement | string} */ c) =>
|
|
351
|
+
nodeToMdast(c, componentDefs),
|
|
352
|
+
);
|
|
338
353
|
}
|
|
339
354
|
return nodeToMdast(child, componentDefs, scope);
|
|
340
355
|
});
|
|
@@ -343,35 +358,37 @@ function inlineComponent(node, tag, componentDefs) {
|
|
|
343
358
|
/**
|
|
344
359
|
* Deep-resolve template expressions in a node tree.
|
|
345
360
|
*
|
|
346
|
-
* @param {
|
|
347
|
-
* @param {
|
|
348
|
-
* @returns {
|
|
361
|
+
* @param {(JxElement | string)[]} nodes
|
|
362
|
+
* @param {Record<string, unknown>} scope
|
|
363
|
+
* @returns {(JxElement | string)[]}
|
|
349
364
|
*/
|
|
350
365
|
function deepResolve(nodes, scope) {
|
|
351
366
|
if (!Array.isArray(nodes)) return [];
|
|
352
|
-
return nodes.map((/** @type {
|
|
367
|
+
return nodes.map((/** @type {JxElement | string} */ node) => resolveNode(node, scope));
|
|
353
368
|
}
|
|
354
369
|
|
|
355
370
|
/**
|
|
356
371
|
* Resolve template expressions in a single node.
|
|
357
372
|
*
|
|
358
|
-
* @param {
|
|
359
|
-
* @param {
|
|
360
|
-
* @returns {
|
|
373
|
+
* @param {JxElement | string} node
|
|
374
|
+
* @param {Record<string, unknown>} scope
|
|
375
|
+
* @returns {JxElement | string}
|
|
361
376
|
*/
|
|
362
377
|
function resolveNode(node, scope) {
|
|
363
378
|
if (typeof node === "string") {
|
|
364
|
-
return isTemplateString(node) ? (evaluateStaticTemplate(node, scope) ?? node) : node;
|
|
379
|
+
return isTemplateString(node) ? String(evaluateStaticTemplate(node, scope) ?? node) : node;
|
|
365
380
|
}
|
|
366
381
|
if (!node || typeof node !== "object") return node;
|
|
367
382
|
|
|
368
383
|
const result = { ...node };
|
|
369
384
|
|
|
370
385
|
if (typeof result.textContent === "string" && isTemplateString(result.textContent)) {
|
|
371
|
-
result.textContent =
|
|
386
|
+
result.textContent = String(
|
|
387
|
+
evaluateStaticTemplate(result.textContent, scope) ?? result.textContent,
|
|
388
|
+
);
|
|
372
389
|
}
|
|
373
390
|
if (typeof result.innerHTML === "string" && isTemplateString(result.innerHTML)) {
|
|
374
|
-
result.innerHTML = evaluateStaticTemplate(result.innerHTML, scope) ?? result.innerHTML;
|
|
391
|
+
result.innerHTML = String(evaluateStaticTemplate(result.innerHTML, scope) ?? result.innerHTML);
|
|
375
392
|
}
|
|
376
393
|
if (result.attributes) {
|
|
377
394
|
result.attributes = { ...result.attributes };
|
|
@@ -393,23 +410,23 @@ function resolveNode(node, scope) {
|
|
|
393
410
|
/**
|
|
394
411
|
* Expand a $prototype: "Array" descriptor into concrete mdast nodes.
|
|
395
412
|
*
|
|
396
|
-
* @param {
|
|
397
|
-
* @param {Map<string,
|
|
398
|
-
* @param {
|
|
399
|
-
* @returns {
|
|
413
|
+
* @param {JxElement} arrayDef
|
|
414
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
415
|
+
* @param {Record<string, unknown> | null} [scope]
|
|
416
|
+
* @returns {MdastNode[]}
|
|
400
417
|
*/
|
|
401
418
|
function expandArray(arrayDef, componentDefs, scope) {
|
|
402
|
-
const itemsRef = arrayDef.items?.$ref;
|
|
419
|
+
const itemsRef = /** @type {JxMutableNode} */ (arrayDef).items?.$ref;
|
|
403
420
|
if (!itemsRef || !scope) return [];
|
|
404
421
|
|
|
405
422
|
// Resolve the items array from scope
|
|
406
423
|
const items = resolveRef(itemsRef, scope);
|
|
407
424
|
if (!Array.isArray(items)) return [];
|
|
408
425
|
|
|
409
|
-
const mapTemplate = arrayDef.map;
|
|
426
|
+
const mapTemplate = /** @type {JxMutableNode} */ (arrayDef).map;
|
|
410
427
|
if (!mapTemplate) return [];
|
|
411
428
|
|
|
412
|
-
return items.flatMap((/** @type {
|
|
429
|
+
return items.flatMap((/** @type {JxMutableNode} */ item, /** @type {number} */ index) => {
|
|
413
430
|
// Create a scope with $map values
|
|
414
431
|
const mapScope = Object.create(scope);
|
|
415
432
|
mapScope.item = item;
|
|
@@ -424,8 +441,8 @@ function expandArray(arrayDef, componentDefs, scope) {
|
|
|
424
441
|
/**
|
|
425
442
|
* Resolve $map/ references in a map template node.
|
|
426
443
|
*
|
|
427
|
-
* @param {
|
|
428
|
-
* @param {
|
|
444
|
+
* @param {JxMutableNode} node
|
|
445
|
+
* @param {Record<string, unknown>} item
|
|
429
446
|
* @returns {any}
|
|
430
447
|
*/
|
|
431
448
|
function resolveMapNode(node, item) {
|
|
@@ -436,8 +453,8 @@ function resolveMapNode(node, item) {
|
|
|
436
453
|
|
|
437
454
|
// Resolve $ref values
|
|
438
455
|
for (const [key, value] of Object.entries(result)) {
|
|
439
|
-
if (value && typeof value === "object" && value.$ref) {
|
|
440
|
-
const ref = value.$ref;
|
|
456
|
+
if (value && typeof value === "object" && /** @type {JxMutableNode} */ (value).$ref) {
|
|
457
|
+
const ref = /** @type {string} */ (/** @type {JxMutableNode} */ (value).$ref);
|
|
441
458
|
if (ref.startsWith("$map/")) {
|
|
442
459
|
const path = ref.slice("$map/".length);
|
|
443
460
|
result[key] = resolvePath(
|
|
@@ -457,7 +474,9 @@ function resolveMapNode(node, item) {
|
|
|
457
474
|
}
|
|
458
475
|
|
|
459
476
|
if (Array.isArray(result.children)) {
|
|
460
|
-
result.children = result.children.map((
|
|
477
|
+
result.children = result.children.map((c) =>
|
|
478
|
+
resolveMapNode(/** @type {JxMutableNode} */ (/** @type {unknown} */ (c)), item),
|
|
479
|
+
);
|
|
461
480
|
}
|
|
462
481
|
|
|
463
482
|
return result;
|
|
@@ -466,13 +485,13 @@ function resolveMapNode(node, item) {
|
|
|
466
485
|
/**
|
|
467
486
|
* Resolve a dot/slash-separated path on an object.
|
|
468
487
|
*
|
|
469
|
-
* @param {
|
|
488
|
+
* @param {unknown} obj
|
|
470
489
|
* @param {string} path
|
|
471
490
|
* @returns {any}
|
|
472
491
|
*/
|
|
473
492
|
function resolvePath(obj, path) {
|
|
474
493
|
const parts = path.split(/[/.]/);
|
|
475
|
-
let current = obj;
|
|
494
|
+
let current = /** @type {JxMutableNode} */ (obj);
|
|
476
495
|
for (const part of parts) {
|
|
477
496
|
if (current == null) return undefined;
|
|
478
497
|
current = current[part];
|
|
@@ -484,8 +503,8 @@ function resolvePath(obj, path) {
|
|
|
484
503
|
* Resolve a $ref string against a scope.
|
|
485
504
|
*
|
|
486
505
|
* @param {string} ref
|
|
487
|
-
* @param {
|
|
488
|
-
* @returns {
|
|
506
|
+
* @param {Record<string, unknown>} scope
|
|
507
|
+
* @returns {unknown}
|
|
489
508
|
*/
|
|
490
509
|
function resolveRef(ref, scope) {
|
|
491
510
|
if (ref.startsWith("#/state/")) {
|
|
@@ -499,10 +518,10 @@ function resolveRef(ref, scope) {
|
|
|
499
518
|
/**
|
|
500
519
|
* Convert a table element to mdast table node.
|
|
501
520
|
*
|
|
502
|
-
* @param {
|
|
503
|
-
* @param {Map<string,
|
|
504
|
-
* @param {
|
|
505
|
-
* @returns {
|
|
521
|
+
* @param {JxElement} node
|
|
522
|
+
* @param {Map<string, JxElement>} componentDefs
|
|
523
|
+
* @param {Record<string, unknown> | null} [scope]
|
|
524
|
+
* @returns {MdastNode[]}
|
|
506
525
|
*/
|
|
507
526
|
function convertTable(node, componentDefs, scope) {
|
|
508
527
|
// Flatten thead/tbody wrappers to get rows
|
|
@@ -516,8 +535,8 @@ function convertTable(node, componentDefs, scope) {
|
|
|
516
535
|
/**
|
|
517
536
|
* Resolve text content, handling template strings if a scope is available.
|
|
518
537
|
*
|
|
519
|
-
* @param {
|
|
520
|
-
* @param {
|
|
538
|
+
* @param {unknown} value
|
|
539
|
+
* @param {Record<string, unknown> | null} [scope]
|
|
521
540
|
* @returns {string | null}
|
|
522
541
|
*/
|
|
523
542
|
function resolveText(value, scope) {
|
|
@@ -539,10 +558,10 @@ function resolveText(value, scope) {
|
|
|
539
558
|
* markdown content.
|
|
540
559
|
*
|
|
541
560
|
* @param {string} html
|
|
542
|
-
* @returns {
|
|
561
|
+
* @returns {MdastNode[]}
|
|
543
562
|
*/
|
|
544
563
|
function htmlToMdast(html) {
|
|
545
|
-
/** @type {
|
|
564
|
+
/** @type {MdastNode[]} */
|
|
546
565
|
const nodes = [];
|
|
547
566
|
|
|
548
567
|
// Simple top-level block parser
|
|
@@ -594,7 +613,7 @@ function splitHtmlBlocks(html) {
|
|
|
594
613
|
* Parse a single HTML element string into mdast node(s).
|
|
595
614
|
*
|
|
596
615
|
* @param {string} html
|
|
597
|
-
* @returns {
|
|
616
|
+
* @returns {MdastNode[] | null}
|
|
598
617
|
*/
|
|
599
618
|
function parseHtmlElement(html) {
|
|
600
619
|
// Heading
|
|
@@ -679,10 +698,10 @@ function parseHtmlElement(html) {
|
|
|
679
698
|
* Parse inline HTML content to mdast inline nodes.
|
|
680
699
|
*
|
|
681
700
|
* @param {string} html
|
|
682
|
-
* @returns {
|
|
701
|
+
* @returns {MdastNode[]}
|
|
683
702
|
*/
|
|
684
703
|
function parseInlineHtml(html) {
|
|
685
|
-
/** @type {
|
|
704
|
+
/** @type {MdastNode[]} */
|
|
686
705
|
const nodes = [];
|
|
687
706
|
let pos = 0;
|
|
688
707
|
|
|
@@ -813,10 +832,10 @@ function findMatchingClose(html, start, tag) {
|
|
|
813
832
|
* Parse <li> elements from list HTML.
|
|
814
833
|
*
|
|
815
834
|
* @param {string} html
|
|
816
|
-
* @returns {
|
|
835
|
+
* @returns {MdastNode[]}
|
|
817
836
|
*/
|
|
818
837
|
function parseListItems(html) {
|
|
819
|
-
/** @type {
|
|
838
|
+
/** @type {MdastNode[]} */
|
|
820
839
|
const items = [];
|
|
821
840
|
const liPattern = /<li(?:\s[^>]*)?>([\s\S]*?)<\/li>/gi;
|
|
822
841
|
let m;
|
|
@@ -835,16 +854,16 @@ function parseListItems(html) {
|
|
|
835
854
|
* Parse an HTML table to mdast table node.
|
|
836
855
|
*
|
|
837
856
|
* @param {string} html
|
|
838
|
-
* @returns {
|
|
857
|
+
* @returns {MdastNode[]}
|
|
839
858
|
*/
|
|
840
859
|
function parseHtmlTable(html) {
|
|
841
|
-
/** @type {
|
|
860
|
+
/** @type {MdastNode[]} */
|
|
842
861
|
const rows = [];
|
|
843
862
|
const trPattern = /<tr(?:\s[^>]*)?>([\s\S]*?)<\/tr>/gi;
|
|
844
863
|
let m;
|
|
845
864
|
while ((m = trPattern.exec(html)) !== null) {
|
|
846
865
|
const cellPattern = /<(?:th|td)(?:\s[^>]*)?>([\s\S]*?)<\/(?:th|td)>/gi;
|
|
847
|
-
/** @type {
|
|
866
|
+
/** @type {MdastNode[]} */
|
|
848
867
|
const cells = [];
|
|
849
868
|
let c;
|
|
850
869
|
while ((c = cellPattern.exec(m[1])) !== null) {
|
|
@@ -888,8 +907,8 @@ function decodeHtmlEntities(str) {
|
|
|
888
907
|
/**
|
|
889
908
|
* Compile a fully-resolved Jx document to clean markdown.
|
|
890
909
|
*
|
|
891
|
-
* @param {
|
|
892
|
-
* @param {Map<string,
|
|
910
|
+
* @param {JxDocument} doc - Resolved Jx document (post layout, context, prototypes, templates)
|
|
911
|
+
* @param {Map<string, JxElement>} [componentDefs] - Component definitions for inlining
|
|
893
912
|
* @returns {{ content: string }}
|
|
894
913
|
*/
|
|
895
914
|
export function compileMarkdown(doc, componentDefs = new Map()) {
|
|
@@ -901,14 +920,14 @@ export function compileMarkdown(doc, componentDefs = new Map()) {
|
|
|
901
920
|
const scope = doc.state ? buildInitialScope(doc.state, null) : null;
|
|
902
921
|
|
|
903
922
|
// Convert to mdast
|
|
904
|
-
const mdastChildren = doc.children.flatMap((/** @type {
|
|
923
|
+
const mdastChildren = doc.children.flatMap((/** @type {JxElement | string} */ child) =>
|
|
905
924
|
nodeToMdast(child, componentDefs, scope),
|
|
906
925
|
);
|
|
907
926
|
|
|
908
927
|
// Clean up: ensure block-level structure (no bare inline nodes at root)
|
|
909
|
-
/** @type {
|
|
928
|
+
/** @type {MdastNode[]} */
|
|
910
929
|
const cleaned = [];
|
|
911
|
-
/** @type {
|
|
930
|
+
/** @type {MdastNode[]} */
|
|
912
931
|
let inlineBuf = [];
|
|
913
932
|
|
|
914
933
|
const flushInline = () => {
|
|
@@ -928,7 +947,9 @@ export function compileMarkdown(doc, componentDefs = new Map()) {
|
|
|
928
947
|
}
|
|
929
948
|
flushInline();
|
|
930
949
|
|
|
931
|
-
const mdast = /** @type {
|
|
950
|
+
const mdast = /** @type {import("mdast").Root} */ (
|
|
951
|
+
/** @type {unknown} */ ({ type: "root", children: cleaned })
|
|
952
|
+
);
|
|
932
953
|
|
|
933
954
|
const md = unified()
|
|
934
955
|
.use(remarkGfm)
|
|
@@ -24,7 +24,7 @@ import { collectServerEntries } from "../shared.js";
|
|
|
24
24
|
*/
|
|
25
25
|
export async function compileServer(sourcePath, opts = {}) {
|
|
26
26
|
const { baseUrl = "/_jx/server" } = opts;
|
|
27
|
-
const doc = await $RefParser.dereference(sourcePath);
|
|
27
|
+
const doc = /** @type {JxElement} */ (await $RefParser.dereference(sourcePath));
|
|
28
28
|
const entries = collectServerEntries(doc);
|
|
29
29
|
if (entries.length === 0) return null;
|
|
30
30
|
|
|
@@ -18,15 +18,20 @@ import { emitElementModule } from "./compile-element.js";
|
|
|
18
18
|
/**
|
|
19
19
|
* Compile a static document to HTML, with dynamic subtrees as islands.
|
|
20
20
|
*
|
|
21
|
-
* @param {any} raw - Raw JSON document (with $ref pointers
|
|
22
|
-
*
|
|
21
|
+
* @param {JxMutableNode | Record<string, any>} raw - Raw JSON document (with $ref pointers
|
|
22
|
+
* preserved)
|
|
23
|
+
* @param {Record<string, unknown>} opts
|
|
23
24
|
* @returns {{ html: string; files: { path: string; content: string; tagName: string }[] }}
|
|
24
25
|
*/
|
|
25
26
|
export function compileStaticPage(raw, opts) {
|
|
26
|
-
const { title, reactivitySrc, litHtmlSrc } = opts;
|
|
27
|
+
const { title, reactivitySrc, litHtmlSrc } = /** @type {JxMutableNode} */ (opts);
|
|
27
28
|
|
|
28
29
|
const rootContext = createCompileContext(raw, null, raw.state ?? {}, raw.$media ?? {});
|
|
29
|
-
const styleBlock = compileStyles(
|
|
30
|
+
const styleBlock = compileStyles(
|
|
31
|
+
raw,
|
|
32
|
+
raw.$media ?? {},
|
|
33
|
+
/** @type {JxStyle | null} */ (opts.projectStyle ?? null),
|
|
34
|
+
);
|
|
30
35
|
/** @type {{ def: any; tagName: string; className: string }[]} */
|
|
31
36
|
const islands = [];
|
|
32
37
|
const bodyContent = compileNode(raw, false, raw, rootContext, islands);
|
|
@@ -83,9 +88,9 @@ export function compileStaticPage(raw, opts) {
|
|
|
83
88
|
* Compile a single Jx node to an HTML string. Dynamic nodes become hydration islands; static nodes
|
|
84
89
|
* become plain HTML.
|
|
85
90
|
*
|
|
86
|
-
* @param {
|
|
91
|
+
* @param {JxMutableNode} def
|
|
87
92
|
* @param {boolean} dynamic
|
|
88
|
-
* @param {
|
|
93
|
+
* @param {JxMutableNode} raw
|
|
89
94
|
* @param {any} context
|
|
90
95
|
* @param {{ def: any; tagName: string; className: string }[]} islands
|
|
91
96
|
* @returns {string}
|
|
@@ -127,8 +132,8 @@ function compileNode(def, dynamic, raw, context, islands) {
|
|
|
127
132
|
* Build the inner HTML (textContent or children) for a node. For children, emit islands only for
|
|
128
133
|
* those that are actually dynamic.
|
|
129
134
|
*
|
|
130
|
-
* @param {
|
|
131
|
-
* @param {
|
|
135
|
+
* @param {JxMutableNode} def
|
|
136
|
+
* @param {JxMutableNode} raw
|
|
132
137
|
* @param {any} context
|
|
133
138
|
* @param {{ def: any; tagName: string; className: string }[]} islands
|
|
134
139
|
* @returns {string}
|
|
@@ -141,14 +146,20 @@ function buildInnerWithIslands(def, raw, context, islands) {
|
|
|
141
146
|
return value == null ? "" : escapeHtml(String(value));
|
|
142
147
|
}
|
|
143
148
|
if (source.innerHTML)
|
|
144
|
-
return
|
|
149
|
+
return (
|
|
150
|
+
/** @type {string} */ (resolveStaticValue(source.innerHTML, context.scope)) ??
|
|
151
|
+
source.innerHTML
|
|
152
|
+
);
|
|
145
153
|
if (Array.isArray(source.children)) {
|
|
146
154
|
const rawChildren = raw?.children;
|
|
147
155
|
return source.children
|
|
148
|
-
.map((
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
156
|
+
.map((c, /** @type {number} */ i) => {
|
|
157
|
+
const child = /** @type {JxMutableNode} */ (/** @type {unknown} */ (c));
|
|
158
|
+
const childDynamic = isNodeDynamic(child);
|
|
159
|
+
const childRaw = /** @type {JxMutableNode} */ (
|
|
160
|
+
/** @type {unknown} */ (rawChildren?.[i] ?? c)
|
|
161
|
+
);
|
|
162
|
+
return compileNode(child, childDynamic, childRaw, context, islands);
|
|
152
163
|
})
|
|
153
164
|
.join("\n ");
|
|
154
165
|
}
|