@jxsuite/compiler 0.23.2 → 0.25.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.
@@ -9,12 +9,19 @@
9
9
  import { unified } from "unified";
10
10
  import remarkStringify from "remark-stringify";
11
11
  import remarkGfm from "remark-gfm";
12
- import { buildInitialScope, evaluateStaticTemplate, isTemplateString } from "../shared.js";
12
+ import { buildInitialScope, evaluateStaticTemplate, isTemplateString } from "../shared.ts";
13
+ import type {
14
+ JxElement,
15
+ JxDocument,
16
+ JxStateDefinition,
17
+ JxMutableNode,
18
+ } from "@jxsuite/schema/types";
19
+ import type { MdastNode } from "@jxsuite/parser/types";
13
20
 
14
21
  // ─── Tag classification ────────────────────────────────────────────────────
15
22
 
16
23
  /** Tags that map directly to mdast node types. */
17
- const TAG_MDAST_MAP = /** @type {Record<string, string>} */ ({
24
+ const TAG_MDAST_MAP = {
18
25
  h1: "heading",
19
26
  h2: "heading",
20
27
  h3: "heading",
@@ -41,7 +48,7 @@ const TAG_MDAST_MAP = /** @type {Record<string, string>} */ ({
41
48
  tr: "tableRow",
42
49
  th: "tableCell",
43
50
  td: "tableCell",
44
- });
51
+ } as Record<string, string>;
45
52
 
46
53
  /** Wrapper tags that should be unwrapped — their children are promoted. */
47
54
  const WRAPPER_TAGS = new Set([
@@ -70,7 +77,11 @@ const WRAPPER_TAGS = new Set([
70
77
  * @param {Record<string, unknown> | null} [scope] - Current resolution scope
71
78
  * @returns {MdastNode[]}
72
79
  */
73
- function nodeToMdast(node, componentDefs, scope) {
80
+ function nodeToMdast(
81
+ node: JxElement | string,
82
+ componentDefs: Map<string, JxElement>,
83
+ scope?: Record<string, unknown> | null,
84
+ ): MdastNode[] {
74
85
  // Bare text
75
86
  if (typeof node === "string") {
76
87
  return node.trim() ? [{ type: "text", value: node }] : [];
@@ -154,7 +165,7 @@ function nodeToMdast(node, componentDefs, scope) {
154
165
 
155
166
  case "link": {
156
167
  const href = String(node.attributes?.href ?? "");
157
- const title = /** @type {string | null} */ (node.attributes?.title ?? null);
168
+ const title = (node.attributes?.title as string | null) ?? null;
158
169
  const children =
159
170
  text != null
160
171
  ? [{ type: "text", value: text }]
@@ -165,7 +176,7 @@ function nodeToMdast(node, componentDefs, scope) {
165
176
  case "image": {
166
177
  const src = String(node.attributes?.src ?? "");
167
178
  const alt = String(node.attributes?.alt ?? "");
168
- const title = /** @type {string | null} */ (node.attributes?.title ?? null);
179
+ const title = (node.attributes?.title as string | null) ?? null;
169
180
  return [{ type: "image", url: src, alt, title }];
170
181
  }
171
182
 
@@ -199,16 +210,11 @@ function nodeToMdast(node, componentDefs, scope) {
199
210
  case "code": {
200
211
  // pre > code → fenced code block
201
212
  const codeChild = Array.isArray(node.children)
202
- ? node.children.find(
203
- (/** @type {JxElement | string} */ c) =>
204
- /** @type {JxMutableNode} */ (c)?.tagName === "code",
205
- )
213
+ ? node.children.find((c: JxElement | string) => (c as JxMutableNode)?.tagName === "code")
206
214
  : null;
207
- const value = /** @type {JxElement | undefined} */ (codeChild)?.textContent ?? text ?? "";
208
- const lang = /** @type {JxElement | undefined} */ (codeChild)?.className?.replace(
209
- "language-",
210
- "",
211
- ) ?? null;
215
+ const value = (codeChild as JxElement | undefined)?.textContent ?? text ?? "";
216
+ const lang =
217
+ (codeChild as JxElement | undefined)?.className?.replace("language-", "") ?? null;
212
218
  return [{ type: "code", lang, value }];
213
219
  }
214
220
 
@@ -247,7 +253,7 @@ function nodeToMdast(node, componentDefs, scope) {
247
253
  * @param {string} type
248
254
  * @returns {boolean}
249
255
  */
250
- function isInlineType(type) {
256
+ function isInlineType(type: string) {
251
257
  return ["text", "emphasis", "strong", "delete", "inlineCode", "link", "image", "break"].includes(
252
258
  type,
253
259
  );
@@ -261,16 +267,18 @@ function isInlineType(type) {
261
267
  * @param {Record<string, unknown> | null} [scope]
262
268
  * @returns {MdastNode[]}
263
269
  */
264
- function convertChildren(node, componentDefs, scope) {
270
+ function convertChildren(
271
+ node: JxElement,
272
+ componentDefs: Map<string, JxElement>,
273
+ scope?: Record<string, unknown> | null,
274
+ ): MdastNode[] {
265
275
  if (node.textContent != null) {
266
276
  const text = resolveText(node.textContent, scope);
267
277
  if (text) return [{ type: "text", value: text }];
268
278
  return [];
269
279
  }
270
280
  if (!Array.isArray(node.children)) return [];
271
- return node.children.flatMap((/** @type {JxElement | string} */ c) =>
272
- nodeToMdast(c, componentDefs, scope),
273
- );
281
+ return node.children.flatMap((c: JxElement | string) => nodeToMdast(c, componentDefs, scope));
274
282
  }
275
283
 
276
284
  /**
@@ -281,16 +289,18 @@ function convertChildren(node, componentDefs, scope) {
281
289
  * @param {Record<string, unknown> | null} [scope]
282
290
  * @returns {MdastNode[]}
283
291
  */
284
- function convertChildrenInline(node, componentDefs, scope) {
292
+ function convertChildrenInline(
293
+ node: JxElement,
294
+ componentDefs: Map<string, JxElement>,
295
+ scope?: Record<string, unknown> | null,
296
+ ): MdastNode[] {
285
297
  if (node.textContent != null) {
286
298
  const text = resolveText(node.textContent, scope);
287
299
  if (text) return [{ type: "text", value: text }];
288
300
  return [];
289
301
  }
290
302
  if (!Array.isArray(node.children)) return [];
291
- return node.children.flatMap((/** @type {JxElement | string} */ c) =>
292
- nodeToMdast(c, componentDefs, scope),
293
- );
303
+ return node.children.flatMap((c: JxElement | string) => nodeToMdast(c, componentDefs, scope));
294
304
  }
295
305
 
296
306
  // ─── Component inlining ─────────────────────────────────────────────────────
@@ -303,7 +313,11 @@ function convertChildrenInline(node, componentDefs, scope) {
303
313
  * @param {Map<string, JxElement>} componentDefs
304
314
  * @returns {MdastNode[]}
305
315
  */
306
- function inlineComponent(node, tag, componentDefs) {
316
+ function inlineComponent(
317
+ node: JxElement,
318
+ tag: string,
319
+ componentDefs: Map<string, JxElement>,
320
+ ): MdastNode[] {
307
321
  const def = componentDefs.get(tag);
308
322
  if (!def) {
309
323
  // No definition — unwrap any children the instance has
@@ -324,10 +338,10 @@ function inlineComponent(node, tag, componentDefs) {
324
338
  ) {
325
339
  stateDefs[key] = { ...existing, default: value };
326
340
  } else {
327
- stateDefs[key] = /** @type {JxStateDefinition} */ (value);
341
+ stateDefs[key] = value as JxStateDefinition;
328
342
  }
329
343
  } else {
330
- stateDefs[key] = /** @type {JxStateDefinition} */ (value);
344
+ stateDefs[key] = value as JxStateDefinition;
331
345
  }
332
346
  }
333
347
 
@@ -341,13 +355,10 @@ function inlineComponent(node, tag, componentDefs) {
341
355
 
342
356
  // Convert to mdast, passing instance's own children as potential slot content
343
357
  const instanceChildren = node.children;
344
- return resolved.flatMap((/** @type {JxElement | string} */ child) => {
358
+ return resolved.flatMap((child: JxElement | string): MdastNode[] => {
345
359
  // Replace slot elements with instance children
346
- if (
347
- /** @type {JxMutableNode} */ (child)?.tagName === "slot" &&
348
- Array.isArray(instanceChildren)
349
- ) {
350
- return instanceChildren.flatMap((/** @type {JxElement | string} */ c) =>
360
+ if (typeof child !== "string" && child?.tagName === "slot" && Array.isArray(instanceChildren)) {
361
+ return instanceChildren.flatMap((c: JxElement | string): MdastNode[] =>
351
362
  nodeToMdast(c, componentDefs),
352
363
  );
353
364
  }
@@ -362,9 +373,9 @@ function inlineComponent(node, tag, componentDefs) {
362
373
  * @param {Record<string, unknown>} scope
363
374
  * @returns {(JxElement | string)[]}
364
375
  */
365
- function deepResolve(nodes, scope) {
376
+ function deepResolve(nodes: (JxElement | string)[], scope: Record<string, unknown>) {
366
377
  if (!Array.isArray(nodes)) return [];
367
- return nodes.map((/** @type {JxElement | string} */ node) => resolveNode(node, scope));
378
+ return nodes.map((node: JxElement | string) => resolveNode(node, scope));
368
379
  }
369
380
 
370
381
  /**
@@ -374,7 +385,7 @@ function deepResolve(nodes, scope) {
374
385
  * @param {Record<string, unknown>} scope
375
386
  * @returns {JxElement | string}
376
387
  */
377
- function resolveNode(node, scope) {
388
+ function resolveNode(node: JxElement | string, scope: Record<string, unknown>) {
378
389
  if (typeof node === "string") {
379
390
  return isTemplateString(node) ? String(evaluateStaticTemplate(node, scope) ?? node) : node;
380
391
  }
@@ -415,18 +426,22 @@ function resolveNode(node, scope) {
415
426
  * @param {Record<string, unknown> | null} [scope]
416
427
  * @returns {MdastNode[]}
417
428
  */
418
- function expandArray(arrayDef, componentDefs, scope) {
419
- const itemsRef = /** @type {JxMutableNode} */ (arrayDef).items?.$ref;
429
+ function expandArray(
430
+ arrayDef: JxElement,
431
+ componentDefs: Map<string, JxElement>,
432
+ scope?: Record<string, unknown> | null,
433
+ ): MdastNode[] {
434
+ const itemsRef = (arrayDef as JxMutableNode).items?.$ref;
420
435
  if (!itemsRef || !scope) return [];
421
436
 
422
437
  // Resolve the items array from scope
423
438
  const items = resolveRef(itemsRef, scope);
424
439
  if (!Array.isArray(items)) return [];
425
440
 
426
- const mapTemplate = /** @type {JxMutableNode} */ (arrayDef).map;
441
+ const mapTemplate = (arrayDef as JxMutableNode).map;
427
442
  if (!mapTemplate) return [];
428
443
 
429
- return items.flatMap((/** @type {JxMutableNode} */ item, /** @type {number} */ index) => {
444
+ return items.flatMap((item: JxMutableNode, index: number): MdastNode[] => {
430
445
  // Create a scope with $map values
431
446
  const mapScope = Object.create(scope);
432
447
  mapScope.item = item;
@@ -434,7 +449,7 @@ function expandArray(arrayDef, componentDefs, scope) {
434
449
 
435
450
  // Resolve the map template with $map refs
436
451
  const resolved = resolveMapNode(mapTemplate, item);
437
- return nodeToMdast(resolved, componentDefs, scope);
452
+ return nodeToMdast(resolved as JxElement | string, componentDefs, scope);
438
453
  });
439
454
  }
440
455
 
@@ -445,7 +460,7 @@ function expandArray(arrayDef, componentDefs, scope) {
445
460
  * @param {Record<string, unknown>} item
446
461
  * @returns {any}
447
462
  */
448
- function resolveMapNode(node, item) {
463
+ function resolveMapNode(node: JxMutableNode, item: Record<string, unknown>) {
449
464
  if (typeof node === "string") return node;
450
465
  if (!node || typeof node !== "object") return node;
451
466
 
@@ -453,8 +468,8 @@ function resolveMapNode(node, item) {
453
468
 
454
469
  // Resolve $ref values
455
470
  for (const [key, value] of Object.entries(result)) {
456
- if (value && typeof value === "object" && /** @type {JxMutableNode} */ (value).$ref) {
457
- const ref = /** @type {string} */ (/** @type {JxMutableNode} */ (value).$ref);
471
+ if (value && typeof value === "object" && (value as JxMutableNode).$ref) {
472
+ const ref = (value as JxMutableNode).$ref as string;
458
473
  if (ref.startsWith("$map/")) {
459
474
  const path = ref.slice("$map/".length);
460
475
  result[key] = resolvePath(
@@ -470,12 +485,14 @@ function resolveMapNode(node, item) {
470
485
  }
471
486
 
472
487
  if (typeof result.textContent === "string" && result.textContent.startsWith("$map/")) {
473
- result.textContent = resolvePath(item, result.textContent.slice("$map/".length));
488
+ result.textContent = resolvePath(item, result.textContent.slice("$map/".length)) as unknown as
489
+ | string
490
+ | null;
474
491
  }
475
492
 
476
493
  if (Array.isArray(result.children)) {
477
494
  result.children = result.children.map((c) =>
478
- resolveMapNode(/** @type {JxMutableNode} */ (/** @type {unknown} */ (c)), item),
495
+ resolveMapNode(c as unknown as JxMutableNode, item),
479
496
  );
480
497
  }
481
498
 
@@ -489,9 +506,9 @@ function resolveMapNode(node, item) {
489
506
  * @param {string} path
490
507
  * @returns {any}
491
508
  */
492
- function resolvePath(obj, path) {
509
+ function resolvePath(obj: unknown, path: string) {
493
510
  const parts = path.split(/[/.]/);
494
- let current = /** @type {JxMutableNode} */ (obj);
511
+ let current = obj as JxMutableNode;
495
512
  for (const part of parts) {
496
513
  if (current == null) return undefined;
497
514
  current = current[part];
@@ -506,7 +523,7 @@ function resolvePath(obj, path) {
506
523
  * @param {Record<string, unknown>} scope
507
524
  * @returns {unknown}
508
525
  */
509
- function resolveRef(ref, scope) {
526
+ function resolveRef(ref: string, scope: Record<string, unknown>) {
510
527
  if (ref.startsWith("#/state/")) {
511
528
  return resolvePath(scope, ref.slice("#/state/".length));
512
529
  }
@@ -523,7 +540,11 @@ function resolveRef(ref, scope) {
523
540
  * @param {Record<string, unknown> | null} [scope]
524
541
  * @returns {MdastNode[]}
525
542
  */
526
- function convertTable(node, componentDefs, scope) {
543
+ function convertTable(
544
+ node: JxElement,
545
+ componentDefs: Map<string, JxElement>,
546
+ scope?: Record<string, unknown> | null,
547
+ ) {
527
548
  // Flatten thead/tbody wrappers to get rows
528
549
  const rows = convertChildren(node, componentDefs, scope).filter((c) => c.type === "tableRow");
529
550
  if (rows.length === 0) return [];
@@ -539,7 +560,7 @@ function convertTable(node, componentDefs, scope) {
539
560
  * @param {Record<string, unknown> | null} [scope]
540
561
  * @returns {string | null}
541
562
  */
542
- function resolveText(value, scope) {
563
+ function resolveText(value: unknown, scope?: Record<string, unknown> | null) {
543
564
  if (value == null) return null;
544
565
  if (typeof value === "string") {
545
566
  if (scope && isTemplateString(value)) {
@@ -560,9 +581,8 @@ function resolveText(value, scope) {
560
581
  * @param {string} html
561
582
  * @returns {MdastNode[]}
562
583
  */
563
- function htmlToMdast(html) {
564
- /** @type {MdastNode[]} */
565
- const nodes = [];
584
+ function htmlToMdast(html: string) {
585
+ const nodes: MdastNode[] = [];
566
586
 
567
587
  // Simple top-level block parser
568
588
  const parts = splitHtmlBlocks(html);
@@ -582,9 +602,8 @@ function htmlToMdast(html) {
582
602
  * @param {string} html
583
603
  * @returns {string[]}
584
604
  */
585
- function splitHtmlBlocks(html) {
586
- /** @type {string[]} */
587
- const blocks = [];
605
+ function splitHtmlBlocks(html: string) {
606
+ const blocks: string[] = [];
588
607
  const trimmed = html.trim();
589
608
 
590
609
  // Simple regex: split on top-level block boundaries
@@ -615,7 +634,7 @@ function splitHtmlBlocks(html) {
615
634
  * @param {string} html
616
635
  * @returns {MdastNode[] | null}
617
636
  */
618
- function parseHtmlElement(html) {
637
+ function parseHtmlElement(html: string) {
619
638
  // Heading
620
639
  const hMatch = html.match(/^<(h[1-6])(?:\s[^>]*)?>(.+?)<\/\1>$/is);
621
640
  if (hMatch) {
@@ -700,9 +719,8 @@ function parseHtmlElement(html) {
700
719
  * @param {string} html
701
720
  * @returns {MdastNode[]}
702
721
  */
703
- function parseInlineHtml(html) {
704
- /** @type {MdastNode[]} */
705
- const nodes = [];
722
+ function parseInlineHtml(html: string) {
723
+ const nodes: MdastNode[] = [];
706
724
  let pos = 0;
707
725
 
708
726
  while (pos < html.length) {
@@ -803,7 +821,7 @@ function parseInlineHtml(html) {
803
821
  * @param {string} tag - Tag name to match
804
822
  * @returns {number} Position of the matching closing tag, or -1
805
823
  */
806
- function findMatchingClose(html, start, tag) {
824
+ function findMatchingClose(html: string, start: number, tag: string) {
807
825
  let depth = 1;
808
826
  const openRe = new RegExp(`<${tag}[\\s>]`, "gi");
809
827
  const closeRe = new RegExp(`</${tag}>`, "gi");
@@ -834,9 +852,8 @@ function findMatchingClose(html, start, tag) {
834
852
  * @param {string} html
835
853
  * @returns {MdastNode[]}
836
854
  */
837
- function parseListItems(html) {
838
- /** @type {MdastNode[]} */
839
- const items = [];
855
+ function parseListItems(html: string) {
856
+ const items: MdastNode[] = [];
840
857
  const liPattern = /<li(?:\s[^>]*)?>([\s\S]*?)<\/li>/gi;
841
858
  let m;
842
859
  while ((m = liPattern.exec(html)) !== null) {
@@ -856,15 +873,13 @@ function parseListItems(html) {
856
873
  * @param {string} html
857
874
  * @returns {MdastNode[]}
858
875
  */
859
- function parseHtmlTable(html) {
860
- /** @type {MdastNode[]} */
861
- const rows = [];
876
+ function parseHtmlTable(html: string) {
877
+ const rows: MdastNode[] = [];
862
878
  const trPattern = /<tr(?:\s[^>]*)?>([\s\S]*?)<\/tr>/gi;
863
879
  let m;
864
880
  while ((m = trPattern.exec(html)) !== null) {
865
881
  const cellPattern = /<(?:th|td)(?:\s[^>]*)?>([\s\S]*?)<\/(?:th|td)>/gi;
866
- /** @type {MdastNode[]} */
867
- const cells = [];
882
+ const cells: MdastNode[] = [];
868
883
  let c;
869
884
  while ((c = cellPattern.exec(m[1])) !== null) {
870
885
  cells.push({ type: "tableCell", children: parseInlineHtml(c[1]) });
@@ -881,7 +896,7 @@ function parseHtmlTable(html) {
881
896
  * @param {string} html
882
897
  * @returns {string}
883
898
  */
884
- function stripHtmlTags(html) {
899
+ function stripHtmlTags(html: string) {
885
900
  return html.replace(/<[^>]+>/g, "");
886
901
  }
887
902
 
@@ -891,7 +906,7 @@ function stripHtmlTags(html) {
891
906
  * @param {string} str
892
907
  * @returns {string}
893
908
  */
894
- function decodeHtmlEntities(str) {
909
+ function decodeHtmlEntities(str: string) {
895
910
  return str
896
911
  .replace(/&amp;/g, "&")
897
912
  .replace(/&lt;/g, "<")
@@ -911,7 +926,10 @@ function decodeHtmlEntities(str) {
911
926
  * @param {Map<string, JxElement>} [componentDefs] - Component definitions for inlining
912
927
  * @returns {{ content: string }}
913
928
  */
914
- export function compileMarkdown(doc, componentDefs = new Map()) {
929
+ export function compileMarkdown(
930
+ doc: JxDocument,
931
+ componentDefs: Map<string, JxElement> = new Map(),
932
+ ) {
915
933
  if (!Array.isArray(doc.children) || doc.children.length === 0) {
916
934
  return { content: "" };
917
935
  }
@@ -920,15 +938,13 @@ export function compileMarkdown(doc, componentDefs = new Map()) {
920
938
  const scope = doc.state ? buildInitialScope(doc.state, null) : null;
921
939
 
922
940
  // Convert to mdast
923
- const mdastChildren = doc.children.flatMap((/** @type {JxElement | string} */ child) =>
941
+ const mdastChildren = doc.children.flatMap((child: JxElement | string) =>
924
942
  nodeToMdast(child, componentDefs, scope),
925
943
  );
926
944
 
927
945
  // Clean up: ensure block-level structure (no bare inline nodes at root)
928
- /** @type {MdastNode[]} */
929
- const cleaned = [];
930
- /** @type {MdastNode[]} */
931
- let inlineBuf = [];
946
+ const cleaned: MdastNode[] = [];
947
+ let inlineBuf: MdastNode[] = [];
932
948
 
933
949
  const flushInline = () => {
934
950
  if (inlineBuf.length > 0) {
@@ -947,9 +963,7 @@ export function compileMarkdown(doc, componentDefs = new Map()) {
947
963
  }
948
964
  flushInline();
949
965
 
950
- const mdast = /** @type {import("mdast").Root} */ (
951
- /** @type {unknown} */ ({ type: "root", children: cleaned })
952
- );
966
+ const mdast = { type: "root", children: cleaned } as unknown as import("mdast").Root;
953
967
 
954
968
  const md = unified()
955
969
  .use(remarkGfm)
@@ -6,7 +6,8 @@
6
6
  */
7
7
 
8
8
  import $RefParser from "@apidevtools/json-schema-ref-parser";
9
- import { collectServerEntries } from "../shared.js";
9
+ import { collectServerEntries } from "../shared.ts";
10
+ import type { JxElement } from "@jxsuite/schema/types";
10
11
 
11
12
  /**
12
13
  * Compile a Jx document to a Hono server handler file. The handler exposes each `timing: "server"`
@@ -22,9 +23,14 @@ import { collectServerEntries } from "../shared.js";
22
23
  * @param {string} [opts.baseUrl] - Base path for server endpoints. Default is `'/_jx/server'`
23
24
  * @returns {Promise<string | null>} Hono server handler source string, or null
24
25
  */
25
- export async function compileServer(sourcePath, opts = {}) {
26
+ export async function compileServer(
27
+ sourcePath: string | object,
28
+ opts: {
29
+ baseUrl?: string;
30
+ } = {},
31
+ ) {
26
32
  const { baseUrl = "/_jx/server" } = opts;
27
- const doc = /** @type {JxElement} */ (await $RefParser.dereference(sourcePath));
33
+ const doc = (await $RefParser.dereference(sourcePath)) as JxElement;
28
34
  const entries = collectServerEntries(doc);
29
35
  if (entries.length === 0) return null;
30
36
 
@@ -58,7 +64,13 @@ export default app
58
64
  * @param {string | null} [opts.adapter] - Deployment adapter: `"cloudflare"`, `"node"`, `"bun"`
59
65
  * @returns {string | null} Complete worker/server source string, or null
60
66
  */
61
- export function compileSiteServer(entries, opts = {}) {
67
+ export function compileSiteServer(
68
+ entries: { exportName: string; src: string }[],
69
+ opts: {
70
+ baseUrl?: string;
71
+ adapter?: string | null;
72
+ } = {},
73
+ ) {
62
74
  const { baseUrl = "/_jx/server", adapter = null } = opts;
63
75
  if (entries.length === 0 && !adapter) return null;
64
76
 
@@ -85,7 +97,7 @@ export default app
85
97
  }
86
98
 
87
99
  /** @param {string} exportName @param {string} baseUrl */
88
- function buildRoute(exportName, baseUrl) {
100
+ function buildRoute(exportName: string, baseUrl: string) {
89
101
  return `
90
102
  app.post('${baseUrl}/${exportName}', async (c) => {
91
103
  const args = await c.req.json().catch(() => ({}))
@@ -107,7 +119,12 @@ app.post('${baseUrl}/${exportName}', async (c) => {
107
119
  * @returns {Map<string, string>} Map of output path → source (e.g.
108
120
  * `"functions/_jx/server/sendEmail.js"` → source)
109
121
  */
110
- export function compilePagesFunctions(entries, opts = {}) {
122
+ export function compilePagesFunctions(
123
+ entries: { exportName: string; src: string }[],
124
+ opts: {
125
+ baseUrl?: string;
126
+ } = {},
127
+ ) {
111
128
  const { baseUrl = "/_jx/server" } = opts;
112
129
  const files = new Map();
113
130
 
@@ -12,8 +12,9 @@ import {
12
12
  buildAttrs,
13
13
  compileStyles,
14
14
  escapeHtml,
15
- } from "../shared.js";
16
- import { emitElementModule } from "./compile-element.js";
15
+ } from "../shared.ts";
16
+ import { emitElementModule } from "./compile-element.ts";
17
+ import type { JxStyle, JxMutableNode } from "@jxsuite/schema/types";
17
18
 
18
19
  /**
19
20
  * Compile a static document to HTML, with dynamic subtrees as islands.
@@ -23,17 +24,19 @@ import { emitElementModule } from "./compile-element.js";
23
24
  * @param {Record<string, unknown>} opts
24
25
  * @returns {{ html: string; files: { path: string; content: string; tagName: string }[] }}
25
26
  */
26
- export function compileStaticPage(raw, opts) {
27
- const { title, reactivitySrc, litHtmlSrc } = /** @type {JxMutableNode} */ (opts);
27
+ export function compileStaticPage(
28
+ raw: JxMutableNode | Record<string, any>,
29
+ opts: Record<string, unknown>,
30
+ ) {
31
+ const { title, reactivitySrc, litHtmlSrc } = opts as JxMutableNode;
28
32
 
29
33
  const rootContext = createCompileContext(raw, null, raw.state ?? {}, raw.$media ?? {});
30
34
  const styleBlock = compileStyles(
31
35
  raw,
32
36
  raw.$media ?? {},
33
- /** @type {JxStyle | null} */ (opts.projectStyle ?? null),
37
+ (opts.projectStyle ?? null) as JxStyle | null,
34
38
  );
35
- /** @type {{ def: any; tagName: string; className: string }[]} */
36
- const islands = [];
39
+ const islands: { def: JxMutableNode; tagName: string; className: string }[] = [];
37
40
  const bodyContent = compileNode(raw, false, raw, rootContext, islands);
38
41
 
39
42
  /** @type {{ path: string; content: string; tagName: string }[]} */
@@ -95,7 +98,17 @@ export function compileStaticPage(raw, opts) {
95
98
  * @param {{ def: any; tagName: string; className: string }[]} islands
96
99
  * @returns {string}
97
100
  */
98
- function compileNode(def, dynamic, raw, context, islands) {
101
+ function compileNode(
102
+ def: JxMutableNode,
103
+ dynamic: boolean,
104
+ raw: JxMutableNode,
105
+ context: {
106
+ scope: Record<string, unknown> | null;
107
+ scopeDefs: Record<string, unknown>;
108
+ media: Record<string, string>;
109
+ },
110
+ islands: { def: JxMutableNode; tagName: string; className: string }[],
111
+ ): string {
99
112
  // String children are text nodes
100
113
  if (typeof def === "string") {
101
114
  return escapeHtml(def);
@@ -138,7 +151,16 @@ function compileNode(def, dynamic, raw, context, islands) {
138
151
  * @param {{ def: any; tagName: string; className: string }[]} islands
139
152
  * @returns {string}
140
153
  */
141
- function buildInnerWithIslands(def, raw, context, islands) {
154
+ function buildInnerWithIslands(
155
+ def: JxMutableNode,
156
+ raw: JxMutableNode,
157
+ context: {
158
+ scope: Record<string, unknown> | null;
159
+ scopeDefs: Record<string, unknown>;
160
+ media: Record<string, string>;
161
+ },
162
+ islands: { def: JxMutableNode; tagName: string; className: string }[],
163
+ ): string {
142
164
  const source = raw ?? def;
143
165
 
144
166
  if (source.textContent !== undefined) {
@@ -146,19 +168,14 @@ function buildInnerWithIslands(def, raw, context, islands) {
146
168
  return value == null ? "" : escapeHtml(String(value));
147
169
  }
148
170
  if (source.innerHTML)
149
- return (
150
- /** @type {string} */ (resolveStaticValue(source.innerHTML, context.scope)) ??
151
- source.innerHTML
152
- );
171
+ return (resolveStaticValue(source.innerHTML, context.scope) as string) ?? source.innerHTML;
153
172
  if (Array.isArray(source.children)) {
154
173
  const rawChildren = raw?.children;
155
174
  return source.children
156
- .map((c, /** @type {number} */ i) => {
157
- const child = /** @type {JxMutableNode} */ (/** @type {unknown} */ (c));
175
+ .map((c, i: number) => {
176
+ const child = c as unknown as JxMutableNode;
158
177
  const childDynamic = isNodeDynamic(child);
159
- const childRaw = /** @type {JxMutableNode} */ (
160
- /** @type {unknown} */ (rawChildren?.[i] ?? c)
161
- );
178
+ const childRaw = (rawChildren?.[i] ?? c) as JxMutableNode;
162
179
  return compileNode(child, childDynamic, childRaw, context, islands);
163
180
  })
164
181
  .join("\n ");
package/src/types.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface HeadMergeContext {
2
+ title?: string;
3
+ siteName?: string;
4
+ lang?: string;
5
+ charset?: string;
6
+ url?: string;
7
+ siteUrl?: string;
8
+ pageUrl?: string;
9
+ }
10
+
11
+ export interface SiteRoute {
12
+ urlPattern: string;
13
+ sourcePath?: string;
14
+ _pathParams?: Record<string, string>;
15
+ [key: string]: unknown;
16
+ }