@monimesl/dot-compiler 0.1.0-alpha.21 → 0.1.0-alpha.23

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/index.d.ts CHANGED
@@ -11,6 +11,10 @@ interface DotJson {
11
11
  readonly version: string;
12
12
  readonly permissions?: Readonly<Partial<Record<DotPermission, string>>> | undefined;
13
13
  readonly network?: NetworkAccess | undefined;
14
+ readonly dash?: DashNeeds | undefined;
15
+ }
16
+ interface DashNeeds {
17
+ readonly minApiVersion: string;
14
18
  }
15
19
  interface NetworkAccess {
16
20
  readonly hosts: readonly string[];
@@ -22,6 +26,7 @@ export declare const PAGES_DIR = "pages";
22
26
  interface PageSource {
23
27
  readonly path: string;
24
28
  readonly id: string;
29
+ readonly share: readonly string[] | null;
25
30
  readonly view: string;
26
31
  readonly state: string;
27
32
  readonly controller: string;
@@ -35,6 +40,9 @@ interface Project {
35
40
  }
36
41
  export declare function loadProject(root: string): Promise<Project>;
37
42
  //#endregion
43
+ //#region src/build/bundle.d.ts
44
+ type BuildMode = 'production' | 'development';
45
+ //#endregion
38
46
  //#region src/errors.d.ts
39
47
  export declare class CompileError extends SourceError {
40
48
  readonly name = "CompileError";
@@ -48,7 +56,7 @@ export declare class CompileWarning extends SourceError {
48
56
  interface BuildOptions {
49
57
  root: string;
50
58
  outDir?: string | undefined;
51
- mode?: 'production' | 'development' | undefined;
59
+ mode?: BuildMode | undefined;
52
60
  components?: readonly ComponentManifest[] | undefined;
53
61
  conditions?: readonly string[] | undefined;
54
62
  }
@@ -65,6 +73,8 @@ interface DotManifest extends DotJson {
65
73
  readonly react: string;
66
74
  readonly entry: string;
67
75
  readonly pages: readonly string[];
76
+ readonly share: Readonly<Record<string, readonly string[]>>;
77
+ readonly dash: DashNeeds;
68
78
  }
69
79
  //#endregion
70
80
  //#region src/build/packages.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/project/dot-json.ts","../src/project/project.ts","../src/errors.ts","../src/build/build.ts","../src/build/packages.ts","../src/view/compiler.ts","../src/view/compile.ts","../src/view/control-flow.ts","../src/project/statics.ts"],"mappings":";;;;qBAQa;wBA0BG,aAAa;UAIZ;WAEN;WACA;WACA;WACA;WAEA,cAAc,SAAS,QAAQ,OAAO;WACtC,UAAU;;UAIX;WAEC;;;;qBCzCE;qBACA;UAOI;WAEN;WAEA;WACA;WACA;WACA;;UAGM;WACN;WAEA,SAAS;WAET;WAEA,gBAAgB;WAEhB;;wBAGW,YAAY,eAAe,QAAQ;;;qBCvC5C,qBAAqB;WACd;;;qBAIP,uBAAuB;WAChB;;;;UCyBH;EACf;EAEA;EAEA;EACA,sBAAsB;EACtB;;UAGe;WACN;WACA;WACA,mBAAmB;;;wBAIR,MAAM,SAAS,eAAe,QAAQ;;UAuI3C,oBAAoB;WAE1B;WAEA;WACA;WACA;;;;UCrLM;WACN;WACA,OAAO;WAEP;;UAIM;WACN;WAEA;;wBAQK,iBAAiB,eAAe;;;UCT/B;EACf;EACA,aAAa;EAEb;EAEA;EAEA;EACA,cAAc,SAAS;EAEvB,gBAAgB;;qBAKL;qBAMA;wBA+XG,QAAQ;wBASR,gBAAgB,QAAQ,mBAAmB,OAAO;;;wBC7alD,YAAY,gBAAgB,SAAS;;;qBCCxC,mBAAmB,SAC9B;WAA0B;WAAwC;;;;qBCCvD;wBAoBS,YAAY,eAAe"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/project/dot-json.ts","../src/project/project.ts","../src/build/bundle.ts","../src/errors.ts","../src/build/build.ts","../src/build/packages.ts","../src/view/compiler.ts","../src/view/compile.ts","../src/view/control-flow.ts","../src/project/statics.ts"],"mappings":";;;;qBAea;wBA4BG,aAAa;UAIZ;WAEN;WACA;WACA;WACA;WAEA,cAAc,SAAS,QAAQ,OAAO;WACtC,UAAU;WACV,OAAO;;UAID;WAEN;;UAID;WAEC;;;;qBCzDE;qBACA;UAOI;WAEN;WAEA;WAEA;WACA;WACA;WACA;;UAGM;WACN;WAEA,SAAS;WAET;WAEA,gBAAgB;WAEhB;;wBAGW,YAAY,eAAe,QAAQ;;;KCjC7C;;;qBCRC,qBAAqB;WACd;;;qBAIP,uBAAuB;WAChB;;;;UC4BH;EACf;EAEA;EAEA,OAAO;EACP,sBAAsB;EACtB;;UAGe;WACN;WACA;WACA,mBAAmB;;;wBAIR,MAAM,SAAS,eAAe,QAAQ;;UA4I3C,oBAAoB;WAE1B;WAEA;WACA;WACA;WAEA,OAAO,SAAS;WAEhB,MAAM;;;;UCjMA;WACN;WACA,OAAO;WAEP;;UAIM;WACN;WAEA;;wBAQK,iBAAiB,eAAe;;;UCT/B;EACf;EACA,aAAa;EAEb;EAEA;EAEA;EACA,cAAc,SAAS;EAEvB,gBAAgB;;qBAKL;qBAMA;wBAmZG,QAAQ;wBA2BR,gBAAgB,QAAQ,mBAAmB,OAAO;;;wBCndlD,YAAY,gBAAgB,SAAS;;;qBCCxC,mBAAmB,SAC9B;WAA0B;WAAwC;;;;qBCEvD;wBAoBS,YAAY,eAAe"}
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@ import { createRequire } from "node:module";
2
2
  import { existsSync, readFileSync, realpathSync } from "node:fs";
3
3
  import { dirname, extname, join, relative, resolve, sep } from "node:path";
4
4
  import { copyFile, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
5
- import { ScriptParseError, parseDotModule, parseExpression, parseLogicModule, parseStateModule, unboundReferences } from "@monimesl/dot-script-parser";
6
- import { PERMISSIONS, REACT_HOST_MODULES, SourceError, builtinComponents, builtinRegistry, componentRegistry, eventName, isNetworkHost, isPermission, isSemanticVersion, isWordsOr, otherThanWords, reactHostUrl } from "@monimesl/dot-core";
5
+ import { ScriptParseError, globalMemberUses, parseDotModule, parseExpression, parseLogicModule, parseStateModule, unboundReferences } from "@monimesl/dot-script-parser";
6
+ import { DEFAULT_DASH_API_VERSION, PERMISSIONS, REACT_HOST_MODULES, SourceError, builtinComponents, builtinRegistry, componentRegistry, eventName, isDashApiVersion, isNetworkHost, isPermission, isSemanticVersion, isWordsOr, otherThanWords, reactHostUrl } from "@monimesl/dot-core";
7
7
  import { zipSync } from "fflate";
8
8
  import { rolldown } from "rolldown";
9
9
  import { esmExternalRequirePlugin } from "rolldown/plugins";
@@ -22,6 +22,9 @@ var CompileWarning = class extends SourceError {
22
22
  function quotedList(values) {
23
23
  return values.map((value) => `"${value}"`).join(", ");
24
24
  }
25
+ function relativeSlashPath(from, to) {
26
+ return relative(from, to).split(sep).join("/");
27
+ }
25
28
  //#endregion
26
29
  //#region src/project/dot-json.ts
27
30
  const DOT_JSON_FILE = "dot.json";
@@ -32,7 +35,8 @@ const DOT_JSON_FIELDS = [
32
35
  "name",
33
36
  "version",
34
37
  "permissions",
35
- "network"
38
+ "network",
39
+ "dash"
36
40
  ];
37
41
  const REQUIRED_DOT_JSON_FIELDS = [
38
42
  "package",
@@ -40,6 +44,7 @@ const REQUIRED_DOT_JSON_FIELDS = [
40
44
  "version"
41
45
  ];
42
46
  const NETWORK_FIELDS = ["hosts"];
47
+ const DASH_FIELDS = ["minApiVersion"];
43
48
  const LISTING_FIELDS = [
44
49
  "description",
45
50
  "categories",
@@ -60,11 +65,10 @@ async function readDotJson(file) {
60
65
  if (!isObject(dotJson)) throw new CompileError("dot.json must be an object, such as { \"package\": \"com.mysalone.thing\", \"name\": \"My Salone Thing\", \"version\": \"1.0.0\" }", file);
61
66
  if ("pages" in dotJson) throw new CompileError("List pages in dot.ts, not here: defineDot({ pages: [...] })", file);
62
67
  for (const field of LISTING_FIELDS) if (field in dotJson) throw new CompileError(`Remove "${field}". A dot's description, categories and icon are set where it's published.`, file);
63
- if ("dash" in dotJson) throw new CompileError("Remove \"dash\". Dash now checks the Dot runtime version a dot is built with.", file);
64
68
  rejectUnknownFields(dotJson, DOT_JSON_FIELDS, file);
65
69
  if (dotJson.package === void 0 && typeof dotJson.id === "string" && DOT_PACKAGE_PATTERN.test(dotJson.id)) throw new CompileError(`"${dotJson.id}" is a package name. Rename "id" to "package".`, file);
66
70
  for (const field of REQUIRED_DOT_JSON_FIELDS) if (dotJson[field] === void 0) throw new CompileError(`"${field}" is required`, file);
67
- const { $schema, package: packageName, id, name, version, permissions, network } = dotJson;
71
+ const { $schema, package: packageName, id, name, version, permissions, network, dash } = dotJson;
68
72
  if ($schema !== void 0 && typeof $schema !== "string") throw new CompileError("\"$schema\" must be a string", file);
69
73
  if (typeof packageName !== "string" || !DOT_PACKAGE_PATTERN.test(packageName)) throw new CompileError("\"package\" must be a reverse domain name. Use lowercase words joined by dots, such as \"com.mysalone.thing\".", file);
70
74
  if (packageName.length > 128) throw new CompileError(`"package" must be at most 128 characters`, file);
@@ -77,12 +81,21 @@ async function readDotJson(file) {
77
81
  name,
78
82
  version,
79
83
  permissions: readPermissions(permissions, file),
80
- network: readNetworkAccess(network, file)
84
+ network: readNetworkAccess(network, file),
85
+ dash: readDashNeeds(dash, file)
81
86
  };
82
87
  }
88
+ function readDashNeeds(dash, file) {
89
+ if (dash === void 0) return;
90
+ if (!isObject(dash)) throw new CompileError("\"dash\" must be an object, such as { \"minApiVersion\": \"1.0\" }", file);
91
+ rejectUnknownFields(dash, DASH_FIELDS, file, "dash");
92
+ const { minApiVersion = DEFAULT_DASH_API_VERSION } = dash;
93
+ if (!isDashApiVersion(minApiVersion)) throw new CompileError("\"dash.minApiVersion\" must be a Dash API version: a major and a minor, such as \"1.0\"", file);
94
+ return { minApiVersion };
95
+ }
83
96
  function readPermissions(permissions, file) {
84
97
  if (permissions === void 0) return;
85
- if (!isObject(permissions)) throw new CompileError("\"permissions\" must be an object, such as { \"account\": \"Show your name on receipts\" }", file);
98
+ if (!isObject(permissions)) throw new CompileError("\"permissions\" must be an object, such as { \"camera\": \"Scan tickets at the door\" }", file);
86
99
  for (const [permission, reason] of Object.entries(permissions)) {
87
100
  if (!isPermission(permission)) throw new CompileError(`Unknown permission "${permission}". The permissions are ${quotedList(PERMISSIONS)}`, file);
88
101
  if (!isNonEmptyString(reason)) throw new CompileError(`"permissions.${permission}" must say why the dot needs it, such as "Show your name on receipts"`, file);
@@ -149,7 +162,7 @@ async function listStatics(root) {
149
162
  if (!entry.isFile() || entry.name.startsWith(".")) continue;
150
163
  const file = join(entry.parentPath, entry.name);
151
164
  await checkImage(file, extname(entry.name).toLowerCase());
152
- statics.push(`${STATICS_DIR}/${relative(staticsDir, file).split(sep).join("/")}`);
165
+ statics.push(`${STATICS_DIR}/${relativeSlashPath(staticsDir, file)}`);
153
166
  }
154
167
  return statics.sort();
155
168
  }
@@ -180,15 +193,15 @@ async function loadProject(root) {
180
193
  const dotFile = join(root, DOT_FILE);
181
194
  if (!existsSync(dotFile)) throw new CompileError(`There is no ${DOT_FILE}. Add one: export default defineDot({ pages: [...] })`, root);
182
195
  const { pages } = parseDotModule(await readFile(dotFile, "utf8"), dotFile);
183
- const sources = await Promise.all(pages.map((path) => loadPage(root, path, dotFile)));
196
+ const pageSources = await Promise.all(pages.map((path) => loadPage(root, path, dotFile)));
184
197
  const pagesByLowercaseId = /* @__PURE__ */ new Map();
185
- for (const page of sources) {
186
- const other = pagesByLowercaseId.get(page.id.toLowerCase());
187
- if (other) {
198
+ for (const page of pageSources) {
199
+ const earlierPage = pagesByLowercaseId.get(page.id.toLowerCase());
200
+ if (earlierPage) {
188
201
  let file = dotFile;
189
202
  if (page.id !== page.path) file = page.controller;
190
- else if (other.id !== other.path) file = other.controller;
191
- throw new CompileError(`Page id "${page.id}" (${page.path}) is already used by ${other.path}`, file);
203
+ else if (earlierPage.id !== earlierPage.path) file = earlierPage.controller;
204
+ throw new CompileError(`Page id "${page.id}" (${page.path}) is already used by ${earlierPage.path}`, file);
192
205
  }
193
206
  pagesByLowercaseId.set(page.id.toLowerCase(), page);
194
207
  }
@@ -196,7 +209,7 @@ async function loadProject(root) {
196
209
  root,
197
210
  dotJson,
198
211
  dot: dotFile,
199
- pages: sources,
212
+ pages: pageSources,
200
213
  statics: await listStatics(root)
201
214
  };
202
215
  }
@@ -209,10 +222,12 @@ async function loadPage(root, path, dotFile) {
209
222
  };
210
223
  const missing = Object.values(files).filter((file) => !existsSync(file));
211
224
  if (missing.length > 0) throw new CompileError(`Page "${path}" is missing ${missing.join(", ")}`, dotFile);
212
- const { id } = parseLogicModule(await readFile(files.controller, "utf8"), files.controller);
225
+ const controller = await readFile(files.controller, "utf8");
226
+ const { id, share } = parseLogicModule(controller, files.controller);
213
227
  return {
214
228
  path,
215
229
  id: id ?? path,
230
+ share,
216
231
  ...files
217
232
  };
218
233
  }
@@ -255,9 +270,12 @@ function uiEntry(project, components) {
255
270
  ""
256
271
  ].join("\n");
257
272
  }
258
- function logicEntry(project, { strict }) {
273
+ function logicEntry(project, { strict, dashMinApiVersion }) {
259
274
  const options = [" dot,", ` pages: ${pageTable(project, "page")},`];
260
- if (strict) options.push(" strict: true,");
275
+ if (strict) {
276
+ options.push(" strict: true,");
277
+ options.push(` dashMinApiVersion: ${literal(dashMinApiVersion)},`);
278
+ }
261
279
  return [
262
280
  `import { runService } from ${literal(RUNTIME_MODULES.logic)};`,
263
281
  `import dot from ${literal(project.dot)};`,
@@ -275,7 +293,7 @@ function envModule(env) {
275
293
  //#endregion
276
294
  //#region src/globals.ts
277
295
  const DOT_GLOBALS = {
278
- "@monimesl/dot-runtime": [
296
+ [RUNTIME_PACKAGE]: [
279
297
  "definePage",
280
298
  "defineDot",
281
299
  "createEvent",
@@ -284,6 +302,7 @@ const DOT_GLOBALS = {
284
302
  [ENV_MODULE]: ["env"]
285
303
  };
286
304
  const SCRIPT_FILE = /\.[cm]?[jt]sx?$/;
305
+ const ANSWERS_AT_ONCE = /* @__PURE__ */ new Set(["utils", "supports"]);
287
306
  function dotGlobals(root) {
288
307
  const realRoot = realpathSync(root);
289
308
  const isDotModule = (id) => id.startsWith(realRoot + sep) && !id.includes(`${sep}node_modules${sep}`) && SCRIPT_FILE.test(id);
@@ -293,7 +312,7 @@ function dotGlobals(root) {
293
312
  transform(code, id) {
294
313
  if (!isDotModule(id)) return null;
295
314
  const used = new Set(unboundReferences(code, Object.values(DOT_GLOBALS).flat(), id));
296
- if (isPageModule(id) && used.has("dash")) this.error(`${relative(realRoot, id)} uses the global \`dash\`. In a page, use \`this.dash\` in actions and hooks, so its calls stop when the page closes.`);
315
+ if (isPageModule(id) && used.has("dash") && makesDashCalls(code, id)) this.error(`${relative(realRoot, id)} uses the global \`dash\`. In a page, use \`this.dash\` in actions and hooks, so its calls stop when the page closes. Only dash.utils and dash.supports, which answer at once, work anywhere.`);
297
316
  const imports = [];
298
317
  for (const [source, names] of Object.entries(DOT_GLOBALS)) {
299
318
  const imported = names.filter((name) => used.has(name));
@@ -307,6 +326,10 @@ function dotGlobals(root) {
307
326
  }
308
327
  };
309
328
  }
329
+ function makesDashCalls(code, id) {
330
+ for (const member of globalMemberUses(code, "dash", id)) if (!ANSWERS_AT_ONCE.has(member)) return true;
331
+ return false;
332
+ }
310
333
  //#endregion
311
334
  //#region src/build/bundle.ts
312
335
  async function bundle(options) {
@@ -341,7 +364,7 @@ async function bundle(options) {
341
364
  entryFileNames: options.fileName,
342
365
  sourcemap: options.mode === "development",
343
366
  sourcemapExcludeSources: options.mode === "production",
344
- minify: options.minify
367
+ minify: options.mode === "production"
345
368
  });
346
369
  return output.map((chunk) => join(options.outDir, chunk.fileName));
347
370
  } finally {
@@ -511,17 +534,17 @@ var ViewCompiler = class {
511
534
  }
512
535
  compile(nodes, parent, scope) {
513
536
  const compiled = [];
514
- for (let i = 0; i < nodes.length; i++) {
515
- const node = nodes[i];
537
+ for (let index = 0; index < nodes.length; index++) {
538
+ const node = nodes[index];
516
539
  if (node.type === "Text") {
517
540
  compiled.push(...this.#compileText(node.content, parent, scope, node.loc));
518
541
  continue;
519
542
  }
520
543
  switch (node.tag) {
521
544
  case "If": {
522
- const branches = ifChain(node, nodes.slice(i + 1));
545
+ const branches = ifChain(node, nodes.slice(index + 1));
523
546
  compiled.push(compileConditional(this, branches, parent, scope));
524
- i += branches.length - 1;
547
+ index += branches.length - 1;
525
548
  break;
526
549
  }
527
550
  case "ElseIf":
@@ -537,19 +560,23 @@ var ViewCompiler = class {
537
560
  #compileText(content, parent, scope, loc) {
538
561
  if (parent?.children !== "text") {
539
562
  if (content.trim() === "") return [];
540
- const wrappers = Object.values(this.#components).filter((component) => component.inline && component.children === "text").sort((a, b) => Number(b.name === "Text") - Number(a.name === "Text")).map((component) => `<${component.name}>`).join(" or ");
541
- this.fail(`'${content}' must be inside ${wrappers || "an inline component"}`, loc);
563
+ this.fail(`'${content}' must be inside ${this.#textWrapperNames()}`, loc);
542
564
  }
543
565
  return this.#compileAsSegments(content, scope, loc).map(printSegment);
544
566
  }
567
+ #textWrapperNames() {
568
+ const textWrappers = Object.values(this.#components).filter((component) => {
569
+ return component.inline === true && component.children === "text";
570
+ });
571
+ const textFirst = [...textWrappers.filter((component) => component.name === "Text"), ...textWrappers.filter((component) => component.name !== "Text")];
572
+ if (textFirst.length === 0) return "an inline component";
573
+ return textFirst.map((component) => `<${component.name}>`).join(" or ");
574
+ }
545
575
  compileRoot(nodes) {
546
576
  if (!this.#components["View"]) this.fail(`The components must include <${ROOT_TAG}>, which is the root of every page`);
547
577
  const [root, outside] = nodes;
548
578
  if (root?.type !== "Element" || root.tag !== "View") return this.fail(`A page must have one <${ROOT_TAG}> around everything else`, root?.loc);
549
- if (outside) {
550
- const name = outside.type === "Text" ? `'${outside.content}'` : `<${outside.tag}>`;
551
- this.fail(`${name} must be inside the page's <${ROOT_TAG}>`, outside.loc);
552
- }
579
+ if (outside) this.fail(`${describeNode(outside)} must be inside the page's <${ROOT_TAG}>`, outside.loc);
553
580
  return this.#compileElementArgs(root, null, EMPTY_SCOPE, ROOT_DEFAULTS);
554
581
  }
555
582
  #compileElementArgs(node, parent, scope, defaults = {}) {
@@ -567,9 +594,11 @@ var ViewCompiler = class {
567
594
  for (const [name, value] of propAttributes) props.push(this.#compileProp(component, name, value, scope, node.loc));
568
595
  for (const [name, handler] of Object.entries(node.events)) props.push(this.#compileEvent(component, name, handler, data, node.loc));
569
596
  for (const [name, value] of Object.entries(defaults)) if (!(name in node.attributes)) props.push(`${name}: ${JSON.stringify(value)}`);
597
+ let propsCode = "null";
598
+ if (props.length > 0) propsCode = `{ ${props.join(", ")} }`;
570
599
  return [
571
600
  JSON.stringify(component.name),
572
- props.length ? `{ ${props.join(", ")} }` : "null",
601
+ propsCode,
573
602
  ...this.compile(node.children, component, scope)
574
603
  ];
575
604
  }
@@ -587,7 +616,7 @@ var ViewCompiler = class {
587
616
  const kind = typeof type === "string" ? `a ${type}` : "an enum";
588
617
  this.fail(`\`${name}\` is ${kind}, so set it with one {{ }} binding`, loc);
589
618
  }
590
- return `${name}: ${segments.map(printSegment).join(" + ")}`;
619
+ return `${name}: ${concatenateSegments(segments)}`;
591
620
  }
592
621
  #compileData(attributes, scope, loc) {
593
622
  if (attributes.length === 0) return null;
@@ -601,7 +630,7 @@ var ViewCompiler = class {
601
630
  const bindingCode = singleBindingCode(segments);
602
631
  if (bindingCode !== null) return bindingCode;
603
632
  if (segments.length === 0) return "\"\"";
604
- return segments.map(printSegment).join(" + ");
633
+ return concatenateSegments(segments);
605
634
  }
606
635
  #checkStaticsReference(value, loc) {
607
636
  const { statics } = this.#context;
@@ -613,7 +642,9 @@ var ViewCompiler = class {
613
642
  if (!isIdentifier(handler)) this.fail(`\`${attribute}\` must name a mutation or action in controller.ts, got "${handler}"`, loc);
614
643
  const { handlers } = this.#context;
615
644
  if (handlers && !handlers.includes(handler)) this.fail(`\`${handler}\` isn't a mutation or action in controller.ts`, loc);
616
- return `${attribute}: on(${data ? `${JSON.stringify(handler)}, ${data}` : JSON.stringify(handler)})`;
645
+ let onArguments = JSON.stringify(handler);
646
+ if (data) onArguments += `, ${data}`;
647
+ return `${attribute}: on(${onArguments})`;
617
648
  }
618
649
  checkControlFlowElementAttributes(node) {
619
650
  const { attributes: allowed, required } = CONTROL_FLOW_TAGS[node.tag];
@@ -639,7 +670,7 @@ var ViewCompiler = class {
639
670
  if (value === "false") return "false";
640
671
  return this.fail(`Expected true or false, got "${value}"`, loc);
641
672
  case "number":
642
- if (isNumberText(value)) return String(Number(value));
673
+ if (isNumberText(value)) return printNumber(value);
643
674
  return this.fail(`Expected a number, got "${value}"`, loc);
644
675
  case "string":
645
676
  case "any": return JSON.stringify(value);
@@ -647,26 +678,26 @@ var ViewCompiler = class {
647
678
  }
648
679
  #compileWordOr(type, value, loc) {
649
680
  if (type.words.includes(value)) return JSON.stringify(value);
650
- if (type.or === "number" && isNumberText(value)) return String(Number(value));
681
+ if (type.or === "number" && isNumberText(value)) return printNumber(value);
651
682
  if (type.or === "themeColor" && THEME_COLOR_NAME.test(value)) return JSON.stringify(value);
652
683
  return this.fail(`Expected one of ${quotedList(type.words)}, or ${otherThanWords(type)}, got "${value}"`, loc);
653
684
  }
654
685
  #compileAsSegments(input, scope, loc) {
655
686
  const segments = [];
656
- let last = 0;
687
+ let staticStart = 0;
657
688
  for (const match of input.matchAll(SEGMENT_BINDING_REGEXP)) {
658
- if (match.index > last) segments.push({
689
+ if (match.index > staticStart) segments.push({
659
690
  kind: "static",
660
- value: input.slice(last, match.index)
691
+ value: input.slice(staticStart, match.index)
661
692
  });
662
- const expr = this.#parseBindingExpression(match[1], scope, loc);
693
+ const expression = this.#parseBindingExpression(match[1], scope, loc);
663
694
  segments.push({
664
695
  kind: "binding",
665
- code: printExpr(expr, scope)
696
+ code: printExpr(expression, scope)
666
697
  });
667
- last = match.index + match[0].length;
698
+ staticStart = match.index + match[0].length;
668
699
  }
669
- const rest = input.slice(last);
700
+ const rest = input.slice(staticStart);
670
701
  if (rest.includes("{{")) this.fail("A binding is missing its closing `}}`", loc);
671
702
  if (rest) segments.push({
672
703
  kind: "static",
@@ -675,22 +706,22 @@ var ViewCompiler = class {
675
706
  return segments;
676
707
  }
677
708
  #parseBindingExpression(source, scope, loc) {
678
- let expr;
709
+ let expression;
679
710
  try {
680
- expr = parseExpression(source);
711
+ expression = parseExpression(source);
681
712
  } catch (error) {
682
713
  if (!(error instanceof ScriptParseError)) throw error;
683
714
  return this.fail(`Invalid binding \`{{${source}}}\`: ${error.reason}`, loc);
684
715
  }
685
716
  const { stateKeys } = this.#context;
686
717
  if (stateKeys) {
687
- const undeclared = stateReads(expr, scope).find((name) => !stateKeys.includes(name));
718
+ const undeclared = stateReads(expression, scope).find((name) => !stateKeys.includes(name));
688
719
  if (undeclared) {
689
720
  const declared = stateKeys.join(", ") || "none";
690
721
  this.fail(`\`${undeclared}\` isn't in state.ts. It has: ${declared}`, loc);
691
722
  }
692
723
  }
693
- return expr;
724
+ return expression;
694
725
  }
695
726
  warn(message, loc) {
696
727
  this.#context.onWarning?.(new CompileWarning(message, this.#context.file, loc));
@@ -702,8 +733,9 @@ var ViewCompiler = class {
702
733
  function ifChain(ifNode, nextSiblings) {
703
734
  const branches = [ifNode];
704
735
  for (const sibling of nextSiblings) {
705
- if (branches.at(-1).tag === "Else" || !continuesIf(sibling)) break;
736
+ if (!continuesIf(sibling)) break;
706
737
  branches.push(sibling);
738
+ if (sibling.tag === "Else") break;
707
739
  }
708
740
  return branches;
709
741
  }
@@ -716,11 +748,21 @@ function singleBindingCode(segments) {
716
748
  return null;
717
749
  }
718
750
  function dataKey(attribute) {
719
- const [first = "", ...rest] = attribute.slice(5).split("-");
720
- return first + rest.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
751
+ const words = attribute.slice(5).split("-");
752
+ let key = words[0] ?? "";
753
+ for (const word of words.slice(1)) key += word.charAt(0).toUpperCase() + word.slice(1);
754
+ return key;
755
+ }
756
+ function describeNode(node) {
757
+ if (node.type === "Text") return `'${node.content}'`;
758
+ return `<${node.tag}>`;
721
759
  }
722
760
  function printSegment(segment) {
723
- return segment.kind === "static" ? JSON.stringify(segment.value) : `text(${segment.code})`;
761
+ if (segment.kind === "static") return JSON.stringify(segment.value);
762
+ return `text(${segment.code})`;
763
+ }
764
+ function concatenateSegments(segments) {
765
+ return segments.map(printSegment).join(" + ");
724
766
  }
725
767
  function canHaveChildren(parent, child) {
726
768
  switch (parent.children) {
@@ -732,6 +774,9 @@ function canHaveChildren(parent, child) {
732
774
  function isNumberText(value) {
733
775
  return value.trim() !== "" && Number.isFinite(Number(value));
734
776
  }
777
+ function printNumber(value) {
778
+ return String(Number(value));
779
+ }
735
780
  //#endregion
736
781
  //#region src/view/compile.ts
737
782
  function compileView(source, context) {
@@ -824,18 +869,16 @@ async function build(options) {
824
869
  fileName: "dot.js",
825
870
  format,
826
871
  mode,
827
- minify: mode === "production",
828
872
  conditions: options.conditions ?? [],
829
873
  external
830
874
  });
831
- const files = [
832
- ...await bundleLayer(ENTRY.ui, uiDir, "esm", Object.keys(REACT_HOST_MODULES)),
833
- ...await bundleLayer(ENTRY.logic, join(outDir, "logic"), "iife", []),
834
- await copyRendererStyles(runtime, uiDir),
835
- await writeIndexHtml(project, uiDir, runtime.react.version),
836
- ...await copyStatics(project, uiDir),
837
- await writeManifest(project, outDir, runtime)
838
- ];
875
+ const files = [];
876
+ files.push(...await bundleLayer(ENTRY.ui, uiDir, "esm", Object.keys(REACT_HOST_MODULES)));
877
+ files.push(...await bundleLayer(ENTRY.logic, join(outDir, "logic"), "iife", []));
878
+ files.push(await copyRendererStyles(runtime, uiDir));
879
+ files.push(await writeIndexHtml(project, uiDir, runtime.react.version));
880
+ files.push(...await copyStatics(project, uiDir));
881
+ files.push(await writeManifest(project, outDir, runtime));
839
882
  if (mode === "production") files.push(await writeArchive(project, outDir, files));
840
883
  return {
841
884
  outDir,
@@ -852,7 +895,7 @@ async function copyRendererStyles(runtime, uiDir) {
852
895
  async function writeArchive(project, outDir, files) {
853
896
  const entries = {};
854
897
  for (const file of files) if (!file.endsWith(".map")) {
855
- const name = relative(outDir, file).split(sep).join("/");
898
+ const name = relativeSlashPath(outDir, file);
856
899
  entries[name] = [await readFile(file), { mtime: ARCHIVE_DATE }];
857
900
  }
858
901
  const { package: packageName, version } = project.dotJson;
@@ -868,9 +911,14 @@ async function compileModules(project, env, components, mode, warnings) {
868
911
  const view = await compilePage(page, components, project.statics, warnings, usedComponents);
869
912
  modules.set(viewModuleId(page.id), view);
870
913
  }
871
- const usedBuiltins = [...usedComponents].filter((name) => name in builtinComponents).sort();
872
- modules.set(ENTRY.ui, uiEntry(project, mode === "production" ? usedBuiltins : void 0));
873
- modules.set(ENTRY.logic, logicEntry(project, { strict: mode === "development" }));
914
+ let rendererComponents;
915
+ if (mode === "production") rendererComponents = [...usedComponents].filter((name) => name in builtinComponents).sort();
916
+ modules.set(ENTRY.ui, uiEntry(project, rendererComponents));
917
+ const logicOptions = {
918
+ strict: mode === "development",
919
+ dashMinApiVersion: dashMinApiVersion(project)
920
+ };
921
+ modules.set(ENTRY.logic, logicEntry(project, logicOptions));
874
922
  modules.set(ENV_MODULE, envModule(env));
875
923
  return modules;
876
924
  }
@@ -899,6 +947,8 @@ async function writeManifest(project, outDir, runtime) {
899
947
  function dotManifest(project, runtime) {
900
948
  const { id, package: packageName, name, version, permissions, network } = project.dotJson;
901
949
  const pages = project.pages.map((page) => page.id);
950
+ const share = {};
951
+ for (const page of project.pages) if (page.share) share[page.id] = page.share;
902
952
  return {
903
953
  id,
904
954
  package: packageName,
@@ -908,10 +958,15 @@ function dotManifest(project, runtime) {
908
958
  react: runtime.react.version,
909
959
  permissions,
910
960
  network,
961
+ dash: { minApiVersion: dashMinApiVersion(project) },
911
962
  entry: pages[0],
912
- pages
963
+ pages,
964
+ share
913
965
  };
914
966
  }
967
+ function dashMinApiVersion(project) {
968
+ return project.dotJson.dash?.minApiVersion ?? DEFAULT_DASH_API_VERSION;
969
+ }
915
970
  async function compilePage(page, components, statics, warnings, usedComponents) {
916
971
  const [view, state, controller] = await Promise.all([
917
972
  readFile(page.view, "utf8"),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/utils.ts","../src/project/dot-json.ts","../src/project/statics.ts","../src/project/project.ts","../src/entries.ts","../src/globals.ts","../src/build/bundle.ts","../src/build/packages.ts","../src/view/expression.ts","../src/view/control-flow.ts","../src/view/compiler.ts","../src/view/compile.ts","../src/types.ts","../src/project/env.ts","../src/build/build.ts"],"sourcesContent":["import { SourceError } from '@monimesl/dot-core';\n\nexport class CompileError extends SourceError {\n override readonly name = 'CompileError';\n}\n\n/** A problem that does not stop compilation. */\nexport class CompileWarning extends SourceError {\n override readonly name = 'CompileWarning';\n}\n","export function quotedList(values: readonly string[]): string {\n return values.map((value) => `\"${value}\"`).join(', ');\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type { DotPermission } from '@monimesl/dot-core';\nimport { PERMISSIONS, isNetworkHost, isPermission, isSemanticVersion } from '@monimesl/dot-core';\n\nimport { CompileError } from '../errors';\nimport { quotedList } from '../utils';\n\nexport const DOT_JSON_FILE = 'dot.json';\n\n// The fields dot.json allows. The runtime's `dot.schema.json` describes the same ones for editors,\n// and a test keeps the two in step.\nexport const DOT_JSON_FIELDS: readonly string[] = [\n 'id',\n '$schema',\n 'package',\n 'name',\n 'version',\n 'permissions',\n 'network',\n];\nexport const REQUIRED_DOT_JSON_FIELDS: readonly string[] = ['package', 'name', 'version'];\nexport const NETWORK_FIELDS: readonly string[] = ['hosts'];\n// Where Dash lists a dot, and how, comes from where the dot is published, not from dot.json.\nconst LISTING_FIELDS: readonly string[] = ['description', 'categories', 'icon'];\n\n// The package name: a reverse domain name, such as `com.mysalone.thing`, that never changes for\n// the life of the dot. Hosts name each dot's web origin after it, so it must also be a valid host\n// name. Each word is up to 63 lowercase letters, digits and inner hyphens. The first word starts\n// with a letter.\nconst PACKAGE_WORD = '[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?';\nexport const DOT_PACKAGE_PATTERN = new RegExp(`^(?=[a-z])${PACKAGE_WORD}(?:\\\\.${PACKAGE_WORD})+$`);\nexport const DOT_PACKAGE_MAX_LENGTH = 128;\n\nexport function isDotPackage(name: string): boolean {\n return name.length <= DOT_PACKAGE_MAX_LENGTH && DOT_PACKAGE_PATTERN.test(name);\n}\n\nexport interface DotJson {\n // The ID Monime gives the dot when it's registered. Only publishing needs it.\n readonly id?: string | undefined;\n readonly package: string;\n readonly name: string;\n readonly version: string;\n // Each permission the dot uses, with the reason Dash shows the person.\n readonly permissions?: Readonly<Partial<Record<DotPermission, string>>> | undefined;\n readonly network?: NetworkAccess | undefined;\n}\n\n// Where the dot may send requests with dash.network. Without it, it may send none.\ninterface NetworkAccess {\n // Host names, such as \"api.example.com\", or \"*.example.com\" for any subdomain.\n readonly hosts: readonly string[];\n}\n\nexport async function readDotJson(file: string): Promise<DotJson> {\n let dotJson: unknown;\n try {\n dotJson = JSON.parse(await readFile(file, 'utf8'));\n } catch (error) {\n throw new CompileError(`This isn't valid JSON: ${(error as Error).message}`, file);\n }\n if (!isObject(dotJson)) {\n throw new CompileError(\n 'dot.json must be an object, such as { \"package\": \"com.mysalone.thing\", \"name\": \"My Salone Thing\", \"version\": \"1.0.0\" }',\n file,\n );\n }\n if ('pages' in dotJson) {\n throw new CompileError('List pages in dot.ts, not here: defineDot({ pages: [...] })', file);\n }\n for (const field of LISTING_FIELDS) {\n if (field in dotJson) {\n throw new CompileError(\n `Remove \"${field}\". A dot's description, categories and icon are set where it's published.`,\n file,\n );\n }\n }\n if ('dash' in dotJson) {\n throw new CompileError(\n 'Remove \"dash\". Dash now checks the Dot runtime version a dot is built with.',\n file,\n );\n }\n rejectUnknownFields(dotJson, DOT_JSON_FIELDS, file);\n if (\n dotJson.package === undefined &&\n typeof dotJson.id === 'string' &&\n DOT_PACKAGE_PATTERN.test(dotJson.id)\n ) {\n throw new CompileError(`\"${dotJson.id}\" is a package name. Rename \"id\" to \"package\".`, file);\n }\n for (const field of REQUIRED_DOT_JSON_FIELDS) {\n if (dotJson[field] === undefined) {\n throw new CompileError(`\"${field}\" is required`, file);\n }\n }\n\n const { $schema, package: packageName, id, name, version, permissions, network } = dotJson;\n if ($schema !== undefined && typeof $schema !== 'string') {\n throw new CompileError('\"$schema\" must be a string', file);\n }\n if (typeof packageName !== 'string' || !DOT_PACKAGE_PATTERN.test(packageName)) {\n throw new CompileError(\n '\"package\" must be a reverse domain name. Use lowercase words joined by dots, such as \"com.mysalone.thing\".',\n file,\n );\n }\n if (packageName.length > DOT_PACKAGE_MAX_LENGTH) {\n throw new CompileError(`\"package\" must be at most ${DOT_PACKAGE_MAX_LENGTH} characters`, file);\n }\n if (id !== undefined && !isNonEmptyString(id)) {\n throw new CompileError('\"id\" must be the ID Monime gave the dot, as text', file);\n }\n if (!isNonEmptyString(name)) {\n throw new CompileError('\"name\" must be text, and not empty', file);\n }\n if (!isSemanticVersion(version)) {\n throw new CompileError('\"version\" must be a semantic version, such as \"1.0.0\"', file);\n }\n return {\n id,\n package: packageName,\n name,\n version,\n permissions: readPermissions(permissions, file),\n network: readNetworkAccess(network, file),\n };\n}\n\nfunction readPermissions(\n permissions: unknown,\n file: string,\n): Partial<Record<DotPermission, string>> | undefined {\n if (permissions === undefined) {\n return undefined;\n }\n if (!isObject(permissions)) {\n throw new CompileError(\n '\"permissions\" must be an object, such as { \"account\": \"Show your name on receipts\" }',\n file,\n );\n }\n for (const [permission, reason] of Object.entries(permissions)) {\n if (!isPermission(permission)) {\n throw new CompileError(\n `Unknown permission \"${permission}\". The permissions are ${quotedList(PERMISSIONS)}`,\n file,\n );\n }\n if (!isNonEmptyString(reason)) {\n throw new CompileError(\n `\"permissions.${permission}\" must say why the dot needs it, such as \"Show your name on receipts\"`,\n file,\n );\n }\n }\n return permissions;\n}\n\nfunction readNetworkAccess(network: unknown, file: string): NetworkAccess | undefined {\n if (network === undefined) {\n return undefined;\n }\n if (!isObject(network)) {\n throw new CompileError(\n '\"network\" must be an object, such as { \"hosts\": [\"api.example.com\"] }',\n file,\n );\n }\n rejectUnknownFields(network, NETWORK_FIELDS, file, 'network');\n const { hosts } = network;\n if (!Array.isArray(hosts) || hosts.length === 0) {\n throw new CompileError(\n '\"network.hosts\" must list the hosts the dot sends requests to, such as [\"api.example.com\"]',\n file,\n );\n }\n const listed: string[] = [];\n for (const host of hosts as unknown[]) {\n if (typeof host !== 'string' || !isNetworkHost(host)) {\n throw new CompileError(\n `\"${String(host)}\" is not a host. Use a lowercase host name, such as \"api.example.com\", ` +\n 'or \"*.example.com\" for all its subdomains. Leave out https://, the port and the path.',\n file,\n );\n }\n if (listed.includes(host)) {\n throw new CompileError(`\"network.hosts\" lists \"${host}\" more than once`, file);\n }\n listed.push(host);\n }\n return { hosts: listed };\n}\n\nfunction rejectUnknownFields(\n object: Record<string, unknown>,\n allowed: readonly string[],\n file: string,\n parent?: string,\n): void {\n for (const field of Object.keys(object)) {\n if (allowed.includes(field)) {\n continue;\n }\n if (parent === undefined) {\n throw new CompileError(\n `Unknown field \"${field}\". The fields allowed are ${quotedList(allowed)}`,\n file,\n );\n }\n throw new CompileError(\n `Unknown field \"${parent}.${field}\". The fields allowed in \"${parent}\" are ${quotedList(allowed)}`,\n file,\n );\n }\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value !== '';\n}\n","import { existsSync } from 'node:fs';\nimport { readdir, readFile, stat } from 'node:fs/promises';\nimport { extname, join, relative, sep } from 'node:path';\n\nimport { CompileError } from '../errors';\n\n// Images a dot shows. The build copies them next to the webview as they are, and markup and state\n// refer to them as `statics/<path>`, for example `statics/logo.png`.\nexport const STATICS_DIR = 'statics';\n\nexport const MAX_STATIC_ASSET_BYTES = 1024 * 1024;\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n\n// Raster images only. Each is checked by its first bytes, so a file really is the image its\n// extension says. SVG is left out because it can carry scripts.\nconst IMAGE_FORMATS: Readonly<Record<string, (header: Buffer) => boolean>> = {\n '.png': (header) => header.subarray(0, 8).equals(PNG_SIGNATURE),\n '.jpg': isJpeg,\n '.jpeg': isJpeg,\n '.gif': (header) => ['GIF87a', 'GIF89a'].includes(header.toString('latin1', 0, 6)),\n '.webp': (header) =>\n header.toString('latin1', 0, 4) === 'RIFF' && header.toString('latin1', 8, 12) === 'WEBP',\n};\n\nconst STATIC_ASSET_EXTENSIONS: readonly string[] = Object.keys(IMAGE_FORMATS);\n\n// The images under statics/, as `statics/<path>`. Anything else fails the build.\nexport async function listStatics(root: string): Promise<string[]> {\n const staticsDir = join(root, STATICS_DIR);\n if (!existsSync(staticsDir)) {\n return [];\n }\n const statics: string[] = [];\n for (const entry of await readdir(staticsDir, { recursive: true, withFileTypes: true })) {\n // Hidden files, such as the .DS_Store macOS leaves in folders, are not part of the dot.\n if (!entry.isFile() || entry.name.startsWith('.')) {\n continue;\n }\n const file = join(entry.parentPath, entry.name);\n await checkImage(file, extname(entry.name).toLowerCase());\n statics.push(`${STATICS_DIR}/${relative(staticsDir, file).split(sep).join('/')}`);\n }\n return statics.sort();\n}\n\nasync function checkImage(file: string, extension: string): Promise<void> {\n const isFormat = IMAGE_FORMATS[extension];\n if (!isFormat) {\n throw new CompileError(\n `${STATICS_DIR}/ can only hold images: ${STATIC_ASSET_EXTENSIONS.join(', ')}`,\n file,\n );\n }\n const { size } = await stat(file);\n if (size > MAX_STATIC_ASSET_BYTES) {\n const megabytes = (size / MAX_STATIC_ASSET_BYTES).toFixed(1);\n throw new CompileError(`The image is ${megabytes} MB. Images must be 1 MB or smaller`, file);\n }\n if (!isFormat(await readFile(file))) {\n throw new CompileError(`The file isn't really a ${extension.slice(1)} image`, file);\n }\n}\n\nfunction isJpeg(header: Buffer): boolean {\n return header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff;\n}\n","import { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\n\nimport { parseDotModule, parseLogicModule } from '@monimesl/dot-script-parser';\n\nimport { CompileError } from '../errors';\nimport type { DotJson } from './dot-json';\nimport { DOT_JSON_FILE, readDotJson } from './dot-json';\nimport { listStatics } from './statics';\n\nexport const DOT_FILE = 'dot.ts';\nexport const PAGES_DIR = 'pages';\nconst PAGE_FILES = {\n view: 'view.dml',\n state: 'state.ts',\n controller: 'controller.ts',\n} as const;\n\nexport interface PageSource {\n // The page's folder under `pages/`, such as `edsa-meter/confirmation`.\n readonly path: string;\n // The id pages navigate to. It's `definePage({ id })` if set, or else the path.\n readonly id: string;\n readonly view: string;\n readonly state: string;\n readonly controller: string;\n}\n\nexport interface Project {\n readonly root: string;\n // Already checked.\n readonly dotJson: DotJson;\n // The path of dot.ts, which has `export default defineDot({ pages, theme, plugins, hooks })`.\n readonly dot: string;\n // In the order of `defineDot({ pages })`. The first is the entry page.\n readonly pages: readonly PageSource[];\n // The files under statics/, such as `statics/logo.png`.\n readonly statics: readonly string[];\n}\n\nexport async function loadProject(root: string): Promise<Project> {\n root = resolve(root);\n const dotJsonFile = join(root, DOT_JSON_FILE);\n if (!existsSync(dotJsonFile)) {\n throw new CompileError(`There is no ${DOT_JSON_FILE} in this folder`, root);\n }\n const dotJson = await readDotJson(dotJsonFile);\n const dotFile = join(root, DOT_FILE);\n if (!existsSync(dotFile)) {\n throw new CompileError(\n `There is no ${DOT_FILE}. Add one: export default defineDot({ pages: [...] })`,\n root,\n );\n }\n const { pages } = parseDotModule(await readFile(dotFile, 'utf8'), dotFile);\n\n const sources = await Promise.all(pages.map((path) => loadPage(root, path, dotFile)));\n const pagesByLowercaseId = new Map<string, PageSource>();\n for (const page of sources) {\n const other = pagesByLowercaseId.get(page.id.toLowerCase());\n if (other) {\n // Point at where the clashing id is written. That's controller.ts for a custom id, or dot.ts\n // when both ids are folder names.\n let file = dotFile;\n if (page.id !== page.path) {\n file = page.controller;\n } else if (other.id !== other.path) {\n file = other.controller;\n }\n throw new CompileError(\n `Page id \"${page.id}\" (${page.path}) is already used by ${other.path}`,\n file,\n );\n }\n pagesByLowercaseId.set(page.id.toLowerCase(), page);\n }\n return { root, dotJson, dot: dotFile, pages: sources, statics: await listStatics(root) };\n}\n\nasync function loadPage(root: string, path: string, dotFile: string): Promise<PageSource> {\n const pageDir = join(root, PAGES_DIR, path);\n const files = {\n view: join(pageDir, PAGE_FILES.view),\n state: join(pageDir, PAGE_FILES.state),\n controller: join(pageDir, PAGE_FILES.controller),\n };\n const missing = Object.values(files).filter((file) => !existsSync(file));\n if (missing.length > 0) {\n throw new CompileError(`Page \"${path}\" is missing ${missing.join(', ')}`, dotFile);\n }\n const { id } = parseLogicModule(await readFile(files.controller, 'utf8'), files.controller);\n return { path, id: id ?? path, ...files };\n}\n","import type { PublicEnv } from './project/env';\nimport type { Project } from './project/project';\n\nexport const RUNTIME_PACKAGE = '@monimesl/dot-runtime';\n\nconst RUNTIME_MODULES = {\n ui: `${RUNTIME_PACKAGE}/ui`,\n logic: `${RUNTIME_PACKAGE}/logic`,\n renderer: `${RUNTIME_PACKAGE}/react`,\n} as const;\n\nexport const ENTRY = { ui: 'dot:ui', logic: 'dot:logic' } as const;\n\n// The dot's public configuration, which the global `env` imports.\nexport const ENV_MODULE = 'dot:env';\n\nexport const viewModuleId = (id: string) => `dot:view/${id}`;\n\nfunction literal(value: string): string {\n return JSON.stringify(value);\n}\n\n// `{ \"<page id>\": <importName><index>, ... }`\nfunction pageTable(project: Project, importName: string): string {\n const rows = project.pages.map(\n (page, index) => `\\n ${literal(page.id)}: ${importName}${index},`,\n );\n return `{${rows.join('')}\\n }`;\n}\n\n// Given the components the pages use, the renderer bundles only those. Otherwise it bundles all.\nexport function uiEntry(project: Project, components?: readonly string[]): string {\n const rendererModule = literal(RUNTIME_MODULES.renderer);\n let renderer: string[];\n if (components) {\n const componentList = components.join(', ');\n renderer = [\n `import { createReactRenderer, ${componentList} } from ${rendererModule};`,\n `const createRenderer = () => createReactRenderer({ components: { ${componentList} } });`,\n ];\n } else {\n renderer = [`import createRenderer from ${rendererModule};`];\n }\n return [\n `import { runWebview } from ${literal(RUNTIME_MODULES.ui)};`,\n ...renderer,\n ...project.pages.map(\n (page, index) => `import view${index} from ${literal(viewModuleId(page.id))};`,\n ),\n '',\n // While developing, this runs again on each hot reload and the running webview swaps it in.\n 'runWebview({',\n ' renderer: createRenderer,',\n ` views: ${pageTable(project, 'view')},`,\n '});',\n '',\n ].join('\\n');\n}\n\nexport function logicEntry(project: Project, { strict }: { strict: boolean }): string {\n const options = [' dot,', ` pages: ${pageTable(project, 'page')},`];\n if (strict) {\n options.push(' strict: true,');\n }\n return [\n `import { runService } from ${literal(RUNTIME_MODULES.logic)};`,\n `import dot from ${literal(project.dot)};`,\n ...project.pages.map((page, index) => `import page${index} from ${literal(page.controller)};`),\n '',\n // While developing, this runs again on each hot reload and the running service swaps it in.\n 'runService({',\n ...options,\n '});',\n '',\n ].join('\\n');\n}\n\nexport function envModule(env: PublicEnv): string {\n return `export const env = Object.freeze(${JSON.stringify(env, null, 2)});\\n`;\n}\n","import { realpathSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\n\nimport type { Plugin } from 'rolldown';\nimport { unboundReferences } from '@monimesl/dot-script-parser';\n\nimport { ENV_MODULE } from './entries';\nimport { PAGES_DIR } from './project/project';\n\nexport const DOT_GLOBALS = {\n '@monimesl/dot-runtime': ['definePage', 'defineDot', 'createEvent', 'dash'],\n [ENV_MODULE]: ['env'],\n} as const satisfies Record<string, readonly string[]>;\n\nconst SCRIPT_FILE = /\\.[cm]?[jt]sx?$/;\n\n// Adds imports for the globals each module of a dot uses. Pages must use `this.dash` instead of the\n// global `dash`, because its calls stop when the page closes.\nexport function dotGlobals(root: string): Plugin {\n // The bundler names modules by their real path, such as /private/var/… for /var/… on macOS.\n const realRoot = realpathSync(root);\n const isDotModule = (id: string) =>\n id.startsWith(realRoot + sep) &&\n !id.includes(`${sep}node_modules${sep}`) &&\n SCRIPT_FILE.test(id);\n const isPageModule = (id: string) => id.startsWith(join(realRoot, PAGES_DIR) + sep);\n return {\n name: 'dot:globals',\n transform(code, id) {\n if (!isDotModule(id)) {\n return null;\n }\n const used = new Set(unboundReferences(code, Object.values(DOT_GLOBALS).flat(), id));\n if (isPageModule(id) && used.has('dash')) {\n this.error(\n `${relative(realRoot, id)} uses the global \\`dash\\`. In a page, use \\`this.dash\\` in actions ` +\n 'and hooks, so its calls stop when the page closes.',\n );\n }\n const imports: string[] = [];\n for (const [source, names] of Object.entries(DOT_GLOBALS)) {\n const imported = names.filter((name) => used.has(name));\n if (imported.length > 0) {\n imports.push(`import { ${imported.join(', ')} } from ${JSON.stringify(source)};`);\n }\n }\n if (imports.length === 0) {\n return null;\n }\n return { code: `${code}\\n${imports.join('\\n')}\\n`, map: null };\n },\n };\n}\n","import { join } from 'node:path';\nimport { rm } from 'node:fs/promises';\n\nimport type { Plugin } from 'rolldown';\nimport { rolldown } from 'rolldown';\nimport { esmExternalRequirePlugin } from 'rolldown/plugins';\n\nimport { dotGlobals } from '../globals';\nimport { DOT_JSON_FILE } from '../project/dot-json';\n\ninterface BundleOptions {\n root: string;\n modules: ReadonlyMap<string, string>;\n entry: string;\n outDir: string;\n fileName: string;\n format: 'esm' | 'iife';\n mode: 'production' | 'development';\n minify: boolean;\n conditions: readonly string[];\n // Imports left for the page to resolve, such as React, which hosts serve.\n external: readonly string[];\n}\n\n// Bundles one entry with rolldown, replacing `outDir`. Returns the written files.\nexport async function bundle(options: BundleOptions): Promise<string[]> {\n await rm(options.outDir, { recursive: true, force: true });\n const plugins: Plugin[] = [];\n if (options.external.length > 0) {\n plugins.push(esmExternalRequirePlugin({ external: [...options.external] }));\n }\n plugins.push(generatedModules(options.root, options.modules), dotGlobals(options.root));\n const bundler = await rolldown({\n input: options.entry,\n cwd: options.root,\n platform: 'browser',\n plugins,\n resolve: {\n conditionNames: [...options.conditions, 'browser', 'import', 'require', 'default'],\n },\n transform: { define: { 'process.env.NODE_ENV': JSON.stringify(options.mode) } },\n onLog(level, log, defaultHandler) {\n if (log.code !== 'MODULE_LEVEL_DIRECTIVE') {\n defaultHandler(level, log);\n }\n },\n });\n try {\n const { output } = await bundler.write({\n dir: options.outDir,\n format: options.format,\n entryFileNames: options.fileName,\n sourcemap: options.mode === 'development',\n sourcemapExcludeSources: options.mode === 'production',\n minify: options.minify,\n });\n return output.map((chunk) => join(options.outDir, chunk.fileName));\n } finally {\n await bundler.close();\n }\n}\n\n// Serves generated modules and resolves their imports as if they lived in the project root.\nfunction generatedModules(root: string, modules: ReadonlyMap<string, string>): Plugin {\n const importer = join(root, DOT_JSON_FILE);\n return {\n name: 'dot:generated',\n // The `\\0` prefix marks virtual modules in rolldown, so other plugins leave them alone.\n async resolveId(source, from) {\n if (modules.has(source)) {\n return `\\0${source}`;\n }\n if (!from?.startsWith('\\0dot:')) {\n return null;\n }\n const resolved = await this.resolve(source, importer, { skipSelf: true });\n if (!resolved) {\n this.error(`Can't find \"${source}\" from ${root}. Is it installed?`);\n }\n return resolved;\n },\n load(id) {\n if (!id.startsWith('\\0')) {\n return null;\n }\n return modules.get(id.slice(1)) ?? null;\n },\n };\n}\n","import { readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\n\nimport { CompileError } from '../errors';\nimport { RUNTIME_PACKAGE } from '../entries';\n\nconst RENDERER_PACKAGE = '@monimesl/dot-renderer-react';\n\n// The @monimesl/dot-runtime a project builds with.\nexport interface InstalledRuntime {\n readonly version: string;\n readonly react: ReactHost;\n // The installed React renderer's stylesheet.\n readonly stylesheet: string;\n}\n\n// The React the runtime's renderer uses, which hosts serve rather than each dot bundling it.\nexport interface ReactHost {\n readonly version: string;\n // The built files, in a folder per version: `<dir>/<version>/react.js`.\n readonly dir: string;\n}\n\ninterface InstalledPackage {\n readonly dir: string;\n readonly version: string;\n}\n\nexport function installedRuntime(root: string): InstalledRuntime {\n const runtime = requirePackage(root, RUNTIME_PACKAGE, 'the project');\n const renderer = requirePackage(runtime.dir, RENDERER_PACKAGE, RUNTIME_PACKAGE);\n const react = requirePackage(renderer.dir, 'react', RENDERER_PACKAGE);\n return {\n version: runtime.version,\n react: { version: react.version, dir: join(renderer.dir, 'dist', 'react-host') },\n stylesheet: join(renderer.dir, 'dist', 'styles.css'),\n };\n}\n\nfunction requirePackage(fromDir: string, name: string, installedIn: string): InstalledPackage {\n const require = createRequire(join(fromDir, 'package.json'));\n let packageFile: string;\n try {\n packageFile = require.resolve(`${name}/package.json`);\n } catch {\n throw new CompileError(\n `${name} isn't installed in ${installedIn}. Install the project's dependencies, then try again`,\n fromDir,\n );\n }\n const { version } = JSON.parse(readFileSync(packageFile, 'utf8')) as { version: string };\n return { dir: dirname(packageFile), version };\n}\n","import type { ExprNode } from '@monimesl/dot-script-parser';\n\nexport type Scope = ReadonlyMap<string, string>;\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport const EMPTY_SCOPE: Scope = new Map();\n\nexport function isIdentifier(name: string): boolean {\n return IDENTIFIER.test(name);\n}\n\n// Loop variables read their local; everything else reads page data from `d`.\nexport function printExpr(expr: ExprNode, scope: Scope): string {\n const print = (node: ExprNode) => printExpr(node, scope);\n switch (expr.type) {\n case 'Literal':\n return JSON.stringify(expr.value);\n case 'Identifier':\n return scope.get(expr.name) ?? `d.${expr.name}`;\n case 'Member':\n if (expr.property.type === 'Literal' && typeof expr.property.value === 'string') {\n return `${print(expr.object)}?.${expr.property.value}`;\n }\n return `${print(expr.object)}?.[${print(expr.property)}]`;\n case 'Unary':\n if (expr.operator === 'typeof') {\n return `(typeof ${print(expr.argument)})`;\n }\n return `(${expr.operator}${print(expr.argument)})`;\n case 'Binary':\n return `(${print(expr.left)} ${expr.operator} ${print(expr.right)})`;\n case 'Conditional':\n return `(${print(expr.test)} ? ${print(expr.consequent)} : ${print(expr.alternate)})`;\n }\n}\n\nexport function stateReads(expr: ExprNode, scope: Scope): string[] {\n const reads = (node: ExprNode) => stateReads(node, scope);\n switch (expr.type) {\n case 'Literal':\n return [];\n case 'Identifier':\n return scope.has(expr.name) ? [] : [expr.name];\n case 'Member':\n return [...reads(expr.object), ...reads(expr.property)];\n case 'Unary':\n return reads(expr.argument);\n case 'Binary':\n return [...reads(expr.left), ...reads(expr.right)];\n case 'Conditional':\n return [...reads(expr.test), ...reads(expr.consequent), ...reads(expr.alternate)];\n }\n}\n","import type { ComponentManifest } from '@monimesl/dot-core';\nimport type { DmlElementNode } from '@monimesl/dot-dml-parser';\n\nimport type { ViewCompiler } from './compiler';\nimport { isIdentifier, type Scope } from './expression';\n\nexport const CONTROL_FLOW_TAGS: Readonly<\n Record<string, { readonly attributes: readonly string[]; readonly required: readonly string[] }>\n> = {\n If: { attributes: ['condition'], required: ['condition'] },\n ElseIf: { attributes: ['condition'], required: ['condition'] },\n Else: { attributes: [], required: [] },\n For: { attributes: ['each', 'item', 'index', 'key'], required: ['each'] },\n};\n\n// Compiles sibling <If>, <ElseIf>s and an optional <Else> to `...(a ? [...] : b ? [...] : [...])`.\nexport function compileConditional(\n compiler: ViewCompiler,\n branches: readonly DmlElementNode[],\n parent: ComponentManifest | null,\n scope: Scope,\n): string {\n let code = '[]';\n for (const branch of [...branches].reverse()) {\n const body = `[${compiler.compile(branch.children, parent, scope).join(', ')}]`;\n compiler.checkControlFlowElementAttributes(branch);\n if (branch.tag === 'Else') {\n code = body;\n } else {\n const condition = compiler.compileSingleBinding(branch, 'condition', scope);\n code = `${condition} ? ${body} : ${code}`;\n }\n }\n return `...(${code})`;\n}\n\n// Compiles `<For each=\"{{ list }}\" item index key>` to `each(list, (item, index) => [...], key?)`.\nexport function compileLoop(\n compiler: ViewCompiler,\n node: DmlElementNode,\n parent: ComponentManifest | null,\n scope: Scope,\n): string {\n compiler.checkControlFlowElementAttributes(node);\n const list = compiler.compileSingleBinding(node, 'each', scope);\n const { item = 'item', index = 'index', key } = node.attributes;\n\n const checkVariableName = (attribute: string, name: string) => {\n if (!isIdentifier(name)) {\n compiler.fail(`<For> \\`${attribute}\\` must be a variable name, got \"${name}\"`, node.loc);\n }\n };\n checkVariableName('item', item);\n checkVariableName('index', index);\n if (item === index) {\n compiler.fail('<For> `item` and `index` need different names', node.loc);\n }\n // Loop variables get a `$` prefix so they never clash with names in the generated code.\n const itemVariable = '$' + item;\n const indexVariable = '$' + index;\n const loopScope = new Map(scope);\n loopScope.set(item, itemVariable);\n loopScope.set(index, indexVariable);\n const body = compiler.compile(node.children, parent, loopScope).join(', ');\n const eachArguments = [list, `(${itemVariable}, ${indexVariable}) => [${body}]`];\n if (key === undefined) {\n compiler.warn(\n '<For> has no `key`, so items are matched by position. If items can move, ' +\n 'add key=\"<property>\" or key=\"*this\". To keep matching by position, add key=\"*index\".',\n node.loc,\n );\n } else if (key === '*index') {\n // Matching by position is what `each` does without a key.\n } else if (key === '*this') {\n eachArguments.push(`(${itemVariable}) => ${itemVariable}`);\n } else if (isIdentifier(key)) {\n eachArguments.push(`(${itemVariable}) => ${itemVariable}?.${key}`);\n } else {\n compiler.fail(`<For> \\`key\\` must be a property name, *this or *index, got \"${key}\"`, node.loc);\n }\n return `each(${eachArguments.join(', ')})`;\n}\n","import {\n builtinRegistry,\n eventName,\n type ComponentManifest,\n type ComponentRegistry,\n isWordsOr,\n otherThanWords,\n type PropType,\n type WordsOr,\n type SourceLocation,\n} from '@monimesl/dot-core';\nimport type { DmlElementNode, DmlNode } from '@monimesl/dot-dml-parser';\nimport { type ExprNode, parseExpression, ScriptParseError } from '@monimesl/dot-script-parser';\n\nimport { CompileError, CompileWarning } from '../errors';\nimport { STATICS_DIR } from '../project/statics';\nimport { quotedList } from '../utils';\nimport { compileConditional, compileLoop, CONTROL_FLOW_TAGS } from './control-flow';\nimport { EMPTY_SCOPE, isIdentifier, printExpr, type Scope, stateReads } from './expression';\n\nexport interface ViewContext {\n file: string;\n components?: ComponentRegistry | undefined;\n // The mutations and actions in controller.ts. Each event attribute must name one.\n handlers?: readonly string[] | undefined;\n // The keys in state.ts. Leave it out to skip the check.\n stateKeys?: readonly string[] | undefined;\n // The files under statics/, such as `statics/logo.png`. Any other statics/ path is an error.\n statics?: readonly string[] | undefined;\n onWarning?: ((warning: CompileWarning) => void) | undefined;\n // Called with the name of each component the markup uses.\n onComponent?: ((name: string) => void) | undefined;\n}\n\n// Every page's markup is one root <View>. Unless the markup says otherwise, it fills the page and\n// puts space at the page's edges and between its children.\nexport const ROOT_TAG = 'View';\nconst ROOT_DEFAULTS = { padding: 'large', gap: 'large', grow: true };\n\ntype Segment = { kind: 'static'; value: string } | { kind: 'binding'; code: string };\nconst SEGMENT_BINDING_REGEXP = /{{([\\s\\S]*?)}}/g;\n\nexport const DATA_PREFIX = 'data-';\nconst DATA_ATTRIBUTE = /^data-[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n// A colour named in the theme, such as `gold` or `brandBlue`.\nconst THEME_COLOR_NAME = /^[a-z][a-zA-Z0-9]*$/;\n\nexport class ViewCompiler {\n readonly #context: ViewContext;\n readonly #components: ComponentRegistry;\n\n constructor(context: ViewContext) {\n this.#context = context;\n this.#components = context.components ?? builtinRegistry;\n for (const name of Object.keys(CONTROL_FLOW_TAGS)) {\n if (name in this.#components) {\n this.fail(`<${name}> is reserved for control flow`);\n }\n }\n }\n\n compile(nodes: readonly DmlNode[], parent: ComponentManifest | null, scope: Scope): string[] {\n const compiled: string[] = [];\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!;\n if (node.type === 'Text') {\n compiled.push(...this.#compileText(node.content, parent, scope, node.loc));\n continue;\n }\n switch (node.tag) {\n case 'If': {\n const branches = ifChain(node, nodes.slice(i + 1));\n compiled.push(compileConditional(this, branches, parent, scope));\n // Skip the <ElseIf> and <Else> siblings the chain took in.\n i += branches.length - 1;\n break;\n }\n case 'ElseIf':\n case 'Else':\n return this.fail(`<${node.tag}> must come right after <If> or <ElseIf>`, node.loc);\n case 'For':\n compiled.push(compileLoop(this, node, parent, scope));\n break;\n default:\n compiled.push(`h(${this.#compileElementArgs(node, parent, scope).join(', ')})`);\n }\n }\n return compiled;\n }\n\n #compileText(\n content: string,\n parent: ComponentManifest | null,\n scope: Scope,\n loc?: SourceLocation,\n ): string[] {\n if (parent?.children !== 'text') {\n // A space between two elements in a column or a row is only markup.\n if (content.trim() === '') {\n return [];\n }\n // List <Text> first, since that's what loose text usually needs.\n const inline = Object.values(this.#components)\n .filter((component) => component.inline && component.children === 'text')\n .sort((a, b) => Number(b.name === 'Text') - Number(a.name === 'Text'));\n const wrappers = inline.map((component) => `<${component.name}>`).join(' or ');\n this.fail(`'${content}' must be inside ${wrappers || 'an inline component'}`, loc);\n }\n return this.#compileAsSegments(content, scope, loc).map(printSegment);\n }\n\n // Returns the arguments of the `h` call for the page's root <View>.\n compileRoot(nodes: readonly DmlNode[]): string[] {\n if (!this.#components[ROOT_TAG]) {\n this.fail(`The components must include <${ROOT_TAG}>, which is the root of every page`);\n }\n const [root, outside] = nodes;\n if (root?.type !== 'Element' || root.tag !== ROOT_TAG) {\n return this.fail(`A page must have one <${ROOT_TAG}> around everything else`, root?.loc);\n }\n if (outside) {\n const name = outside.type === 'Text' ? `'${outside.content}'` : `<${outside.tag}>`;\n this.fail(`${name} must be inside the page's <${ROOT_TAG}>`, outside.loc);\n }\n return this.#compileElementArgs(root, null, EMPTY_SCOPE, ROOT_DEFAULTS);\n }\n\n #compileElementArgs(\n node: DmlElementNode,\n parent: ComponentManifest | null,\n scope: Scope,\n defaults: Readonly<Record<string, unknown>> = {},\n ): string[] {\n const component = this.#components[node.tag];\n if (!component) {\n return this.fail(`Unknown component <${node.tag}>`, node.loc);\n }\n this.#context.onComponent?.(component.name);\n if (parent && !canHaveChildren(parent, component)) {\n this.fail(`<${node.tag}> can't go inside <${parent.name}>`, node.loc);\n }\n for (const { prop, ignores, because } of component.overrides ?? []) {\n if (prop in node.attributes && ignores in node.attributes) {\n this.warn(\n `<${component.name}> ignores \\`${ignores}\\` with \\`${prop}\\`: ${because}`,\n node.loc,\n );\n }\n }\n const dataAttributes: [string, string][] = [];\n const propAttributes: [string, string][] = [];\n for (const [name, value] of Object.entries(node.attributes)) {\n if (name.startsWith(DATA_PREFIX)) {\n dataAttributes.push([name, value]);\n } else {\n propAttributes.push([name, value]);\n }\n }\n const data = this.#compileData(dataAttributes, scope, node.loc);\n const props: string[] = [];\n for (const [name, value] of propAttributes) {\n props.push(this.#compileProp(component, name, value, scope, node.loc));\n }\n for (const [name, handler] of Object.entries(node.events)) {\n props.push(this.#compileEvent(component, name, handler, data, node.loc));\n }\n for (const [name, value] of Object.entries(defaults)) {\n if (!(name in node.attributes)) {\n props.push(`${name}: ${JSON.stringify(value)}`);\n }\n }\n return [\n JSON.stringify(component.name),\n props.length ? `{ ${props.join(', ')} }` : 'null',\n ...this.compile(node.children, component, scope),\n ];\n }\n\n #compileProp(\n component: ComponentManifest,\n name: string,\n value: string,\n scope: Scope,\n loc?: SourceLocation,\n ): string {\n const type = component.props[name];\n if (!type) {\n return this.fail(`<${component.name}> has no \\`${name}\\` attribute`, loc);\n }\n const segments = this.#compileAsSegments(value, scope, loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode !== null) {\n return `${name}: ${bindingCode}`;\n }\n if (segments.every((segment) => segment.kind === 'static')) {\n this.#checkStaticsReference(value, loc);\n return `${name}: ${this.#compileLiteral(type, value, loc)}`;\n }\n if (type !== 'string' && type !== 'any') {\n const kind = typeof type === 'string' ? `a ${type}` : 'an enum';\n this.fail(`\\`${name}\\` is ${kind}, so set it with one {{ }} binding`, loc);\n }\n return `${name}: ${segments.map(printSegment).join(' + ')}`;\n }\n\n // `data-account-id=\"{{ account.id }}\"` becomes `{ accountId: d.account.id }`, which the element's\n // events carry to their handlers.\n #compileData(\n attributes: readonly [string, string][],\n scope: Scope,\n loc?: SourceLocation,\n ): string | null {\n if (attributes.length === 0) {\n return null;\n }\n const entries = attributes.map(([name, value]) => {\n if (!DATA_ATTRIBUTE.test(name)) {\n this.fail(`\\`${name}\\` must be lowercase words joined by -, such as data-account-id`, loc);\n }\n return `${dataKey(name)}: ${this.#compileDataValue(value, scope, loc)}`;\n });\n return `{ ${entries.join(', ')} }`;\n }\n\n // A single binding keeps its value's type, such as a number. Anything else becomes a string.\n #compileDataValue(value: string, scope: Scope, loc?: SourceLocation): string {\n const segments = this.#compileAsSegments(value, scope, loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode !== null) {\n return bindingCode;\n }\n if (segments.length === 0) {\n return '\"\"';\n }\n return segments.map(printSegment).join(' + ');\n }\n\n #checkStaticsReference(value: string, loc: SourceLocation | undefined): void {\n const { statics } = this.#context;\n if (statics && value.startsWith(`${STATICS_DIR}/`) && !statics.includes(value)) {\n this.fail(`\"${value}\" isn't in ${STATICS_DIR}/`, loc);\n }\n }\n\n #compileEvent(\n component: ComponentManifest,\n attribute: string,\n handler: string,\n data: string | null,\n loc?: SourceLocation,\n ): string {\n const event = eventName(attribute);\n if (!component.events.includes(event)) {\n this.fail(`<${component.name}> has no \\`${attribute}\\` event`, loc);\n }\n if (!isIdentifier(handler)) {\n this.fail(\n `\\`${attribute}\\` must name a mutation or action in controller.ts, got \"${handler}\"`,\n loc,\n );\n }\n const { handlers } = this.#context;\n if (handlers && !handlers.includes(handler)) {\n this.fail(`\\`${handler}\\` isn't a mutation or action in controller.ts`, loc);\n }\n const args = data ? `${JSON.stringify(handler)}, ${data}` : JSON.stringify(handler);\n return `${attribute}: on(${args})`;\n }\n\n checkControlFlowElementAttributes(node: DmlElementNode): void {\n const { attributes: allowed, required } = CONTROL_FLOW_TAGS[node.tag]!;\n const [event] = Object.keys(node.events);\n if (event) {\n this.fail(\n `<${node.tag}> can't handle events such as \\`${event}\\`. ` +\n 'Put the handler on a component inside it.',\n node.loc,\n );\n }\n for (const name of Object.keys(node.attributes)) {\n if (!allowed.includes(name)) {\n this.fail(`<${node.tag}> has no \\`${name}\\` attribute`, node.loc);\n }\n }\n for (const name of required) {\n if (!(name in node.attributes)) {\n this.fail(`<${node.tag}> requires \\`${name}\\``, node.loc);\n }\n }\n }\n\n compileSingleBinding(node: DmlElementNode, attribute: string, scope: Scope): string {\n const segments = this.#compileAsSegments(node.attributes[attribute] ?? '', scope, node.loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode === null) {\n return this.fail(`<${node.tag}> \\`${attribute}\\` must be one {{ }} binding`, node.loc);\n }\n return bindingCode;\n }\n\n #compileLiteral(type: PropType, value: string, loc?: SourceLocation): string {\n if (isWordsOr(type)) {\n return this.#compileWordOr(type, value, loc);\n }\n if (typeof type !== 'string') {\n if (type.includes(value)) {\n return JSON.stringify(value);\n }\n return this.fail(`Expected one of ${quotedList(type)}, got \"${value}\"`, loc);\n }\n switch (type) {\n case 'boolean':\n if (value === '' || value === 'true') {\n return 'true';\n }\n if (value === 'false') {\n return 'false';\n }\n return this.fail(`Expected true or false, got \"${value}\"`, loc);\n case 'number':\n if (isNumberText(value)) {\n return String(Number(value));\n }\n return this.fail(`Expected a number, got \"${value}\"`, loc);\n case 'string':\n case 'any':\n return JSON.stringify(value);\n }\n }\n\n // A word, or else a number or the name of a colour in the dot's theme. A name is checked when the\n // page shows, since the theme is set in dot.ts at run time.\n #compileWordOr(type: WordsOr, value: string, loc?: SourceLocation): string {\n if (type.words.includes(value)) {\n return JSON.stringify(value);\n }\n if (type.or === 'number' && isNumberText(value)) {\n return String(Number(value));\n }\n if (type.or === 'themeColor' && THEME_COLOR_NAME.test(value)) {\n return JSON.stringify(value);\n }\n return this.fail(\n `Expected one of ${quotedList(type.words)}, or ${otherThanWords(type)}, got \"${value}\"`,\n loc,\n );\n }\n\n #compileAsSegments(input: string, scope: Scope, loc?: SourceLocation): Segment[] {\n const segments: Segment[] = [];\n let last = 0;\n for (const match of input.matchAll(SEGMENT_BINDING_REGEXP)) {\n if (match.index > last) {\n segments.push({ kind: 'static', value: input.slice(last, match.index) });\n }\n const expr = this.#parseBindingExpression(match[1]!, scope, loc);\n segments.push({ kind: 'binding', code: printExpr(expr, scope) });\n last = match.index + match[0].length;\n }\n const rest = input.slice(last);\n if (rest.includes('{{')) {\n this.fail('A binding is missing its closing `}}`', loc);\n }\n if (rest) {\n segments.push({ kind: 'static', value: rest });\n }\n return segments;\n }\n\n #parseBindingExpression(source: string, scope: Scope, loc?: SourceLocation): ExprNode {\n let expr: ExprNode;\n try {\n expr = parseExpression(source);\n } catch (error) {\n if (!(error instanceof ScriptParseError)) {\n throw error;\n }\n return this.fail(`Invalid binding \\`{{${source}}}\\`: ${error.reason}`, loc);\n }\n const { stateKeys } = this.#context;\n if (stateKeys) {\n const undeclared = stateReads(expr, scope).find((name) => !stateKeys.includes(name));\n if (undeclared) {\n const declared = stateKeys.join(', ') || 'none';\n this.fail(`\\`${undeclared}\\` isn't in state.ts. It has: ${declared}`, loc);\n }\n }\n return expr;\n }\n\n warn(message: string, loc?: SourceLocation): void {\n this.#context.onWarning?.(new CompileWarning(message, this.#context.file, loc));\n }\n\n fail(message: string, loc?: SourceLocation): never {\n throw new CompileError(message, this.#context.file, loc);\n }\n}\n\n// The <If>, then the <ElseIf> and <Else> siblings that continue it.\nfunction ifChain(ifNode: DmlElementNode, nextSiblings: readonly DmlNode[]): DmlElementNode[] {\n const branches = [ifNode];\n for (const sibling of nextSiblings) {\n if (branches.at(-1)!.tag === 'Else' || !continuesIf(sibling)) {\n break;\n }\n branches.push(sibling);\n }\n return branches;\n}\n\nfunction continuesIf(node: DmlNode): node is DmlElementNode {\n return node.type === 'Element' && (node.tag === 'ElseIf' || node.tag === 'Else');\n}\n\nfunction singleBindingCode(segments: readonly Segment[]): string | null {\n const [first] = segments;\n if (segments.length === 1 && first?.kind === 'binding') {\n return first.code;\n }\n return null;\n}\n\n// `data-account-id` -> `accountId`\nexport function dataKey(attribute: string): string {\n const [first = '', ...rest] = attribute.slice(DATA_PREFIX.length).split('-');\n return first + rest.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join('');\n}\n\nfunction printSegment(segment: Segment): string {\n return segment.kind === 'static' ? JSON.stringify(segment.value) : `text(${segment.code})`;\n}\n\nexport function canHaveChildren(parent: ComponentManifest, child: ComponentManifest): boolean {\n switch (parent.children) {\n case 'none':\n return false;\n case 'text':\n return child.inline === true;\n case 'elements':\n return true;\n }\n}\n\nfunction isNumberText(value: string): boolean {\n return value.trim() !== '' && Number.isFinite(Number(value));\n}\n","import { parseDmlToIR } from '@monimesl/dot-dml-parser';\n\nimport { ViewCompiler, type ViewContext } from './compiler';\n\n// Compiles markup to a module whose render function builds the root <View> with the renderer's `h`.\nexport function compileView(source: string, context: ViewContext): string {\n const nodes = parseDmlToIR(source, {\n locations: true,\n file: context.file,\n whitespace: 'inline',\n });\n const compiler = new ViewCompiler(context);\n const rootArguments = compiler.compileRoot(nodes);\n const rootArgumentLines = rootArguments.map((argument) => `\\n ${argument},`).join('');\n return [\n 'export default function render(d, { h, on, text, each }) {',\n ` return h(${rootArgumentLines}\\n );`,\n '}',\n '',\n ].join('\\n');\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nimport type { PublicEnv } from './project/env';\nimport type { Project } from './project/project';\n\nconst PAGE_TYPES_FILE = '.dot/pages.d.ts';\nconst ENV_TYPES_FILE = '.dot/env.d.ts';\n\n// Page ids, so navigation targets are typed.\nexport async function writePageTypes(project: Project): Promise<string> {\n const members = project.pages.map((page) => `${JSON.stringify(page.id)}: true;`);\n return writeIfChanged(\n join(project.root, PAGE_TYPES_FILE),\n globalInterface('dot.ts', 'DotPageIds', members),\n );\n}\n\n// The names in the global `env`, so a misspelled one is a type error.\nexport async function writeEnvTypes(project: Project, env: PublicEnv): Promise<string> {\n const members = Object.keys(env).map((name) => `readonly ${name}: string;`);\n return writeIfChanged(\n join(project.root, ENV_TYPES_FILE),\n globalInterface('the variables in .env files', 'DotPublicEnv', members),\n );\n}\n\n// A declaration file that fills in one of the runtime's global interfaces.\nfunction globalInterface(source: string, name: string, members: readonly string[]): string {\n return [\n `// Generated by dotctl from ${source}. Do not edit.`,\n 'declare global {',\n ` interface ${name} {`,\n ...members.map((member) => ` ${member}`),\n ' }',\n '}',\n '',\n 'export {};',\n '',\n ].join('\\n');\n}\n\n// Leaves an unchanged file alone, so editors and watchers don't see a change.\nasync function writeIfChanged(file: string, content: string): Promise<string> {\n const current = await readFile(file, 'utf8').catch(() => null);\n if (current !== content) {\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, content);\n }\n return file;\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseEnv } from 'node:util';\n\nimport { CompileError } from '../errors';\n\n// Every variable in the .env files ships inside the dot, where anyone with the dot can read it.\n// Never put a secret in them.\nconst PUBLIC_ENV_NAME = /^[A-Z][A-Z0-9_]*$/;\n\nexport type PublicEnv = Readonly<Record<string, string>>;\n\n// Reads `.env`, then `.env.<mode>`, and the later file wins. The shell can override a variable the\n// files declare, so CI can set a value. It can't add one, so PATH or a CI secret stays out.\nexport async function loadPublicEnv(\n root: string,\n mode: string,\n shellEnv: Readonly<Record<string, string | undefined>> = process.env,\n): Promise<PublicEnv> {\n const env: Record<string, string> = {};\n for (const fileName of ['.env', `.env.${mode}`]) {\n const file = join(root, fileName);\n if (existsSync(file)) {\n addVariables(env, parseEnv(await readFile(file, 'utf8')), file);\n }\n }\n // Sorted, so the bundle and the generated types don't change with the order of the files.\n const sorted: Record<string, string> = {};\n for (const name of Object.keys(env).sort()) {\n sorted[name] = shellEnv[name] ?? env[name]!;\n }\n return sorted;\n}\n\nfunction addVariables(\n env: Record<string, string>,\n variables: Readonly<Record<string, string | undefined>>,\n file: string,\n): void {\n for (const [name, value] of Object.entries(variables)) {\n if (value === undefined) {\n continue;\n }\n if (!PUBLIC_ENV_NAME.test(name)) {\n throw new CompileError(\n `\"${name}\" must be capital letters, digits and underscores, starting with a letter`,\n file,\n );\n }\n env[name] = value;\n }\n}\n","import { copyFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\n\nimport { zipSync } from 'fflate';\n\nimport type { ComponentManifest, ComponentRegistry } from '@monimesl/dot-core';\nimport {\n REACT_HOST_MODULES,\n builtinComponents,\n componentRegistry,\n reactHostUrl,\n} from '@monimesl/dot-core';\nimport { parseLogicModule, parseStateModule } from '@monimesl/dot-script-parser';\n\nimport { bundle } from './bundle';\nimport type { InstalledRuntime } from './packages';\nimport { installedRuntime } from './packages';\nimport { compileView } from '../view';\nimport type { ViewContext } from '../view';\nimport { writeEnvTypes, writePageTypes } from '../types';\nimport type { PublicEnv } from '../project/env';\nimport { loadPublicEnv } from '../project/env';\nimport type { CompileWarning } from '../errors';\nimport type { DotJson } from '../project/dot-json';\nimport type { PageSource, Project } from '../project/project';\nimport { loadProject } from '../project/project';\nimport { ENTRY, ENV_MODULE, envModule, logicEntry, uiEntry, viewModuleId } from '../entries';\n\nconst MANIFEST_FILE = 'manifest.json';\nconst STYLES_FILE = 'dot.css';\n// The earliest date a ZIP file can hold.\nconst ARCHIVE_DATE = new Date(1980, 0, 1);\n\nexport interface BuildOptions {\n root: string;\n // Defaults to `<root>/dist`.\n outDir?: string | undefined;\n // `production` (the default) is minified. `development` isn't, so it reads well in a debugger.\n mode?: 'production' | 'development' | undefined;\n components?: readonly ComponentManifest[] | undefined;\n conditions?: readonly string[] | undefined;\n}\n\nexport interface BuildResult {\n readonly outDir: string;\n readonly files: readonly string[];\n readonly warnings: readonly CompileWarning[];\n}\n\n/** Compiles and bundles the dot into `outDir` for hosts, and refreshes the types in `.dot/`. */\nexport async function build(options: BuildOptions): Promise<BuildResult> {\n const project = await loadProject(options.root);\n const mode = options.mode ?? 'production';\n const env = await loadPublicEnv(project.root, mode);\n const runtime = installedRuntime(project.root);\n await writePageTypes(project);\n await writeEnvTypes(project, env);\n\n const warnings: CompileWarning[] = [];\n const components = componentRegistry([\n ...Object.values(builtinComponents),\n ...(options.components ?? []),\n ]);\n const modules = await compileModules(project, env, components, mode, warnings);\n\n const outDir = resolve(project.root, options.outDir ?? 'dist');\n const uiDir = join(outDir, 'ui');\n const bundleLayer = (\n entry: string,\n layerDir: string,\n format: 'esm' | 'iife',\n external: readonly string[],\n ) =>\n bundle({\n root: project.root,\n modules,\n entry,\n outDir: layerDir,\n fileName: 'dot.js',\n format,\n mode,\n minify: mode === 'production',\n conditions: options.conditions ?? [],\n external,\n });\n // Each bundle empties its folder first, so the files that go next to it are written after.\n const files = [\n // React stays out of the webview bundle. The host serves it, and the import map points at it.\n ...(await bundleLayer(ENTRY.ui, uiDir, 'esm', Object.keys(REACT_HOST_MODULES))),\n ...(await bundleLayer(ENTRY.logic, join(outDir, 'logic'), 'iife', [])),\n await copyRendererStyles(runtime, uiDir),\n await writeIndexHtml(project, uiDir, runtime.react.version),\n ...(await copyStatics(project, uiDir)),\n await writeManifest(project, outDir, runtime),\n ];\n if (mode === 'production') {\n files.push(await writeArchive(project, outDir, files));\n }\n return { outDir, files, warnings };\n}\n\nasync function copyRendererStyles(runtime: InstalledRuntime, uiDir: string): Promise<string> {\n const file = join(uiDir, STYLES_FILE);\n await mkdir(uiDir, { recursive: true });\n await copyFile(runtime.stylesheet, file);\n return file;\n}\n\n// The build as the one file Dash downloads, `<package>-<version>.zip`, without source maps. Its files\n// all get the same date, so the same build always makes the same archive.\nasync function writeArchive(project: Project, outDir: string, files: string[]): Promise<string> {\n const entries: Record<string, [Uint8Array, { mtime: Date }]> = {};\n for (const file of files) {\n if (!file.endsWith('.map')) {\n const name = relative(outDir, file).split(sep).join('/');\n entries[name] = [await readFile(file), { mtime: ARCHIVE_DATE }];\n }\n }\n const { package: packageName, version } = project.dotJson;\n // Remove archives of earlier versions, which would otherwise pile up.\n for (const name of await readdir(outDir)) {\n if (name.startsWith(`${packageName}-`) && name.endsWith('.zip')) {\n await rm(join(outDir, name));\n }\n }\n const file = join(outDir, `${packageName}-${version}.zip`);\n await writeFile(file, zipSync(entries, { level: 9 }));\n return file;\n}\n\nasync function compileModules(\n project: Project,\n env: PublicEnv,\n components: ComponentRegistry,\n mode: 'production' | 'development',\n warnings: CompileWarning[],\n): Promise<Map<string, string>> {\n const modules = new Map<string, string>();\n const usedComponents = new Set<string>();\n for (const page of project.pages) {\n const view = await compilePage(page, components, project.statics, warnings, usedComponents);\n modules.set(viewModuleId(page.id), view);\n }\n // While developing, a hot reload keeps the renderer, so it has every component a page may add.\n const usedBuiltins = [...usedComponents].filter((name) => name in builtinComponents).sort();\n modules.set(ENTRY.ui, uiEntry(project, mode === 'production' ? usedBuiltins : undefined));\n modules.set(ENTRY.logic, logicEntry(project, { strict: mode === 'development' }));\n modules.set(ENV_MODULE, envModule(env));\n return modules;\n}\n\nasync function writeIndexHtml(\n project: Project,\n uiDir: string,\n reactVersion: string,\n): Promise<string> {\n const file = join(uiDir, 'index.html');\n await mkdir(uiDir, { recursive: true });\n await writeFile(file, indexHtml(project.dotJson.name, reactVersion));\n return file;\n}\n\nasync function copyStatics(project: Project, uiDir: string): Promise<string[]> {\n const copies: string[] = [];\n for (const file of project.statics) {\n const copy = join(uiDir, file);\n await mkdir(dirname(copy), { recursive: true });\n await copyFile(join(project.root, file), copy);\n copies.push(copy);\n }\n return copies;\n}\n\nasync function writeManifest(\n project: Project,\n outDir: string,\n runtime: InstalledRuntime,\n): Promise<string> {\n const file = join(outDir, MANIFEST_FILE);\n const manifest = dotManifest(project, runtime);\n await writeFile(file, `${JSON.stringify(manifest, null, 2)}\\n`);\n return file;\n}\n\n/** What a host needs to run the build: dot.json without `$schema`, where it starts and its pages. */\nexport interface DotManifest extends DotJson {\n // The version of @monimesl/dot-runtime in the bundles, so a host can tell whether it runs them.\n readonly runtime: string;\n // The React version the webview imports from the host.\n readonly react: string;\n readonly entry: string;\n readonly pages: readonly string[];\n}\n\nfunction dotManifest(project: Project, runtime: InstalledRuntime): DotManifest {\n const { id, package: packageName, name, version, permissions, network } = project.dotJson;\n const pages = project.pages.map((page) => page.id);\n return {\n id,\n package: packageName,\n name,\n version,\n runtime: runtime.version,\n react: runtime.react.version,\n permissions,\n network,\n entry: pages[0]!,\n pages,\n };\n}\n\nasync function compilePage(\n page: PageSource,\n components: ComponentRegistry,\n statics: readonly string[],\n warnings: CompileWarning[],\n usedComponents: Set<string>,\n): Promise<string> {\n const [view, state, controller] = await Promise.all([\n readFile(page.view, 'utf8'),\n readFile(page.state, 'utf8'),\n readFile(page.controller, 'utf8'),\n ]);\n const context: ViewContext = {\n file: page.view,\n components,\n statics,\n onWarning: (warning) => warnings.push(warning),\n onComponent: (name) => usedComponents.add(name),\n };\n // State keys are checked only when state.ts is a plain object literal.\n const { keys } = parseStateModule(state, page.state);\n if (keys) {\n context.stateKeys = keys;\n }\n // Handler names are checked only when both lists could be read without running the code.\n const { mutations, actions } = parseLogicModule(controller, page.controller);\n if (mutations && actions) {\n context.handlers = [...mutations, ...actions];\n }\n return compileView(view, context);\n}\n\nfunction indexHtml(title: string, reactVersion: string): string {\n const escaped = title.replace(/[&<>\"]/g, (char) => `&#${char.charCodeAt(0)};`);\n const imports: Record<string, string> = {};\n for (const [name, file] of Object.entries(REACT_HOST_MODULES)) {\n imports[name] = reactHostUrl(reactVersion, file);\n }\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"\n />\n <title>${escaped}</title>\n <link rel=\"stylesheet\" href=\"./${STYLES_FILE}\" />\n <style>\n body {\n margin: 0;\n }\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"importmap\">${JSON.stringify({ imports })}</script>\n <script type=\"module\" src=\"./dot.js\"></script>\n </body>\n</html>\n`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/utils.ts","../src/project/dot-json.ts","../src/project/statics.ts","../src/project/project.ts","../src/entries.ts","../src/globals.ts","../src/build/bundle.ts","../src/build/packages.ts","../src/view/expression.ts","../src/view/control-flow.ts","../src/view/compiler.ts","../src/view/compile.ts","../src/types.ts","../src/project/env.ts","../src/build/build.ts"],"sourcesContent":["import { SourceError } from '@monimesl/dot-core';\n\nexport class CompileError extends SourceError {\n override readonly name = 'CompileError';\n}\n\n/** A problem that does not stop compilation. */\nexport class CompileWarning extends SourceError {\n override readonly name = 'CompileWarning';\n}\n","import { relative, sep } from 'node:path';\n\nexport function quotedList(values: readonly string[]): string {\n return values.map((value) => `\"${value}\"`).join(', ');\n}\n\n// The path from `from` to `to` with `/` between folders, as archives and markup write it.\nexport function relativeSlashPath(from: string, to: string): string {\n return relative(from, to).split(sep).join('/');\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type { DotPermission } from '@monimesl/dot-core';\nimport {\n DEFAULT_DASH_API_VERSION,\n PERMISSIONS,\n isDashApiVersion,\n isNetworkHost,\n isPermission,\n isSemanticVersion,\n} from '@monimesl/dot-core';\n\nimport { CompileError } from '../errors';\nimport { quotedList } from '../utils';\n\nexport const DOT_JSON_FILE = 'dot.json';\n\n// The fields dot.json allows. The runtime's `dot.schema.json` describes the same ones for editors,\n// and a test keeps the two in step.\nexport const DOT_JSON_FIELDS: readonly string[] = [\n 'id',\n '$schema',\n 'package',\n 'name',\n 'version',\n 'permissions',\n 'network',\n 'dash',\n];\nexport const REQUIRED_DOT_JSON_FIELDS: readonly string[] = ['package', 'name', 'version'];\nexport const NETWORK_FIELDS: readonly string[] = ['hosts'];\nexport const DASH_FIELDS: readonly string[] = ['minApiVersion'];\n// Where Dash lists a dot, and how, comes from where the dot is published, not from dot.json.\nconst LISTING_FIELDS: readonly string[] = ['description', 'categories', 'icon'];\n\n// The package name: a reverse domain name, such as `com.mysalone.thing`, that never changes for\n// the life of the dot. Hosts name each dot's web origin after it, so it must also be a valid host\n// name. Each word is up to 63 lowercase letters, digits and inner hyphens. The first word starts\n// with a letter.\nconst PACKAGE_WORD = '[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?';\nexport const DOT_PACKAGE_PATTERN = new RegExp(`^(?=[a-z])${PACKAGE_WORD}(?:\\\\.${PACKAGE_WORD})+$`);\nexport const DOT_PACKAGE_MAX_LENGTH = 128;\n\nexport function isDotPackage(name: string): boolean {\n return name.length <= DOT_PACKAGE_MAX_LENGTH && DOT_PACKAGE_PATTERN.test(name);\n}\n\nexport interface DotJson {\n // The ID Monime gives the dot when it's registered. Only publishing needs it.\n readonly id?: string | undefined;\n readonly package: string;\n readonly name: string;\n readonly version: string;\n // Each permission the dot uses, with the reason Dash shows the person.\n readonly permissions?: Readonly<Partial<Record<DotPermission, string>>> | undefined;\n readonly network?: NetworkAccess | undefined;\n readonly dash?: DashNeeds | undefined;\n}\n\n// What the dot needs from Dash.\nexport interface DashNeeds {\n // The Dash API version, such as \"1.4\": Dash must offer the same major and at least this minor.\n readonly minApiVersion: string;\n}\n\n// Where the dot may send requests with dash.network. Without it, it may send none.\ninterface NetworkAccess {\n // Host names, such as \"api.example.com\", or \"*.example.com\" for any subdomain.\n readonly hosts: readonly string[];\n}\n\nexport async function readDotJson(file: string): Promise<DotJson> {\n let dotJson: unknown;\n try {\n dotJson = JSON.parse(await readFile(file, 'utf8'));\n } catch (error) {\n throw new CompileError(`This isn't valid JSON: ${(error as Error).message}`, file);\n }\n if (!isObject(dotJson)) {\n throw new CompileError(\n 'dot.json must be an object, such as { \"package\": \"com.mysalone.thing\", \"name\": \"My Salone Thing\", \"version\": \"1.0.0\" }',\n file,\n );\n }\n if ('pages' in dotJson) {\n throw new CompileError('List pages in dot.ts, not here: defineDot({ pages: [...] })', file);\n }\n for (const field of LISTING_FIELDS) {\n if (field in dotJson) {\n throw new CompileError(\n `Remove \"${field}\". A dot's description, categories and icon are set where it's published.`,\n file,\n );\n }\n }\n rejectUnknownFields(dotJson, DOT_JSON_FIELDS, file);\n if (\n dotJson.package === undefined &&\n typeof dotJson.id === 'string' &&\n DOT_PACKAGE_PATTERN.test(dotJson.id)\n ) {\n throw new CompileError(`\"${dotJson.id}\" is a package name. Rename \"id\" to \"package\".`, file);\n }\n for (const field of REQUIRED_DOT_JSON_FIELDS) {\n if (dotJson[field] === undefined) {\n throw new CompileError(`\"${field}\" is required`, file);\n }\n }\n\n const { $schema, package: packageName, id, name, version, permissions, network, dash } = dotJson;\n if ($schema !== undefined && typeof $schema !== 'string') {\n throw new CompileError('\"$schema\" must be a string', file);\n }\n if (typeof packageName !== 'string' || !DOT_PACKAGE_PATTERN.test(packageName)) {\n throw new CompileError(\n '\"package\" must be a reverse domain name. Use lowercase words joined by dots, such as \"com.mysalone.thing\".',\n file,\n );\n }\n if (packageName.length > DOT_PACKAGE_MAX_LENGTH) {\n throw new CompileError(`\"package\" must be at most ${DOT_PACKAGE_MAX_LENGTH} characters`, file);\n }\n if (id !== undefined && !isNonEmptyString(id)) {\n throw new CompileError('\"id\" must be the ID Monime gave the dot, as text', file);\n }\n if (!isNonEmptyString(name)) {\n throw new CompileError('\"name\" must be text, and not empty', file);\n }\n if (!isSemanticVersion(version)) {\n throw new CompileError('\"version\" must be a semantic version, such as \"1.0.0\"', file);\n }\n return {\n id,\n package: packageName,\n name,\n version,\n permissions: readPermissions(permissions, file),\n network: readNetworkAccess(network, file),\n dash: readDashNeeds(dash, file),\n };\n}\n\nfunction readDashNeeds(dash: unknown, file: string): DashNeeds | undefined {\n if (dash === undefined) {\n return undefined;\n }\n if (!isObject(dash)) {\n throw new CompileError('\"dash\" must be an object, such as { \"minApiVersion\": \"1.0\" }', file);\n }\n rejectUnknownFields(dash, DASH_FIELDS, file, 'dash');\n const { minApiVersion = DEFAULT_DASH_API_VERSION } = dash;\n if (!isDashApiVersion(minApiVersion)) {\n throw new CompileError(\n '\"dash.minApiVersion\" must be a Dash API version: a major and a minor, such as \"1.0\"',\n file,\n );\n }\n return { minApiVersion };\n}\n\nfunction readPermissions(\n permissions: unknown,\n file: string,\n): Partial<Record<DotPermission, string>> | undefined {\n if (permissions === undefined) {\n return undefined;\n }\n if (!isObject(permissions)) {\n throw new CompileError(\n '\"permissions\" must be an object, such as { \"camera\": \"Scan tickets at the door\" }',\n file,\n );\n }\n for (const [permission, reason] of Object.entries(permissions)) {\n if (!isPermission(permission)) {\n throw new CompileError(\n `Unknown permission \"${permission}\". The permissions are ${quotedList(PERMISSIONS)}`,\n file,\n );\n }\n if (!isNonEmptyString(reason)) {\n throw new CompileError(\n `\"permissions.${permission}\" must say why the dot needs it, such as \"Show your name on receipts\"`,\n file,\n );\n }\n }\n return permissions;\n}\n\nfunction readNetworkAccess(network: unknown, file: string): NetworkAccess | undefined {\n if (network === undefined) {\n return undefined;\n }\n if (!isObject(network)) {\n throw new CompileError(\n '\"network\" must be an object, such as { \"hosts\": [\"api.example.com\"] }',\n file,\n );\n }\n rejectUnknownFields(network, NETWORK_FIELDS, file, 'network');\n const { hosts } = network;\n if (!Array.isArray(hosts) || hosts.length === 0) {\n throw new CompileError(\n '\"network.hosts\" must list the hosts the dot sends requests to, such as [\"api.example.com\"]',\n file,\n );\n }\n const listed: string[] = [];\n for (const host of hosts as unknown[]) {\n if (typeof host !== 'string' || !isNetworkHost(host)) {\n throw new CompileError(\n `\"${String(host)}\" is not a host. Use a lowercase host name, such as \"api.example.com\", ` +\n 'or \"*.example.com\" for all its subdomains. Leave out https://, the port and the path.',\n file,\n );\n }\n if (listed.includes(host)) {\n throw new CompileError(`\"network.hosts\" lists \"${host}\" more than once`, file);\n }\n listed.push(host);\n }\n return { hosts: listed };\n}\n\nfunction rejectUnknownFields(\n object: Record<string, unknown>,\n allowed: readonly string[],\n file: string,\n parent?: string,\n): void {\n for (const field of Object.keys(object)) {\n if (allowed.includes(field)) {\n continue;\n }\n if (parent === undefined) {\n throw new CompileError(\n `Unknown field \"${field}\". The fields allowed are ${quotedList(allowed)}`,\n file,\n );\n }\n throw new CompileError(\n `Unknown field \"${parent}.${field}\". The fields allowed in \"${parent}\" are ${quotedList(allowed)}`,\n file,\n );\n }\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value !== '';\n}\n","import { existsSync } from 'node:fs';\nimport { readdir, readFile, stat } from 'node:fs/promises';\nimport { extname, join } from 'node:path';\n\nimport { CompileError } from '../errors';\nimport { relativeSlashPath } from '../utils';\n\n// Images a dot shows. The build copies them next to the webview as they are, and markup and state\n// refer to them as `statics/<path>`, for example `statics/logo.png`.\nexport const STATICS_DIR = 'statics';\n\nexport const MAX_STATIC_ASSET_BYTES = 1024 * 1024;\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n\n// Raster images only. Each is checked by its first bytes, so a file really is the image its\n// extension says. SVG is left out because it can carry scripts.\nconst IMAGE_FORMATS: Readonly<Record<string, (header: Buffer) => boolean>> = {\n '.png': (header) => header.subarray(0, 8).equals(PNG_SIGNATURE),\n '.jpg': isJpeg,\n '.jpeg': isJpeg,\n '.gif': (header) => ['GIF87a', 'GIF89a'].includes(header.toString('latin1', 0, 6)),\n '.webp': (header) =>\n header.toString('latin1', 0, 4) === 'RIFF' && header.toString('latin1', 8, 12) === 'WEBP',\n};\n\nconst STATIC_ASSET_EXTENSIONS: readonly string[] = Object.keys(IMAGE_FORMATS);\n\n// The images under statics/, as `statics/<path>`. Anything else fails the build.\nexport async function listStatics(root: string): Promise<string[]> {\n const staticsDir = join(root, STATICS_DIR);\n if (!existsSync(staticsDir)) {\n return [];\n }\n const statics: string[] = [];\n for (const entry of await readdir(staticsDir, { recursive: true, withFileTypes: true })) {\n // Hidden files, such as the .DS_Store macOS leaves in folders, are not part of the dot.\n if (!entry.isFile() || entry.name.startsWith('.')) {\n continue;\n }\n const file = join(entry.parentPath, entry.name);\n await checkImage(file, extname(entry.name).toLowerCase());\n statics.push(`${STATICS_DIR}/${relativeSlashPath(staticsDir, file)}`);\n }\n return statics.sort();\n}\n\nasync function checkImage(file: string, extension: string): Promise<void> {\n const isFormat = IMAGE_FORMATS[extension];\n if (!isFormat) {\n throw new CompileError(\n `${STATICS_DIR}/ can only hold images: ${STATIC_ASSET_EXTENSIONS.join(', ')}`,\n file,\n );\n }\n const { size } = await stat(file);\n if (size > MAX_STATIC_ASSET_BYTES) {\n const megabytes = (size / MAX_STATIC_ASSET_BYTES).toFixed(1);\n throw new CompileError(`The image is ${megabytes} MB. Images must be 1 MB or smaller`, file);\n }\n if (!isFormat(await readFile(file))) {\n throw new CompileError(`The file isn't really a ${extension.slice(1)} image`, file);\n }\n}\n\nfunction isJpeg(header: Buffer): boolean {\n return header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff;\n}\n","import { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\n\nimport { parseDotModule, parseLogicModule } from '@monimesl/dot-script-parser';\n\nimport { CompileError } from '../errors';\nimport type { DotJson } from './dot-json';\nimport { DOT_JSON_FILE, readDotJson } from './dot-json';\nimport { listStatics } from './statics';\n\nexport const DOT_FILE = 'dot.ts';\nexport const PAGES_DIR = 'pages';\nconst PAGE_FILES = {\n view: 'view.dml',\n state: 'state.ts',\n controller: 'controller.ts',\n} as const;\n\nexport interface PageSource {\n // The page's folder under `pages/`, such as `edsa-meter/confirmation`.\n readonly path: string;\n // The id pages navigate to. It's `definePage({ id })` if set, or else the path.\n readonly id: string;\n // The options its share link may carry, from `definePage({ share })`, or null if it doesn't share.\n readonly share: readonly string[] | null;\n readonly view: string;\n readonly state: string;\n readonly controller: string;\n}\n\nexport interface Project {\n readonly root: string;\n // Already checked.\n readonly dotJson: DotJson;\n // The path of dot.ts, which has `export default defineDot({ pages, theme, plugins, hooks })`.\n readonly dot: string;\n // In the order of `defineDot({ pages })`. The first is the entry page.\n readonly pages: readonly PageSource[];\n // The files under statics/, such as `statics/logo.png`.\n readonly statics: readonly string[];\n}\n\nexport async function loadProject(root: string): Promise<Project> {\n root = resolve(root);\n const dotJsonFile = join(root, DOT_JSON_FILE);\n if (!existsSync(dotJsonFile)) {\n throw new CompileError(`There is no ${DOT_JSON_FILE} in this folder`, root);\n }\n const dotJson = await readDotJson(dotJsonFile);\n const dotFile = join(root, DOT_FILE);\n if (!existsSync(dotFile)) {\n throw new CompileError(\n `There is no ${DOT_FILE}. Add one: export default defineDot({ pages: [...] })`,\n root,\n );\n }\n const { pages } = parseDotModule(await readFile(dotFile, 'utf8'), dotFile);\n\n const pageSources = await Promise.all(pages.map((path) => loadPage(root, path, dotFile)));\n const pagesByLowercaseId = new Map<string, PageSource>();\n for (const page of pageSources) {\n const earlierPage = pagesByLowercaseId.get(page.id.toLowerCase());\n if (earlierPage) {\n // Point at where the clashing id is written. That's controller.ts for a custom id, or dot.ts\n // when both ids are folder names.\n let file = dotFile;\n if (page.id !== page.path) {\n file = page.controller;\n } else if (earlierPage.id !== earlierPage.path) {\n file = earlierPage.controller;\n }\n throw new CompileError(\n `Page id \"${page.id}\" (${page.path}) is already used by ${earlierPage.path}`,\n file,\n );\n }\n pagesByLowercaseId.set(page.id.toLowerCase(), page);\n }\n return { root, dotJson, dot: dotFile, pages: pageSources, statics: await listStatics(root) };\n}\n\nasync function loadPage(root: string, path: string, dotFile: string): Promise<PageSource> {\n const pageDir = join(root, PAGES_DIR, path);\n const files = {\n view: join(pageDir, PAGE_FILES.view),\n state: join(pageDir, PAGE_FILES.state),\n controller: join(pageDir, PAGE_FILES.controller),\n };\n const missing = Object.values(files).filter((file) => !existsSync(file));\n if (missing.length > 0) {\n throw new CompileError(`Page \"${path}\" is missing ${missing.join(', ')}`, dotFile);\n }\n const controller = await readFile(files.controller, 'utf8');\n const { id, share } = parseLogicModule(controller, files.controller);\n return { path, id: id ?? path, share, ...files };\n}\n","import type { PublicEnv } from './project/env';\nimport type { Project } from './project/project';\n\nexport const RUNTIME_PACKAGE = '@monimesl/dot-runtime';\n\nconst RUNTIME_MODULES = {\n ui: `${RUNTIME_PACKAGE}/ui`,\n logic: `${RUNTIME_PACKAGE}/logic`,\n renderer: `${RUNTIME_PACKAGE}/react`,\n} as const;\n\nexport const ENTRY = { ui: 'dot:ui', logic: 'dot:logic' } as const;\n\n// The dot's public configuration, which the global `env` imports.\nexport const ENV_MODULE = 'dot:env';\n\nexport const viewModuleId = (id: string) => `dot:view/${id}`;\n\nfunction literal(value: string): string {\n return JSON.stringify(value);\n}\n\n// `{ \"<page id>\": <importName><index>, ... }`\nfunction pageTable(project: Project, importName: string): string {\n const rows = project.pages.map(\n (page, index) => `\\n ${literal(page.id)}: ${importName}${index},`,\n );\n return `{${rows.join('')}\\n }`;\n}\n\n// Given the components the pages use, the renderer bundles only those. Otherwise it bundles all.\nexport function uiEntry(project: Project, components?: readonly string[]): string {\n const rendererModule = literal(RUNTIME_MODULES.renderer);\n let renderer: string[];\n if (components) {\n const componentList = components.join(', ');\n renderer = [\n `import { createReactRenderer, ${componentList} } from ${rendererModule};`,\n `const createRenderer = () => createReactRenderer({ components: { ${componentList} } });`,\n ];\n } else {\n renderer = [`import createRenderer from ${rendererModule};`];\n }\n return [\n `import { runWebview } from ${literal(RUNTIME_MODULES.ui)};`,\n ...renderer,\n ...project.pages.map(\n (page, index) => `import view${index} from ${literal(viewModuleId(page.id))};`,\n ),\n '',\n // While developing, this runs again on each hot reload and the running webview swaps it in.\n 'runWebview({',\n ' renderer: createRenderer,',\n ` views: ${pageTable(project, 'view')},`,\n '});',\n '',\n ].join('\\n');\n}\n\ninterface LogicEntryOptions {\n // While developing, the service checks more, such as Dash calls newer than the dot's minApiVersion.\n strict: boolean;\n dashMinApiVersion: string;\n}\n\nexport function logicEntry(\n project: Project,\n { strict, dashMinApiVersion }: LogicEntryOptions,\n): string {\n const options = [' dot,', ` pages: ${pageTable(project, 'page')},`];\n if (strict) {\n options.push(' strict: true,');\n options.push(` dashMinApiVersion: ${literal(dashMinApiVersion)},`);\n }\n return [\n `import { runService } from ${literal(RUNTIME_MODULES.logic)};`,\n `import dot from ${literal(project.dot)};`,\n ...project.pages.map((page, index) => `import page${index} from ${literal(page.controller)};`),\n '',\n // While developing, this runs again on each hot reload and the running service swaps it in.\n 'runService({',\n ...options,\n '});',\n '',\n ].join('\\n');\n}\n\nexport function envModule(env: PublicEnv): string {\n return `export const env = Object.freeze(${JSON.stringify(env, null, 2)});\\n`;\n}\n","import { realpathSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\n\nimport type { Plugin } from 'rolldown';\nimport { globalMemberUses, unboundReferences } from '@monimesl/dot-script-parser';\n\nimport { ENV_MODULE, RUNTIME_PACKAGE } from './entries';\nimport { PAGES_DIR } from './project/project';\n\nexport const DOT_GLOBALS = {\n [RUNTIME_PACKAGE]: ['definePage', 'defineDot', 'createEvent', 'dash'],\n [ENV_MODULE]: ['env'],\n} as const satisfies Record<string, readonly string[]>;\n\nconst SCRIPT_FILE = /\\.[cm]?[jt]sx?$/;\n\n// The parts of `dash` that make no calls and answer at once, which pages may use as a global.\nconst ANSWERS_AT_ONCE = new Set(['utils', 'supports']);\n\n// Adds imports for the globals each module of a dot uses. Pages must use `this.dash` instead of the\n// global `dash`, because its calls stop when the page closes.\nexport function dotGlobals(root: string): Plugin {\n // The bundler names modules by their real path, such as /private/var/… for /var/… on macOS.\n const realRoot = realpathSync(root);\n const isDotModule = (id: string) =>\n id.startsWith(realRoot + sep) &&\n !id.includes(`${sep}node_modules${sep}`) &&\n SCRIPT_FILE.test(id);\n const isPageModule = (id: string) => id.startsWith(join(realRoot, PAGES_DIR) + sep);\n return {\n name: 'dot:globals',\n transform(code, id) {\n if (!isDotModule(id)) {\n return null;\n }\n const used = new Set(unboundReferences(code, Object.values(DOT_GLOBALS).flat(), id));\n if (isPageModule(id) && used.has('dash') && makesDashCalls(code, id)) {\n this.error(\n `${relative(realRoot, id)} uses the global \\`dash\\`. In a page, use \\`this.dash\\` in actions ` +\n 'and hooks, so its calls stop when the page closes. Only dash.utils and dash.supports, ' +\n 'which answer at once, work anywhere.',\n );\n }\n const imports: string[] = [];\n for (const [source, names] of Object.entries(DOT_GLOBALS)) {\n const imported = names.filter((name) => used.has(name));\n if (imported.length > 0) {\n imports.push(`import { ${imported.join(', ')} } from ${JSON.stringify(source)};`);\n }\n }\n if (imports.length === 0) {\n return null;\n }\n return { code: `${code}\\n${imports.join('\\n')}\\n`, map: null };\n },\n };\n}\n\n// Whether a module uses the global `dash` for anything but the parts that answer at once.\nfunction makesDashCalls(code: string, id: string): boolean {\n for (const member of globalMemberUses(code, 'dash', id)) {\n if (!ANSWERS_AT_ONCE.has(member)) {\n return true;\n }\n }\n return false;\n}\n","import { join } from 'node:path';\nimport { rm } from 'node:fs/promises';\n\nimport type { Plugin } from 'rolldown';\nimport { rolldown } from 'rolldown';\nimport { esmExternalRequirePlugin } from 'rolldown/plugins';\n\nimport { dotGlobals } from '../globals';\nimport { DOT_JSON_FILE } from '../project/dot-json';\n\nexport type BuildMode = 'production' | 'development';\n\ninterface BundleOptions {\n root: string;\n modules: ReadonlyMap<string, string>;\n entry: string;\n outDir: string;\n fileName: string;\n format: 'esm' | 'iife';\n mode: BuildMode;\n conditions: readonly string[];\n // Imports left for the page to resolve, such as React, which hosts serve.\n external: readonly string[];\n}\n\n// Bundles one entry with rolldown, replacing `outDir`. Returns the written files.\nexport async function bundle(options: BundleOptions): Promise<string[]> {\n await rm(options.outDir, { recursive: true, force: true });\n const plugins: Plugin[] = [];\n if (options.external.length > 0) {\n plugins.push(esmExternalRequirePlugin({ external: [...options.external] }));\n }\n plugins.push(generatedModules(options.root, options.modules), dotGlobals(options.root));\n const bundler = await rolldown({\n input: options.entry,\n cwd: options.root,\n platform: 'browser',\n plugins,\n resolve: {\n conditionNames: [...options.conditions, 'browser', 'import', 'require', 'default'],\n },\n transform: { define: { 'process.env.NODE_ENV': JSON.stringify(options.mode) } },\n onLog(level, log, defaultHandler) {\n if (log.code !== 'MODULE_LEVEL_DIRECTIVE') {\n defaultHandler(level, log);\n }\n },\n });\n try {\n const { output } = await bundler.write({\n dir: options.outDir,\n format: options.format,\n entryFileNames: options.fileName,\n sourcemap: options.mode === 'development',\n sourcemapExcludeSources: options.mode === 'production',\n minify: options.mode === 'production',\n });\n return output.map((chunk) => join(options.outDir, chunk.fileName));\n } finally {\n await bundler.close();\n }\n}\n\n// Serves generated modules and resolves their imports as if they lived in the project root.\nfunction generatedModules(root: string, modules: ReadonlyMap<string, string>): Plugin {\n const importer = join(root, DOT_JSON_FILE);\n return {\n name: 'dot:generated',\n // The `\\0` prefix marks virtual modules in rolldown, so other plugins leave them alone.\n async resolveId(source, from) {\n if (modules.has(source)) {\n return `\\0${source}`;\n }\n if (!from?.startsWith('\\0dot:')) {\n return null;\n }\n const resolved = await this.resolve(source, importer, { skipSelf: true });\n if (!resolved) {\n this.error(`Can't find \"${source}\" from ${root}. Is it installed?`);\n }\n return resolved;\n },\n load(id) {\n if (!id.startsWith('\\0')) {\n return null;\n }\n return modules.get(id.slice(1)) ?? null;\n },\n };\n}\n","import { readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\n\nimport { CompileError } from '../errors';\nimport { RUNTIME_PACKAGE } from '../entries';\n\nconst RENDERER_PACKAGE = '@monimesl/dot-renderer-react';\n\n// The @monimesl/dot-runtime a project builds with.\nexport interface InstalledRuntime {\n readonly version: string;\n readonly react: ReactHost;\n // The installed React renderer's stylesheet.\n readonly stylesheet: string;\n}\n\n// The React the runtime's renderer uses, which hosts serve rather than each dot bundling it.\nexport interface ReactHost {\n readonly version: string;\n // The built files, in a folder per version: `<dir>/<version>/react.js`.\n readonly dir: string;\n}\n\ninterface InstalledPackage {\n readonly dir: string;\n readonly version: string;\n}\n\nexport function installedRuntime(root: string): InstalledRuntime {\n const runtime = requirePackage(root, RUNTIME_PACKAGE, 'the project');\n const renderer = requirePackage(runtime.dir, RENDERER_PACKAGE, RUNTIME_PACKAGE);\n const react = requirePackage(renderer.dir, 'react', RENDERER_PACKAGE);\n return {\n version: runtime.version,\n react: { version: react.version, dir: join(renderer.dir, 'dist', 'react-host') },\n stylesheet: join(renderer.dir, 'dist', 'styles.css'),\n };\n}\n\nfunction requirePackage(fromDir: string, name: string, installedIn: string): InstalledPackage {\n const require = createRequire(join(fromDir, 'package.json'));\n let packageFile: string;\n try {\n packageFile = require.resolve(`${name}/package.json`);\n } catch {\n throw new CompileError(\n `${name} isn't installed in ${installedIn}. Install the project's dependencies, then try again`,\n fromDir,\n );\n }\n const { version } = JSON.parse(readFileSync(packageFile, 'utf8')) as { version: string };\n return { dir: dirname(packageFile), version };\n}\n","import type { ExprNode } from '@monimesl/dot-script-parser';\n\nexport type Scope = ReadonlyMap<string, string>;\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport const EMPTY_SCOPE: Scope = new Map();\n\nexport function isIdentifier(name: string): boolean {\n return IDENTIFIER.test(name);\n}\n\n// Loop variables read their local; everything else reads page data from `d`.\nexport function printExpr(expr: ExprNode, scope: Scope): string {\n const print = (node: ExprNode) => printExpr(node, scope);\n switch (expr.type) {\n case 'Literal':\n return JSON.stringify(expr.value);\n case 'Identifier':\n return scope.get(expr.name) ?? `d.${expr.name}`;\n case 'Member':\n if (expr.property.type === 'Literal' && typeof expr.property.value === 'string') {\n return `${print(expr.object)}?.${expr.property.value}`;\n }\n return `${print(expr.object)}?.[${print(expr.property)}]`;\n case 'Unary':\n if (expr.operator === 'typeof') {\n return `(typeof ${print(expr.argument)})`;\n }\n return `(${expr.operator}${print(expr.argument)})`;\n case 'Binary':\n return `(${print(expr.left)} ${expr.operator} ${print(expr.right)})`;\n case 'Conditional':\n return `(${print(expr.test)} ? ${print(expr.consequent)} : ${print(expr.alternate)})`;\n }\n}\n\nexport function stateReads(expr: ExprNode, scope: Scope): string[] {\n const reads = (node: ExprNode) => stateReads(node, scope);\n switch (expr.type) {\n case 'Literal':\n return [];\n case 'Identifier':\n return scope.has(expr.name) ? [] : [expr.name];\n case 'Member':\n return [...reads(expr.object), ...reads(expr.property)];\n case 'Unary':\n return reads(expr.argument);\n case 'Binary':\n return [...reads(expr.left), ...reads(expr.right)];\n case 'Conditional':\n return [...reads(expr.test), ...reads(expr.consequent), ...reads(expr.alternate)];\n }\n}\n","import type { ComponentManifest } from '@monimesl/dot-core';\nimport type { DmlElementNode } from '@monimesl/dot-dml-parser';\n\nimport type { ViewCompiler } from './compiler';\nimport { isIdentifier, type Scope } from './expression';\n\nexport const CONTROL_FLOW_TAGS: Readonly<\n Record<string, { readonly attributes: readonly string[]; readonly required: readonly string[] }>\n> = {\n If: { attributes: ['condition'], required: ['condition'] },\n ElseIf: { attributes: ['condition'], required: ['condition'] },\n Else: { attributes: [], required: [] },\n For: { attributes: ['each', 'item', 'index', 'key'], required: ['each'] },\n};\n\n// Compiles sibling <If>, <ElseIf>s and an optional <Else> to `...(a ? [...] : b ? [...] : [...])`.\nexport function compileConditional(\n compiler: ViewCompiler,\n branches: readonly DmlElementNode[],\n parent: ComponentManifest | null,\n scope: Scope,\n): string {\n let code = '[]';\n for (const branch of [...branches].reverse()) {\n const body = `[${compiler.compile(branch.children, parent, scope).join(', ')}]`;\n compiler.checkControlFlowElementAttributes(branch);\n if (branch.tag === 'Else') {\n code = body;\n } else {\n const condition = compiler.compileSingleBinding(branch, 'condition', scope);\n code = `${condition} ? ${body} : ${code}`;\n }\n }\n return `...(${code})`;\n}\n\n// Compiles `<For each=\"{{ list }}\" item index key>` to `each(list, (item, index) => [...], key?)`.\nexport function compileLoop(\n compiler: ViewCompiler,\n node: DmlElementNode,\n parent: ComponentManifest | null,\n scope: Scope,\n): string {\n compiler.checkControlFlowElementAttributes(node);\n const list = compiler.compileSingleBinding(node, 'each', scope);\n const { item = 'item', index = 'index', key } = node.attributes;\n\n const checkVariableName = (attribute: string, name: string) => {\n if (!isIdentifier(name)) {\n compiler.fail(`<For> \\`${attribute}\\` must be a variable name, got \"${name}\"`, node.loc);\n }\n };\n checkVariableName('item', item);\n checkVariableName('index', index);\n if (item === index) {\n compiler.fail('<For> `item` and `index` need different names', node.loc);\n }\n // Loop variables get a `$` prefix so they never clash with names in the generated code.\n const itemVariable = '$' + item;\n const indexVariable = '$' + index;\n const loopScope = new Map(scope);\n loopScope.set(item, itemVariable);\n loopScope.set(index, indexVariable);\n const body = compiler.compile(node.children, parent, loopScope).join(', ');\n const eachArguments = [list, `(${itemVariable}, ${indexVariable}) => [${body}]`];\n if (key === undefined) {\n compiler.warn(\n '<For> has no `key`, so items are matched by position. If items can move, ' +\n 'add key=\"<property>\" or key=\"*this\". To keep matching by position, add key=\"*index\".',\n node.loc,\n );\n } else if (key === '*index') {\n // Matching by position is what `each` does without a key.\n } else if (key === '*this') {\n eachArguments.push(`(${itemVariable}) => ${itemVariable}`);\n } else if (isIdentifier(key)) {\n eachArguments.push(`(${itemVariable}) => ${itemVariable}?.${key}`);\n } else {\n compiler.fail(`<For> \\`key\\` must be a property name, *this or *index, got \"${key}\"`, node.loc);\n }\n return `each(${eachArguments.join(', ')})`;\n}\n","import {\n builtinRegistry,\n eventName,\n type ComponentManifest,\n type ComponentRegistry,\n isWordsOr,\n otherThanWords,\n type PropType,\n type WordsOr,\n type SourceLocation,\n} from '@monimesl/dot-core';\nimport type { DmlElementNode, DmlNode } from '@monimesl/dot-dml-parser';\nimport { type ExprNode, parseExpression, ScriptParseError } from '@monimesl/dot-script-parser';\n\nimport { CompileError, CompileWarning } from '../errors';\nimport { STATICS_DIR } from '../project/statics';\nimport { quotedList } from '../utils';\nimport { compileConditional, compileLoop, CONTROL_FLOW_TAGS } from './control-flow';\nimport { EMPTY_SCOPE, isIdentifier, printExpr, type Scope, stateReads } from './expression';\n\nexport interface ViewContext {\n file: string;\n components?: ComponentRegistry | undefined;\n // The mutations and actions in controller.ts. Each event attribute must name one.\n handlers?: readonly string[] | undefined;\n // The keys in state.ts. Leave it out to skip the check.\n stateKeys?: readonly string[] | undefined;\n // The files under statics/, such as `statics/logo.png`. Any other statics/ path is an error.\n statics?: readonly string[] | undefined;\n onWarning?: ((warning: CompileWarning) => void) | undefined;\n // Called with the name of each component the markup uses.\n onComponent?: ((name: string) => void) | undefined;\n}\n\n// Every page's markup is one root <View>. Unless the markup says otherwise, it fills the page and\n// puts space at the page's edges and between its children.\nexport const ROOT_TAG = 'View';\nconst ROOT_DEFAULTS = { padding: 'large', gap: 'large', grow: true };\n\ntype Segment = { kind: 'static'; value: string } | { kind: 'binding'; code: string };\nconst SEGMENT_BINDING_REGEXP = /{{([\\s\\S]*?)}}/g;\n\nexport const DATA_PREFIX = 'data-';\nconst DATA_ATTRIBUTE = /^data-[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n// A colour named in the theme, such as `gold` or `brandBlue`.\nconst THEME_COLOR_NAME = /^[a-z][a-zA-Z0-9]*$/;\n\nexport class ViewCompiler {\n readonly #context: ViewContext;\n readonly #components: ComponentRegistry;\n\n constructor(context: ViewContext) {\n this.#context = context;\n this.#components = context.components ?? builtinRegistry;\n for (const name of Object.keys(CONTROL_FLOW_TAGS)) {\n if (name in this.#components) {\n this.fail(`<${name}> is reserved for control flow`);\n }\n }\n }\n\n compile(nodes: readonly DmlNode[], parent: ComponentManifest | null, scope: Scope): string[] {\n const compiled: string[] = [];\n for (let index = 0; index < nodes.length; index++) {\n const node = nodes[index]!;\n if (node.type === 'Text') {\n compiled.push(...this.#compileText(node.content, parent, scope, node.loc));\n continue;\n }\n switch (node.tag) {\n case 'If': {\n const branches = ifChain(node, nodes.slice(index + 1));\n compiled.push(compileConditional(this, branches, parent, scope));\n // Skip the <ElseIf> and <Else> siblings the chain took in.\n index += branches.length - 1;\n break;\n }\n case 'ElseIf':\n case 'Else':\n return this.fail(`<${node.tag}> must come right after <If> or <ElseIf>`, node.loc);\n case 'For':\n compiled.push(compileLoop(this, node, parent, scope));\n break;\n default:\n compiled.push(`h(${this.#compileElementArgs(node, parent, scope).join(', ')})`);\n }\n }\n return compiled;\n }\n\n #compileText(\n content: string,\n parent: ComponentManifest | null,\n scope: Scope,\n loc?: SourceLocation,\n ): string[] {\n if (parent?.children !== 'text') {\n // A space between two elements in a column or a row is only markup.\n if (content.trim() === '') {\n return [];\n }\n this.fail(`'${content}' must be inside ${this.#textWrapperNames()}`, loc);\n }\n return this.#compileAsSegments(content, scope, loc).map(printSegment);\n }\n\n // Names the components loose text can go in, with <Text> first, since that's what it usually needs.\n #textWrapperNames(): string {\n const textWrappers = Object.values(this.#components).filter((component) => {\n return component.inline === true && component.children === 'text';\n });\n const textFirst = [\n ...textWrappers.filter((component) => component.name === 'Text'),\n ...textWrappers.filter((component) => component.name !== 'Text'),\n ];\n if (textFirst.length === 0) {\n return 'an inline component';\n }\n return textFirst.map((component) => `<${component.name}>`).join(' or ');\n }\n\n // Returns the arguments of the `h` call for the page's root <View>.\n compileRoot(nodes: readonly DmlNode[]): string[] {\n if (!this.#components[ROOT_TAG]) {\n this.fail(`The components must include <${ROOT_TAG}>, which is the root of every page`);\n }\n const [root, outside] = nodes;\n if (root?.type !== 'Element' || root.tag !== ROOT_TAG) {\n return this.fail(`A page must have one <${ROOT_TAG}> around everything else`, root?.loc);\n }\n if (outside) {\n this.fail(`${describeNode(outside)} must be inside the page's <${ROOT_TAG}>`, outside.loc);\n }\n return this.#compileElementArgs(root, null, EMPTY_SCOPE, ROOT_DEFAULTS);\n }\n\n #compileElementArgs(\n node: DmlElementNode,\n parent: ComponentManifest | null,\n scope: Scope,\n defaults: Readonly<Record<string, unknown>> = {},\n ): string[] {\n const component = this.#components[node.tag];\n if (!component) {\n return this.fail(`Unknown component <${node.tag}>`, node.loc);\n }\n this.#context.onComponent?.(component.name);\n if (parent && !canHaveChildren(parent, component)) {\n this.fail(`<${node.tag}> can't go inside <${parent.name}>`, node.loc);\n }\n for (const { prop, ignores, because } of component.overrides ?? []) {\n if (prop in node.attributes && ignores in node.attributes) {\n this.warn(\n `<${component.name}> ignores \\`${ignores}\\` with \\`${prop}\\`: ${because}`,\n node.loc,\n );\n }\n }\n const dataAttributes: [string, string][] = [];\n const propAttributes: [string, string][] = [];\n for (const [name, value] of Object.entries(node.attributes)) {\n if (name.startsWith(DATA_PREFIX)) {\n dataAttributes.push([name, value]);\n } else {\n propAttributes.push([name, value]);\n }\n }\n const data = this.#compileData(dataAttributes, scope, node.loc);\n const props: string[] = [];\n for (const [name, value] of propAttributes) {\n props.push(this.#compileProp(component, name, value, scope, node.loc));\n }\n for (const [name, handler] of Object.entries(node.events)) {\n props.push(this.#compileEvent(component, name, handler, data, node.loc));\n }\n for (const [name, value] of Object.entries(defaults)) {\n if (!(name in node.attributes)) {\n props.push(`${name}: ${JSON.stringify(value)}`);\n }\n }\n let propsCode = 'null';\n if (props.length > 0) {\n propsCode = `{ ${props.join(', ')} }`;\n }\n return [\n JSON.stringify(component.name),\n propsCode,\n ...this.compile(node.children, component, scope),\n ];\n }\n\n #compileProp(\n component: ComponentManifest,\n name: string,\n value: string,\n scope: Scope,\n loc?: SourceLocation,\n ): string {\n const type = component.props[name];\n if (!type) {\n return this.fail(`<${component.name}> has no \\`${name}\\` attribute`, loc);\n }\n const segments = this.#compileAsSegments(value, scope, loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode !== null) {\n return `${name}: ${bindingCode}`;\n }\n if (segments.every((segment) => segment.kind === 'static')) {\n this.#checkStaticsReference(value, loc);\n return `${name}: ${this.#compileLiteral(type, value, loc)}`;\n }\n if (type !== 'string' && type !== 'any') {\n const kind = typeof type === 'string' ? `a ${type}` : 'an enum';\n this.fail(`\\`${name}\\` is ${kind}, so set it with one {{ }} binding`, loc);\n }\n return `${name}: ${concatenateSegments(segments)}`;\n }\n\n // `data-account-id=\"{{ account.id }}\"` becomes `{ accountId: d.account.id }`, which the element's\n // events carry to their handlers.\n #compileData(\n attributes: readonly [string, string][],\n scope: Scope,\n loc?: SourceLocation,\n ): string | null {\n if (attributes.length === 0) {\n return null;\n }\n const entries = attributes.map(([name, value]) => {\n if (!DATA_ATTRIBUTE.test(name)) {\n this.fail(`\\`${name}\\` must be lowercase words joined by -, such as data-account-id`, loc);\n }\n return `${dataKey(name)}: ${this.#compileDataValue(value, scope, loc)}`;\n });\n return `{ ${entries.join(', ')} }`;\n }\n\n // A single binding keeps its value's type, such as a number. Anything else becomes a string.\n #compileDataValue(value: string, scope: Scope, loc?: SourceLocation): string {\n const segments = this.#compileAsSegments(value, scope, loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode !== null) {\n return bindingCode;\n }\n if (segments.length === 0) {\n return '\"\"';\n }\n return concatenateSegments(segments);\n }\n\n #checkStaticsReference(value: string, loc: SourceLocation | undefined): void {\n const { statics } = this.#context;\n if (statics && value.startsWith(`${STATICS_DIR}/`) && !statics.includes(value)) {\n this.fail(`\"${value}\" isn't in ${STATICS_DIR}/`, loc);\n }\n }\n\n #compileEvent(\n component: ComponentManifest,\n attribute: string,\n handler: string,\n data: string | null,\n loc?: SourceLocation,\n ): string {\n const event = eventName(attribute);\n if (!component.events.includes(event)) {\n this.fail(`<${component.name}> has no \\`${attribute}\\` event`, loc);\n }\n if (!isIdentifier(handler)) {\n this.fail(\n `\\`${attribute}\\` must name a mutation or action in controller.ts, got \"${handler}\"`,\n loc,\n );\n }\n const { handlers } = this.#context;\n if (handlers && !handlers.includes(handler)) {\n this.fail(`\\`${handler}\\` isn't a mutation or action in controller.ts`, loc);\n }\n let onArguments = JSON.stringify(handler);\n if (data) {\n onArguments += `, ${data}`;\n }\n return `${attribute}: on(${onArguments})`;\n }\n\n checkControlFlowElementAttributes(node: DmlElementNode): void {\n const { attributes: allowed, required } = CONTROL_FLOW_TAGS[node.tag]!;\n const [event] = Object.keys(node.events);\n if (event) {\n this.fail(\n `<${node.tag}> can't handle events such as \\`${event}\\`. ` +\n 'Put the handler on a component inside it.',\n node.loc,\n );\n }\n for (const name of Object.keys(node.attributes)) {\n if (!allowed.includes(name)) {\n this.fail(`<${node.tag}> has no \\`${name}\\` attribute`, node.loc);\n }\n }\n for (const name of required) {\n if (!(name in node.attributes)) {\n this.fail(`<${node.tag}> requires \\`${name}\\``, node.loc);\n }\n }\n }\n\n compileSingleBinding(node: DmlElementNode, attribute: string, scope: Scope): string {\n const segments = this.#compileAsSegments(node.attributes[attribute] ?? '', scope, node.loc);\n const bindingCode = singleBindingCode(segments);\n if (bindingCode === null) {\n return this.fail(`<${node.tag}> \\`${attribute}\\` must be one {{ }} binding`, node.loc);\n }\n return bindingCode;\n }\n\n #compileLiteral(type: PropType, value: string, loc?: SourceLocation): string {\n if (isWordsOr(type)) {\n return this.#compileWordOr(type, value, loc);\n }\n if (typeof type !== 'string') {\n if (type.includes(value)) {\n return JSON.stringify(value);\n }\n return this.fail(`Expected one of ${quotedList(type)}, got \"${value}\"`, loc);\n }\n switch (type) {\n case 'boolean':\n if (value === '' || value === 'true') {\n return 'true';\n }\n if (value === 'false') {\n return 'false';\n }\n return this.fail(`Expected true or false, got \"${value}\"`, loc);\n case 'number':\n if (isNumberText(value)) {\n return printNumber(value);\n }\n return this.fail(`Expected a number, got \"${value}\"`, loc);\n case 'string':\n case 'any':\n return JSON.stringify(value);\n }\n }\n\n // A word, or else a number or the name of a colour in the dot's theme. A name is checked when the\n // page shows, since the theme is set in dot.ts at run time.\n #compileWordOr(type: WordsOr, value: string, loc?: SourceLocation): string {\n if (type.words.includes(value)) {\n return JSON.stringify(value);\n }\n if (type.or === 'number' && isNumberText(value)) {\n return printNumber(value);\n }\n if (type.or === 'themeColor' && THEME_COLOR_NAME.test(value)) {\n return JSON.stringify(value);\n }\n return this.fail(\n `Expected one of ${quotedList(type.words)}, or ${otherThanWords(type)}, got \"${value}\"`,\n loc,\n );\n }\n\n #compileAsSegments(input: string, scope: Scope, loc?: SourceLocation): Segment[] {\n const segments: Segment[] = [];\n let staticStart = 0;\n for (const match of input.matchAll(SEGMENT_BINDING_REGEXP)) {\n if (match.index > staticStart) {\n segments.push({ kind: 'static', value: input.slice(staticStart, match.index) });\n }\n const expression = this.#parseBindingExpression(match[1]!, scope, loc);\n segments.push({ kind: 'binding', code: printExpr(expression, scope) });\n staticStart = match.index + match[0].length;\n }\n const rest = input.slice(staticStart);\n if (rest.includes('{{')) {\n this.fail('A binding is missing its closing `}}`', loc);\n }\n if (rest) {\n segments.push({ kind: 'static', value: rest });\n }\n return segments;\n }\n\n #parseBindingExpression(source: string, scope: Scope, loc?: SourceLocation): ExprNode {\n let expression: ExprNode;\n try {\n expression = parseExpression(source);\n } catch (error) {\n if (!(error instanceof ScriptParseError)) {\n throw error;\n }\n return this.fail(`Invalid binding \\`{{${source}}}\\`: ${error.reason}`, loc);\n }\n const { stateKeys } = this.#context;\n if (stateKeys) {\n const undeclared = stateReads(expression, scope).find((name) => !stateKeys.includes(name));\n if (undeclared) {\n const declared = stateKeys.join(', ') || 'none';\n this.fail(`\\`${undeclared}\\` isn't in state.ts. It has: ${declared}`, loc);\n }\n }\n return expression;\n }\n\n warn(message: string, loc?: SourceLocation): void {\n this.#context.onWarning?.(new CompileWarning(message, this.#context.file, loc));\n }\n\n fail(message: string, loc?: SourceLocation): never {\n throw new CompileError(message, this.#context.file, loc);\n }\n}\n\n// The <If>, then the <ElseIf> and <Else> siblings that continue it.\nfunction ifChain(ifNode: DmlElementNode, nextSiblings: readonly DmlNode[]): DmlElementNode[] {\n const branches = [ifNode];\n for (const sibling of nextSiblings) {\n if (!continuesIf(sibling)) {\n break;\n }\n branches.push(sibling);\n // Nothing continues the chain after an <Else>.\n if (sibling.tag === 'Else') {\n break;\n }\n }\n return branches;\n}\n\nfunction continuesIf(node: DmlNode): node is DmlElementNode {\n return node.type === 'Element' && (node.tag === 'ElseIf' || node.tag === 'Else');\n}\n\nfunction singleBindingCode(segments: readonly Segment[]): string | null {\n const [first] = segments;\n if (segments.length === 1 && first?.kind === 'binding') {\n return first.code;\n }\n return null;\n}\n\n// `data-account-id` -> `accountId`\nexport function dataKey(attribute: string): string {\n const words = attribute.slice(DATA_PREFIX.length).split('-');\n let key = words[0] ?? '';\n for (const word of words.slice(1)) {\n key += word.charAt(0).toUpperCase() + word.slice(1);\n }\n return key;\n}\n\nfunction describeNode(node: DmlNode): string {\n if (node.type === 'Text') {\n return `'${node.content}'`;\n }\n return `<${node.tag}>`;\n}\n\nfunction printSegment(segment: Segment): string {\n if (segment.kind === 'static') {\n return JSON.stringify(segment.value);\n }\n return `text(${segment.code})`;\n}\n\nfunction concatenateSegments(segments: readonly Segment[]): string {\n return segments.map(printSegment).join(' + ');\n}\n\nexport function canHaveChildren(parent: ComponentManifest, child: ComponentManifest): boolean {\n switch (parent.children) {\n case 'none':\n return false;\n case 'text':\n return child.inline === true;\n case 'elements':\n return true;\n }\n}\n\nfunction isNumberText(value: string): boolean {\n return value.trim() !== '' && Number.isFinite(Number(value));\n}\n\n// Writes the number in its plain form, so `1e3` and `007` become `1000` and `7`.\nfunction printNumber(value: string): string {\n return String(Number(value));\n}\n","import { parseDmlToIR } from '@monimesl/dot-dml-parser';\n\nimport { ViewCompiler, type ViewContext } from './compiler';\n\n// Compiles markup to a module whose render function builds the root <View> with the renderer's `h`.\nexport function compileView(source: string, context: ViewContext): string {\n const nodes = parseDmlToIR(source, {\n locations: true,\n file: context.file,\n whitespace: 'inline',\n });\n const compiler = new ViewCompiler(context);\n const rootArguments = compiler.compileRoot(nodes);\n const rootArgumentLines = rootArguments.map((argument) => `\\n ${argument},`).join('');\n return [\n 'export default function render(d, { h, on, text, each }) {',\n ` return h(${rootArgumentLines}\\n );`,\n '}',\n '',\n ].join('\\n');\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nimport type { PublicEnv } from './project/env';\nimport type { Project } from './project/project';\n\nconst PAGE_TYPES_FILE = '.dot/pages.d.ts';\nconst ENV_TYPES_FILE = '.dot/env.d.ts';\n\n// Page ids, so navigation targets are typed.\nexport async function writePageTypes(project: Project): Promise<string> {\n const members = project.pages.map((page) => `${JSON.stringify(page.id)}: true;`);\n return writeIfChanged(\n join(project.root, PAGE_TYPES_FILE),\n globalInterface('dot.ts', 'DotPageIds', members),\n );\n}\n\n// The names in the global `env`, so a misspelled one is a type error.\nexport async function writeEnvTypes(project: Project, env: PublicEnv): Promise<string> {\n const members = Object.keys(env).map((name) => `readonly ${name}: string;`);\n return writeIfChanged(\n join(project.root, ENV_TYPES_FILE),\n globalInterface('the variables in .env files', 'DotPublicEnv', members),\n );\n}\n\n// A declaration file that fills in one of the runtime's global interfaces.\nfunction globalInterface(source: string, name: string, members: readonly string[]): string {\n return [\n `// Generated by dotctl from ${source}. Do not edit.`,\n 'declare global {',\n ` interface ${name} {`,\n ...members.map((member) => ` ${member}`),\n ' }',\n '}',\n '',\n 'export {};',\n '',\n ].join('\\n');\n}\n\n// Leaves an unchanged file alone, so editors and watchers don't see a change.\nasync function writeIfChanged(file: string, content: string): Promise<string> {\n const current = await readFile(file, 'utf8').catch(() => null);\n if (current !== content) {\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, content);\n }\n return file;\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseEnv } from 'node:util';\n\nimport { CompileError } from '../errors';\n\n// Every variable in the .env files ships inside the dot, where anyone with the dot can read it.\n// Never put a secret in them.\nconst PUBLIC_ENV_NAME = /^[A-Z][A-Z0-9_]*$/;\n\nexport type PublicEnv = Readonly<Record<string, string>>;\n\n// Reads `.env`, then `.env.<mode>`, and the later file wins. The shell can override a variable the\n// files declare, so CI can set a value. It can't add one, so PATH or a CI secret stays out.\nexport async function loadPublicEnv(\n root: string,\n mode: string,\n shellEnv: Readonly<Record<string, string | undefined>> = process.env,\n): Promise<PublicEnv> {\n const env: Record<string, string> = {};\n for (const fileName of ['.env', `.env.${mode}`]) {\n const file = join(root, fileName);\n if (existsSync(file)) {\n addVariables(env, parseEnv(await readFile(file, 'utf8')), file);\n }\n }\n // Sorted, so the bundle and the generated types don't change with the order of the files.\n const sorted: Record<string, string> = {};\n for (const name of Object.keys(env).sort()) {\n sorted[name] = shellEnv[name] ?? env[name]!;\n }\n return sorted;\n}\n\nfunction addVariables(\n env: Record<string, string>,\n variables: Readonly<Record<string, string | undefined>>,\n file: string,\n): void {\n for (const [name, value] of Object.entries(variables)) {\n if (value === undefined) {\n continue;\n }\n if (!PUBLIC_ENV_NAME.test(name)) {\n throw new CompileError(\n `\"${name}\" must be capital letters, digits and underscores, starting with a letter`,\n file,\n );\n }\n env[name] = value;\n }\n}\n","import { copyFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\n\nimport { zipSync } from 'fflate';\n\nimport type { ComponentManifest, ComponentRegistry } from '@monimesl/dot-core';\nimport {\n DEFAULT_DASH_API_VERSION,\n REACT_HOST_MODULES,\n builtinComponents,\n componentRegistry,\n reactHostUrl,\n} from '@monimesl/dot-core';\nimport { parseLogicModule, parseStateModule } from '@monimesl/dot-script-parser';\n\nimport { bundle } from './bundle';\nimport type { BuildMode } from './bundle';\nimport type { InstalledRuntime } from './packages';\nimport { installedRuntime } from './packages';\nimport { compileView } from '../view';\nimport type { ViewContext } from '../view';\nimport { writeEnvTypes, writePageTypes } from '../types';\nimport type { PublicEnv } from '../project/env';\nimport { loadPublicEnv } from '../project/env';\nimport type { CompileWarning } from '../errors';\nimport type { DashNeeds, DotJson } from '../project/dot-json';\nimport type { PageSource, Project } from '../project/project';\nimport { loadProject } from '../project/project';\nimport { ENTRY, ENV_MODULE, envModule, logicEntry, uiEntry, viewModuleId } from '../entries';\nimport { relativeSlashPath } from '../utils';\n\nconst MANIFEST_FILE = 'manifest.json';\nconst STYLES_FILE = 'dot.css';\n// The earliest date a ZIP file can hold.\nconst ARCHIVE_DATE = new Date(1980, 0, 1);\n\nexport interface BuildOptions {\n root: string;\n // Defaults to `<root>/dist`.\n outDir?: string | undefined;\n // `production` (the default) is minified. `development` isn't, so it reads well in a debugger.\n mode?: BuildMode | undefined;\n components?: readonly ComponentManifest[] | undefined;\n conditions?: readonly string[] | undefined;\n}\n\nexport interface BuildResult {\n readonly outDir: string;\n readonly files: readonly string[];\n readonly warnings: readonly CompileWarning[];\n}\n\n/** Compiles and bundles the dot into `outDir` for hosts, and refreshes the types in `.dot/`. */\nexport async function build(options: BuildOptions): Promise<BuildResult> {\n const project = await loadProject(options.root);\n const mode = options.mode ?? 'production';\n const env = await loadPublicEnv(project.root, mode);\n const runtime = installedRuntime(project.root);\n await writePageTypes(project);\n await writeEnvTypes(project, env);\n\n const warnings: CompileWarning[] = [];\n const components = componentRegistry([\n ...Object.values(builtinComponents),\n ...(options.components ?? []),\n ]);\n const modules = await compileModules(project, env, components, mode, warnings);\n\n const outDir = resolve(project.root, options.outDir ?? 'dist');\n const uiDir = join(outDir, 'ui');\n const bundleLayer = (\n entry: string,\n layerDir: string,\n format: 'esm' | 'iife',\n external: readonly string[],\n ) =>\n bundle({\n root: project.root,\n modules,\n entry,\n outDir: layerDir,\n fileName: 'dot.js',\n format,\n mode,\n conditions: options.conditions ?? [],\n external,\n });\n const files: string[] = [];\n // React stays out of the webview bundle. The host serves it, and the import map points at it.\n files.push(...(await bundleLayer(ENTRY.ui, uiDir, 'esm', Object.keys(REACT_HOST_MODULES))));\n files.push(...(await bundleLayer(ENTRY.logic, join(outDir, 'logic'), 'iife', [])));\n // Each bundle empties its folder first, so the files that go next to it are written after.\n files.push(await copyRendererStyles(runtime, uiDir));\n files.push(await writeIndexHtml(project, uiDir, runtime.react.version));\n files.push(...(await copyStatics(project, uiDir)));\n files.push(await writeManifest(project, outDir, runtime));\n if (mode === 'production') {\n files.push(await writeArchive(project, outDir, files));\n }\n return { outDir, files, warnings };\n}\n\nasync function copyRendererStyles(runtime: InstalledRuntime, uiDir: string): Promise<string> {\n const file = join(uiDir, STYLES_FILE);\n await mkdir(uiDir, { recursive: true });\n await copyFile(runtime.stylesheet, file);\n return file;\n}\n\n// The build as the one file Dash downloads, `<package>-<version>.zip`, without source maps. Its files\n// all get the same date, so the same build always makes the same archive.\nasync function writeArchive(project: Project, outDir: string, files: string[]): Promise<string> {\n const entries: Record<string, [Uint8Array, { mtime: Date }]> = {};\n for (const file of files) {\n if (!file.endsWith('.map')) {\n const name = relativeSlashPath(outDir, file);\n entries[name] = [await readFile(file), { mtime: ARCHIVE_DATE }];\n }\n }\n const { package: packageName, version } = project.dotJson;\n // Remove archives of earlier versions, which would otherwise pile up.\n for (const name of await readdir(outDir)) {\n if (name.startsWith(`${packageName}-`) && name.endsWith('.zip')) {\n await rm(join(outDir, name));\n }\n }\n const file = join(outDir, `${packageName}-${version}.zip`);\n await writeFile(file, zipSync(entries, { level: 9 }));\n return file;\n}\n\nasync function compileModules(\n project: Project,\n env: PublicEnv,\n components: ComponentRegistry,\n mode: BuildMode,\n warnings: CompileWarning[],\n): Promise<Map<string, string>> {\n const modules = new Map<string, string>();\n const usedComponents = new Set<string>();\n for (const page of project.pages) {\n const view = await compilePage(page, components, project.statics, warnings, usedComponents);\n modules.set(viewModuleId(page.id), view);\n }\n // While developing, a hot reload keeps the renderer, so it has every component a page may add.\n let rendererComponents: string[] | undefined;\n if (mode === 'production') {\n rendererComponents = [...usedComponents].filter((name) => name in builtinComponents).sort();\n }\n modules.set(ENTRY.ui, uiEntry(project, rendererComponents));\n const logicOptions = {\n strict: mode === 'development',\n dashMinApiVersion: dashMinApiVersion(project),\n };\n modules.set(ENTRY.logic, logicEntry(project, logicOptions));\n modules.set(ENV_MODULE, envModule(env));\n return modules;\n}\n\nasync function writeIndexHtml(\n project: Project,\n uiDir: string,\n reactVersion: string,\n): Promise<string> {\n const file = join(uiDir, 'index.html');\n await mkdir(uiDir, { recursive: true });\n await writeFile(file, indexHtml(project.dotJson.name, reactVersion));\n return file;\n}\n\nasync function copyStatics(project: Project, uiDir: string): Promise<string[]> {\n const copies: string[] = [];\n for (const file of project.statics) {\n const copy = join(uiDir, file);\n await mkdir(dirname(copy), { recursive: true });\n await copyFile(join(project.root, file), copy);\n copies.push(copy);\n }\n return copies;\n}\n\nasync function writeManifest(\n project: Project,\n outDir: string,\n runtime: InstalledRuntime,\n): Promise<string> {\n const file = join(outDir, MANIFEST_FILE);\n const manifest = dotManifest(project, runtime);\n await writeFile(file, `${JSON.stringify(manifest, null, 2)}\\n`);\n return file;\n}\n\n/** What a host needs to run the build: dot.json without `$schema`, where it starts and its pages. */\nexport interface DotManifest extends DotJson {\n // The version of @monimesl/dot-runtime in the bundles, so a host can tell whether it runs them.\n readonly runtime: string;\n // The React version the webview imports from the host.\n readonly react: string;\n readonly entry: string;\n readonly pages: readonly string[];\n // Each page that Dash's Share can open, with the options its link may carry.\n readonly share: Readonly<Record<string, readonly string[]>>;\n // Written even when dot.json leaves it out, so hosts and Monime needn't know the default.\n readonly dash: DashNeeds;\n}\n\nfunction dotManifest(project: Project, runtime: InstalledRuntime): DotManifest {\n const { id, package: packageName, name, version, permissions, network } = project.dotJson;\n const pages = project.pages.map((page) => page.id);\n const share: Record<string, readonly string[]> = {};\n for (const page of project.pages) {\n if (page.share) {\n share[page.id] = page.share;\n }\n }\n return {\n id,\n package: packageName,\n name,\n version,\n runtime: runtime.version,\n react: runtime.react.version,\n permissions,\n network,\n dash: { minApiVersion: dashMinApiVersion(project) },\n entry: pages[0]!,\n pages,\n share,\n };\n}\n\nfunction dashMinApiVersion(project: Project): string {\n return project.dotJson.dash?.minApiVersion ?? DEFAULT_DASH_API_VERSION;\n}\n\nasync function compilePage(\n page: PageSource,\n components: ComponentRegistry,\n statics: readonly string[],\n warnings: CompileWarning[],\n usedComponents: Set<string>,\n): Promise<string> {\n const [view, state, controller] = await Promise.all([\n readFile(page.view, 'utf8'),\n readFile(page.state, 'utf8'),\n readFile(page.controller, 'utf8'),\n ]);\n const context: ViewContext = {\n file: page.view,\n components,\n statics,\n onWarning: (warning) => warnings.push(warning),\n onComponent: (name) => usedComponents.add(name),\n };\n // State keys are checked only when state.ts is a plain object literal.\n const { keys } = parseStateModule(state, page.state);\n if (keys) {\n context.stateKeys = keys;\n }\n // Handler names are checked only when both lists could be read without running the code.\n const { mutations, actions } = parseLogicModule(controller, page.controller);\n if (mutations && actions) {\n context.handlers = [...mutations, ...actions];\n }\n return compileView(view, context);\n}\n\nfunction indexHtml(title: string, reactVersion: string): string {\n const escaped = title.replace(/[&<>\"]/g, (char) => `&#${char.charCodeAt(0)};`);\n const imports: Record<string, string> = {};\n for (const [name, file] of Object.entries(REACT_HOST_MODULES)) {\n imports[name] = reactHostUrl(reactVersion, file);\n }\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"\n />\n <title>${escaped}</title>\n <link rel=\"stylesheet\" href=\"./${STYLES_FILE}\" />\n <style>\n body {\n margin: 0;\n }\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"importmap\">${JSON.stringify({ imports })}</script>\n <script type=\"module\" src=\"./dot.js\"></script>\n </body>\n</html>\n`;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-compiler",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "Compiles Dot mini apps into a webview bundle and a service bundle",
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,9 +26,9 @@
26
26
  "dependencies": {
27
27
  "fflate": "^0.8.3",
28
28
  "rolldown": "^1.2.9",
29
- "@monimesl/dot-core": "0.1.0-alpha.21",
30
- "@monimesl/dot-dml-parser": "0.1.0-alpha.21",
31
- "@monimesl/dot-script-parser": "0.1.0-alpha.21"
29
+ "@monimesl/dot-core": "0.1.0-alpha.23",
30
+ "@monimesl/dot-script-parser": "0.1.0-alpha.23",
31
+ "@monimesl/dot-dml-parser": "0.1.0-alpha.23"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^22.20.4",