@monimesl/dot-script-parser 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
@@ -2,6 +2,7 @@ import "oxc-parser";
2
2
  import { SourceError } from "@monimesl/dot-core";
3
3
  //#region src/globals.d.ts
4
4
  export declare function unboundReferences(source: string, names: readonly string[], file?: string): string[];
5
+ export declare function globalMemberUses(source: string, name: string, file?: string): string[];
5
6
  //#endregion
6
7
  //#region src/dot.d.ts
7
8
  interface DotModuleIR {
@@ -66,6 +67,7 @@ interface PageStateModule {
66
67
  }
67
68
  interface PageModule {
68
69
  readonly id: string | null;
70
+ readonly share: readonly string[] | null;
69
71
  readonly hooks: readonly string[];
70
72
  readonly mutations: readonly string[] | null;
71
73
  readonly actions: readonly string[] | null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/globals.ts","../src/dot.ts","../src/errors.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts","../src/ast/page/types.ts","../src/ast/page/parse.ts"],"mappings":";;;wBAWgB,kBACd,gBACA,0BACA;;;UCTe;WACN;WACA;aAAqB;aAAwB;;;wBAGxC,eAAe,gBAAgB,gBAAkB;;;qBCPpD,yBAAyB;WAClB;;;;cCJP;cAEA;KAoBD;KAEP;WAAyB;WAA0B,OAAO;;KAE1D;WAA4B;WAA6B;;KAEzD;WACM;WACA,QAAQ;WACR,UAAU;;KAGT,wBAAwB;KAE/B;WACM;WACA,UAAU;WACV,UAAU;;KAGT,yBAAyB;KAEhC;WACM;WACA,UAAU;WACV,MAAM;WACN,OAAO;;KAGb;WACM;WACA,MAAM;WACN,YAAY;WACZ,WAAW;;KAGV,WACV,cAAc,iBAAiB,aAAa,gBAAgB,iBAAiB;;;wBCpD/D,gBAAgB,iBAAiB;;;UCPhC;WAEN;WAEA,YAAY,SAAS;;UAGf;WACN;WACA;WACA;WACA;WAEA,gBAAgB,SAAS;;;;wBCFpB,iBAAiB,gBAAgB,gBAAoB;wBAarD,iBAAiB,gBAAgB,gBAAyB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/globals.ts","../src/dot.ts","../src/errors.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts","../src/ast/page/types.ts","../src/ast/page/parse.ts"],"mappings":";;;wBAagB,kBACd,gBACA,0BACA;wBAcc,iBAAiB,gBAAgB,cAAc;;;UCzB9C;WACN;WACA;aAAqB;aAAwB;;;wBAGxC,eAAe,gBAAgB,gBAAkB;;;qBCPpD,yBAAyB;WAClB;;;;cCJP;cAEA;KAoBD;KAEP;WAAyB;WAA0B,OAAO;;KAE1D;WAA4B;WAA6B;;KAEzD;WACM;WACA,QAAQ;WACR,UAAU;;KAGT,wBAAwB;KAE/B;WACM;WACA,UAAU;WACV,UAAU;;KAGT,yBAAyB;KAEhC;WACM;WACA,UAAU;WACV,MAAM;WACN,OAAO;;KAGb;WACM;WACA,MAAM;WACN,YAAY;WACZ,WAAW;;KAGV,WACV,cAAc,iBAAiB,aAAa,gBAAgB,iBAAiB;;;wBCpD/D,gBAAgB,iBAAiB;;;UCPhC;WAEN;WAEA,YAAY,SAAS;;UAGf;WACN;WAEA;WACA;WACA;WACA;WAEA,gBAAgB,SAAS;;;;wBCHpB,iBAAiB,gBAAgB,gBAAoB;wBAarD,iBAAiB,gBAAgB,gBAAyB"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { parseSync } from "oxc-parser";
2
- import { PAGE_HOOKS, SourceError, isPageId, locationAt } from "@monimesl/dot-core";
2
+ import { MAX_SHARED_OPTIONS, PAGE_HOOKS, SourceError, isPageId, isSharedOptionName, locationAt } from "@monimesl/dot-core";
3
3
  //#region src/utils.ts
4
4
  function propertyName(key) {
5
5
  if (key.type === "Identifier") return key.name;
@@ -63,9 +63,16 @@ function defaultExport(program) {
63
63
  }
64
64
  function defineCall(program, source, file, callee) {
65
65
  const exported = defaultExport(program);
66
- const call = exported && unwrapExpression(exported);
67
- const options = call?.type === "CallExpression" ? call.arguments[0] : void 0;
68
- if (call?.type !== "CallExpression" || call.callee.type !== "Identifier" || call.callee.name !== callee || options?.type !== "ObjectExpression") return failAt(`${fileName(file)} must \`export default ${callee}({ ... })\``, source, exported?.start ?? 0, file);
66
+ let options;
67
+ if (exported) options = callOptions(unwrapExpression(exported), callee);
68
+ if (!options) return failAt(`${fileName(file)} must \`export default ${callee}({ ... })\``, source, exported?.start ?? 0, file);
69
+ return options;
70
+ }
71
+ function callOptions(expression, callee) {
72
+ if (expression.type !== "CallExpression") return;
73
+ if (expression.callee.type !== "Identifier" || expression.callee.name !== callee) return;
74
+ const [options] = expression.arguments;
75
+ if (options?.type !== "ObjectExpression") return;
69
76
  return options;
70
77
  }
71
78
  function fileName(path) {
@@ -78,9 +85,26 @@ function unboundReferences(source, names, file = "module.ts") {
78
85
  const program = parseModule(source, file);
79
86
  const bound = topLevelBindings(program);
80
87
  const references = /* @__PURE__ */ new Set();
81
- collectReferences(program, null, "", references);
88
+ forEachReference(program, (identifier) => {
89
+ references.add(identifier.name);
90
+ });
82
91
  return names.filter((name) => references.has(name) && !bound.has(name));
83
92
  }
93
+ function globalMemberUses(source, name, file = "module.ts") {
94
+ const program = parseModule(source, file);
95
+ if (topLevelBindings(program).has(name)) return [];
96
+ const uses = [];
97
+ forEachReference(program, (identifier, parent, key) => {
98
+ if (identifier.name === name) uses.push(memberRead(parent, key));
99
+ });
100
+ return uses;
101
+ }
102
+ function memberRead(parent, key) {
103
+ if (parent?.type !== "MemberExpression" || key !== "object" || parent.computed === true) return "";
104
+ const property = parent.property;
105
+ if (property?.type !== "Identifier") return "";
106
+ return property.name;
107
+ }
84
108
  function topLevelBindings(program) {
85
109
  const names = /* @__PURE__ */ new Set();
86
110
  for (const statement of program.body) {
@@ -99,31 +123,33 @@ function topLevelBindings(program) {
99
123
  return names;
100
124
  }
101
125
  function collectPatternNames(pattern, names) {
102
- const visit = (child) => {
103
- if (isNode(child)) collectPatternNames(child, names);
104
- };
126
+ if (!isNode(pattern)) return;
105
127
  switch (pattern.type) {
106
128
  case "Identifier":
107
129
  names.add(pattern.name);
108
130
  break;
109
131
  case "ObjectPattern":
110
- for (const property of pattern.properties) visit(property.type === "RestElement" ? property.argument : property.value);
132
+ for (const property of pattern.properties) if (property.type === "RestElement") collectPatternNames(property.argument, names);
133
+ else collectPatternNames(property.value, names);
111
134
  break;
112
135
  case "ArrayPattern":
113
- for (const element of pattern.elements) visit(element);
136
+ for (const element of pattern.elements) collectPatternNames(element, names);
114
137
  break;
115
138
  case "RestElement":
116
- visit(pattern.argument);
139
+ collectPatternNames(pattern.argument, names);
117
140
  break;
118
- case "AssignmentPattern": visit(pattern.left);
141
+ case "AssignmentPattern": collectPatternNames(pattern.left, names);
119
142
  }
120
143
  }
121
- function collectReferences(node, parent, key, references) {
144
+ function forEachReference(program, visit) {
145
+ visitReferences(program, null, "", visit);
146
+ }
147
+ function visitReferences(node, parent, key, visit) {
122
148
  if (node.type === "ImportDeclaration") return;
123
- if (node.type === "Identifier" && isReference(parent, key)) references.add(node.name);
149
+ if (node.type === "Identifier" && isReference(parent, key)) visit(node, parent, key);
124
150
  for (const [childKey, value] of Object.entries(node)) {
125
151
  const children = Array.isArray(value) ? value : [value];
126
- for (const child of children) if (isNode(child)) collectReferences(child, node, childKey, references);
152
+ for (const child of children) if (isNode(child)) visitReferences(child, node, childKey, visit);
127
153
  }
128
154
  }
129
155
  function isReference(parent, key) {
@@ -139,11 +165,13 @@ function isReference(parent, key) {
139
165
  }
140
166
  }
141
167
  function isNode(value) {
142
- return typeof value?.type === "string";
168
+ if (typeof value !== "object" || value === null) return false;
169
+ return typeof value.type === "string";
143
170
  }
144
171
  //#endregion
145
172
  //#region src/ast/page/parse.ts
146
173
  const HOOKS = new Set(PAGE_HOOKS);
174
+ const SHARE_EXAMPLE = "such as share: { options: ['show'] }";
147
175
  function parseStateModule(source, file = "state.ts") {
148
176
  const program = parseModule(source, file);
149
177
  const exported = defaultExport(program);
@@ -158,6 +186,7 @@ function parseLogicModule(source, file = "controller.ts") {
158
186
  const program = parseModule(source, file);
159
187
  const options = defineCall(program, source, file, "definePage");
160
188
  let id = null;
189
+ let share = null;
161
190
  let mutations = [];
162
191
  let actions = [];
163
192
  const hooks = [];
@@ -165,14 +194,13 @@ function parseLogicModule(source, file = "controller.ts") {
165
194
  case "initialState":
166
195
  case "configs": break;
167
196
  case "id":
168
- id = pageId(value, source, file);
197
+ id = readPageId(value, source, file);
198
+ break;
199
+ case "share":
200
+ share = readSharedOptions(value, source, file);
169
201
  break;
170
202
  case "hooks":
171
- if (value.type !== "ObjectExpression") break;
172
- for (const hook of staticProperties(value)) {
173
- if (!HOOKS.has(hook.name)) failAt(`Unknown page hook \`${hook.name}\`. The hooks are ${PAGE_HOOKS.join(", ")}`, source, hook.start, file);
174
- hooks.push(hook.name);
175
- }
203
+ hooks.push(...readHooks(value, source, file));
176
204
  break;
177
205
  case "mutations":
178
206
  mutations = resolvedProperties(program, value);
@@ -181,20 +209,53 @@ function parseLogicModule(source, file = "controller.ts") {
181
209
  actions = resolvedProperties(program, value);
182
210
  break;
183
211
  default: if (isFunction(value)) failAt(`\`${name}\` must go in \`mutations\` or \`actions\``, source, start, file);
184
- else failAt(`Unknown option \`${name}\`. definePage takes id, initialState, configs, hooks, mutations and actions`, source, start, file);
212
+ else failAt(`Unknown option \`${name}\`. definePage takes id, initialState, configs, share, hooks, mutations and actions`, source, start, file);
185
213
  }
186
214
  const mutationNames = namesOf(mutations);
187
215
  const actionNames = namesOf(actions);
188
- const clash = mutationNames?.find((name) => actionNames?.includes(name));
189
- if (clash) failAt(`\`${clash}\` is both a mutation and an action`, source, options.start, file);
216
+ if (mutationNames && actionNames) {
217
+ const clash = mutationNames.find((name) => actionNames.includes(name));
218
+ if (clash) failAt(`\`${clash}\` is both a mutation and an action`, source, options.start, file);
219
+ }
190
220
  return {
191
221
  id,
222
+ share,
192
223
  mutations: mutationNames,
193
224
  actions: actionNames,
194
225
  hooks,
195
226
  handlerOffsets: offsetsOf([...mutations ?? [], ...actions ?? []])
196
227
  };
197
228
  }
229
+ function readSharedOptions(node, source, file) {
230
+ const object = unwrapExpression(node);
231
+ if (object.type !== "ObjectExpression") return failAt(`Write \`share\` out in place, ${SHARE_EXAMPLE}`, source, node.start, file);
232
+ const properties = staticProperties(object);
233
+ if (properties.length !== object.properties.length) return failAt(`Write \`share\` out in place, ${SHARE_EXAMPLE}`, source, object.start, file);
234
+ const options = [];
235
+ for (const property of properties) {
236
+ if (property.name !== "options") return failAt(`Unknown share option \`${property.name}\`. share only takes options`, source, property.start, file);
237
+ const list = unwrapExpression(property.value);
238
+ if (list.type !== "ArrayExpression") return failAt(`share's options must be a list of names, ${SHARE_EXAMPLE}`, source, list.start, file);
239
+ for (const element of list.elements) {
240
+ if (!element || element.type !== "Literal" || typeof element.value !== "string") return failAt(`share's options must be names written as strings, ${SHARE_EXAMPLE}`, source, element?.start ?? list.start, file);
241
+ const name = element.value;
242
+ if (!isSharedOptionName(name)) return failAt(`"${name}" can't go in a link. Use letters, digits, "-" and "_"`, source, element.start, file);
243
+ if (options.includes(name)) return failAt(`"${name}" is in share's options twice`, source, element.start, file);
244
+ options.push(name);
245
+ }
246
+ if (options.length > MAX_SHARED_OPTIONS) return failAt(`A link can carry at most ${MAX_SHARED_OPTIONS} options`, source, list.start, file);
247
+ }
248
+ return options;
249
+ }
250
+ function readHooks(node, source, file) {
251
+ if (node.type !== "ObjectExpression") return [];
252
+ const hooks = [];
253
+ for (const hook of staticProperties(node)) {
254
+ if (!HOOKS.has(hook.name)) failAt(`Unknown page hook \`${hook.name}\`. The hooks are ${PAGE_HOOKS.join(", ")}`, source, hook.start, file);
255
+ hooks.push(hook.name);
256
+ }
257
+ return hooks;
258
+ }
198
259
  function isFunction(node) {
199
260
  return node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
200
261
  }
@@ -202,10 +263,12 @@ function resolvedProperties(program, node) {
202
263
  const object = resolveObject(program, node);
203
264
  if (!object) return null;
204
265
  const properties = staticProperties(object);
205
- return properties.length === object.properties.length ? properties : null;
266
+ if (properties.length !== object.properties.length) return null;
267
+ return properties;
206
268
  }
207
269
  function namesOf(properties) {
208
- return properties?.map((property) => property.name) ?? null;
270
+ if (properties === null) return null;
271
+ return properties.map((property) => property.name);
209
272
  }
210
273
  function offsetsOf(properties) {
211
274
  const offsets = {};
@@ -219,11 +282,15 @@ function resolveObject(program, node) {
219
282
  for (const statement of program.body) {
220
283
  const declaration = withoutExport(statement);
221
284
  if (declaration?.type !== "VariableDeclaration" || declaration.kind !== "const") continue;
222
- for (const declarator of declaration.declarations) if (declarator.id.type === "Identifier" && declarator.id.name === target.name) return declarator.init ? resolveObject(program, declarator.init) : null;
285
+ for (const declarator of declaration.declarations) {
286
+ if (declarator.id.type !== "Identifier" || declarator.id.name !== target.name) continue;
287
+ if (!declarator.init) return null;
288
+ return resolveObject(program, declarator.init);
289
+ }
223
290
  }
224
291
  return null;
225
292
  }
226
- function pageId(node, source, file) {
293
+ function readPageId(node, source, file) {
227
294
  const value = unwrapExpression(node);
228
295
  if (value.type !== "Literal" || typeof value.value !== "string") return failAt("A page id must be written as a string, such as 'cart'", source, node.start, file);
229
296
  if (!isPageId(value.value)) return failAt(`"${value.value}" isn't a valid page id. Use letters, digits, "-" and "_", with "/" between folders`, source, node.start, file);
@@ -236,19 +303,19 @@ function parseDotModule(source, file = "dot.ts") {
236
303
  const pagesProperty = staticProperties(options).find((property) => property.name === "pages");
237
304
  if (!pagesProperty) return failAt("defineDot needs `pages`, a list of page folders with the entry page first", source, options.start, file);
238
305
  const { value, start } = pagesProperty;
239
- const array = unwrapExpression(value);
240
- if (array.type !== "ArrayExpression") return failAt("`pages` must be a list of page folders", source, start, file);
241
- if (array.elements.length === 0) return failAt("`pages` needs at least one page", source, start, file);
242
- const pages = array.elements.map((element) => {
306
+ const pageList = unwrapExpression(value);
307
+ if (pageList.type !== "ArrayExpression") return failAt("`pages` must be a list of page folders", source, start, file);
308
+ if (pageList.elements.length === 0) return failAt("`pages` needs at least one page", source, start, file);
309
+ const pages = pageList.elements.map((element) => {
243
310
  if (!element || element.type === "SpreadElement") return failAt("`pages` must list each page folder as a string", source, element?.start ?? start, file);
244
- return pageId(element, source, file);
311
+ return readPageId(element, source, file);
245
312
  });
246
- const last = array.elements.at(-1);
313
+ const lastPage = pageList.elements.at(-1);
247
314
  return {
248
315
  pages,
249
316
  lastPage: {
250
- start: last.start,
251
- end: last.end
317
+ start: lastPage.start,
318
+ end: lastPage.end
252
319
  }
253
320
  };
254
321
  }
@@ -285,14 +352,14 @@ function parseExpression(source) {
285
352
  if (source.trim().length === 0) failAt("The binding is empty", source, 0);
286
353
  const { program, errors } = parseSync("binding.js", source, { preserveParens: false });
287
354
  failOnSyntaxError(errors, source);
288
- const [statement, extra] = program.body;
289
- if (!statement || extra || statement.type !== "ExpressionStatement") return failAt("A binding must be one expression", source, statement?.start ?? 0);
290
- return convert(statement.expression, source);
355
+ const statement = program.body[0];
356
+ if (program.body.length !== 1 || statement?.type !== "ExpressionStatement") return failAt("A binding must be one expression", source, statement?.start ?? 0);
357
+ return toExprNode(statement.expression, source);
291
358
  }
292
- function convert(node, source) {
359
+ function toExprNode(node, source) {
293
360
  switch (node.type) {
294
361
  case "Literal":
295
- if (typeof node.value === "bigint" || node.value instanceof RegExp) break;
362
+ if (typeof node.value === "bigint" || node.value instanceof RegExp) return failUnsupported(node, source);
296
363
  return {
297
364
  type: "Literal",
298
365
  value: node.value
@@ -302,12 +369,12 @@ function convert(node, source) {
302
369
  name: node.name
303
370
  };
304
371
  case "MemberExpression": {
305
- if (node.object.type === "Super" || node.property.type === "PrivateIdentifier") break;
306
- const object = convert(node.object, source);
372
+ if (node.object.type === "Super" || node.property.type === "PrivateIdentifier") return failUnsupported(node, source);
373
+ const object = toExprNode(node.object, source);
307
374
  if (node.computed) return {
308
375
  type: "Member",
309
376
  object,
310
- property: convert(node.property, source)
377
+ property: toExprNode(node.property, source)
311
378
  };
312
379
  return {
313
380
  type: "Member",
@@ -319,32 +386,35 @@ function convert(node, source) {
319
386
  };
320
387
  }
321
388
  case "UnaryExpression":
322
- if (!isOneOf(UNARY_OPERATORS, node.operator)) break;
389
+ if (!isOneOf(UNARY_OPERATORS, node.operator)) return failUnsupported(node, source);
323
390
  return {
324
391
  type: "Unary",
325
392
  operator: node.operator,
326
- argument: convert(node.argument, source)
393
+ argument: toExprNode(node.argument, source)
327
394
  };
328
395
  case "BinaryExpression":
329
396
  case "LogicalExpression":
330
- if (node.left.type === "PrivateIdentifier" || !isOneOf(BINARY_OPERATORS, node.operator)) break;
397
+ if (node.left.type === "PrivateIdentifier" || !isOneOf(BINARY_OPERATORS, node.operator)) return failUnsupported(node, source);
331
398
  return {
332
399
  type: "Binary",
333
400
  operator: node.operator,
334
- left: convert(node.left, source),
335
- right: convert(node.right, source)
401
+ left: toExprNode(node.left, source),
402
+ right: toExprNode(node.right, source)
336
403
  };
337
404
  case "ConditionalExpression": return {
338
405
  type: "Conditional",
339
- test: convert(node.test, source),
340
- consequent: convert(node.consequent, source),
341
- alternate: convert(node.alternate, source)
406
+ test: toExprNode(node.test, source),
407
+ consequent: toExprNode(node.consequent, source),
408
+ alternate: toExprNode(node.alternate, source)
342
409
  };
343
410
  case "CallExpression":
344
411
  case "NewExpression": return failAt("Bindings can't call functions", source, node.start);
345
412
  case "AssignmentExpression":
346
413
  case "UpdateExpression": return failAt("Bindings can't change values", source, node.start);
414
+ default: return failUnsupported(node, source);
347
415
  }
416
+ }
417
+ function failUnsupported(node, source) {
348
418
  let detail = "";
349
419
  if ("operator" in node) detail = ` \`${node.operator}\``;
350
420
  return failAt(`Bindings can't use ${node.type}${detail}`, source, node.start);
@@ -353,6 +423,6 @@ function isOneOf(list, value) {
353
423
  return list.includes(value);
354
424
  }
355
425
  //#endregion
356
- export { ScriptParseError, parseDotModule, parseExpression, parseLogicModule, parseStateModule, unboundReferences };
426
+ export { ScriptParseError, globalMemberUses, parseDotModule, parseExpression, parseLogicModule, parseStateModule, unboundReferences };
357
427
 
358
428
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/errors.ts","../src/module.ts","../src/globals.ts","../src/ast/page/parse.ts","../src/dot.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts"],"sourcesContent":["import type { Expression, ObjectExpression, Program, PropertyKey } from 'oxc-parser';\n\ntype TopLevelStatement = Program['body'][number];\n\nfunction propertyName(key: PropertyKey): string | null {\n if (key.type === 'Identifier') {\n return key.name;\n }\n if (key.type === 'Literal' && typeof key.value === 'string') {\n return key.value;\n }\n return null;\n}\n\nexport function unwrapExpression(node: Expression): Expression {\n while (\n node.type === 'TSAsExpression' ||\n node.type === 'TSSatisfiesExpression' ||\n node.type === 'TSNonNullExpression'\n ) {\n node = node.expression;\n }\n return node;\n}\n\nexport interface StaticProperty {\n readonly name: string;\n readonly value: Expression;\n readonly start: number;\n}\n\n// The properties of an object literal whose names are written out. Computed ones are skipped.\nexport function staticProperties(object: ObjectExpression): StaticProperty[] {\n const properties: StaticProperty[] = [];\n for (const property of object.properties) {\n if (property.type !== 'Property' || property.computed) {\n continue;\n }\n const name = propertyName(property.key);\n if (name !== null) {\n properties.push({ name, value: property.value, start: property.start });\n }\n }\n return properties;\n}\n\n// Unwraps `export const ...` and the like to the declaration. Other statements pass through.\nexport function withoutExport(statement: TopLevelStatement): TopLevelStatement | null {\n if (statement.type === 'ExportNamedDeclaration') {\n return statement.declaration;\n }\n return statement;\n}\n","import type { OxcError } from 'oxc-parser';\nimport { locationAt, SourceError } from '@monimesl/dot-core';\n\nexport class ScriptParseError extends SourceError {\n override readonly name = 'ScriptParseError';\n}\n\nexport function failAt(reason: string, source: string, offset: number, file?: string): never {\n throw new ScriptParseError(reason, file, locationAt(source, offset));\n}\n\nexport function failOnSyntaxError(\n errors: readonly OxcError[],\n source: string,\n file?: string,\n): void {\n const [error] = errors;\n if (error) {\n failAt(error.message, source, error.labels[0]?.start ?? 0, file);\n }\n}\n","import { parseSync } from 'oxc-parser';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport { unwrapExpression } from './utils';\nimport { failAt, failOnSyntaxError } from './errors';\n\nexport function parseModule(source: string, file: string): Program {\n const { program, errors } = parseSync(file, source, { lang: 'ts', sourceType: 'module' });\n failOnSyntaxError(errors, source, file);\n return program;\n}\n\nexport function defaultExport(program: Program): Expression | undefined {\n for (const statement of program.body) {\n if (statement.type !== 'ExportDefaultDeclaration') {\n continue;\n }\n const { declaration } = statement;\n switch (declaration.type) {\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n case 'TSInterfaceDeclaration':\n return undefined;\n default:\n return declaration;\n }\n }\n return undefined;\n}\n\nexport function defineCall(\n program: Program,\n source: string,\n file: string,\n callee: string,\n): ObjectExpression {\n const exported = defaultExport(program);\n const call = exported && unwrapExpression(exported);\n const options = call?.type === 'CallExpression' ? call.arguments[0] : undefined;\n if (\n call?.type !== 'CallExpression' ||\n call.callee.type !== 'Identifier' ||\n call.callee.name !== callee ||\n options?.type !== 'ObjectExpression'\n ) {\n return failAt(\n `${fileName(file)} must \\`export default ${callee}({ ... })\\``,\n source,\n exported?.start ?? 0,\n file,\n );\n }\n return options;\n}\n\n// The last segment of a path, with either separator.\nfunction fileName(path: string): string {\n const lastSeparator = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n return path.slice(lastSeparator + 1);\n}\n","import type { Program } from 'oxc-parser';\n\nimport { parseModule } from './module';\nimport { withoutExport } from './utils';\n\ninterface Node {\n readonly type: string;\n readonly [key: string]: unknown;\n}\n\n// Which of `names` a module uses without declaring or importing, for the compiler to import.\nexport function unboundReferences(\n source: string,\n names: readonly string[],\n file = 'module.ts',\n): string[] {\n const program = parseModule(source, file);\n const bound = topLevelBindings(program);\n const references = new Set<string>();\n collectReferences(program as unknown as Node, null, '', references);\n return names.filter((name) => references.has(name) && !bound.has(name));\n}\n\nfunction topLevelBindings(program: Program): Set<string> {\n const names = new Set<string>();\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n switch (declaration?.type) {\n case 'ImportDeclaration':\n for (const specifier of declaration.specifiers) {\n names.add(specifier.local.name);\n }\n break;\n case 'VariableDeclaration':\n for (const declarator of declaration.declarations) {\n collectPatternNames(declarator.id as unknown as Node, names);\n }\n break;\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n if (declaration.id) {\n names.add(declaration.id.name);\n }\n break;\n }\n }\n return names;\n}\n\nfunction collectPatternNames(pattern: Node, names: Set<string>): void {\n const visit = (child: unknown) => {\n if (isNode(child)) {\n collectPatternNames(child, names);\n }\n };\n switch (pattern.type) {\n case 'Identifier':\n names.add(pattern.name as string);\n break;\n case 'ObjectPattern':\n for (const property of pattern.properties as Node[]) {\n visit(property.type === 'RestElement' ? property.argument : property.value);\n }\n break;\n case 'ArrayPattern':\n for (const element of pattern.elements as unknown[]) {\n visit(element);\n }\n break;\n case 'RestElement':\n visit(pattern.argument);\n break;\n case 'AssignmentPattern':\n visit(pattern.left);\n break;\n }\n}\n\nfunction collectReferences(\n node: Node,\n parent: Node | null,\n key: string,\n references: Set<string>,\n): void {\n if (node.type === 'ImportDeclaration') {\n return;\n }\n if (node.type === 'Identifier' && isReference(parent, key)) {\n references.add(node.name as string);\n }\n for (const [childKey, value] of Object.entries(node)) {\n const children: unknown[] = Array.isArray(value) ? value : [value];\n for (const child of children) {\n if (isNode(child)) {\n collectReferences(child, node, childKey, references);\n }\n }\n }\n}\n\n// False for identifiers that name a property or label rather than refer to a variable.\nfunction isReference(parent: Node | null, key: string): boolean {\n switch (parent?.type) {\n case 'MemberExpression':\n return key !== 'property' || parent.computed === true;\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n return key !== 'key' || parent.computed === true;\n case 'LabeledStatement':\n case 'BreakStatement':\n case 'ContinueStatement':\n return key !== 'label';\n default:\n return true;\n }\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof (value as Node | null)?.type === 'string';\n}\n","import { isPageId, PAGE_HOOKS } from '@monimesl/dot-core';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport type { PageModule, PageStateModule } from './types';\nimport { failAt } from '../../errors';\nimport { defaultExport, defineCall, parseModule } from '../../module';\nimport type { StaticProperty } from '../../utils';\nimport { staticProperties, unwrapExpression, withoutExport } from '../../utils';\n\nconst HOOKS = new Set<string>(PAGE_HOOKS);\n\nexport function parseStateModule(source: string, file = 'state.ts'): PageStateModule {\n const program = parseModule(source, file);\n const exported = defaultExport(program);\n if (!exported) {\n return failAt('state.ts must have a default export', source, 0, file);\n }\n const properties = resolvedProperties(program, exported);\n return {\n keys: namesOf(properties),\n keyOffsets: offsetsOf(properties ?? []),\n };\n}\n\nexport function parseLogicModule(source: string, file = 'controller.ts'): PageModule {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'definePage');\n let id: string | null = null;\n let mutations: StaticProperty[] | null = [];\n let actions: StaticProperty[] | null = [];\n const hooks: string[] = [];\n for (const { name, value, start } of staticProperties(options)) {\n switch (name) {\n case 'initialState':\n case 'configs':\n break;\n case 'id':\n id = pageId(value, source, file);\n break;\n case 'hooks':\n if (value.type !== 'ObjectExpression') {\n break;\n }\n for (const hook of staticProperties(value)) {\n if (!HOOKS.has(hook.name)) {\n failAt(\n `Unknown page hook \\`${hook.name}\\`. The hooks are ${PAGE_HOOKS.join(', ')}`,\n source,\n hook.start,\n file,\n );\n }\n hooks.push(hook.name);\n }\n break;\n case 'mutations':\n mutations = resolvedProperties(program, value);\n break;\n case 'actions':\n actions = resolvedProperties(program, value);\n break;\n default:\n if (isFunction(value)) {\n failAt(`\\`${name}\\` must go in \\`mutations\\` or \\`actions\\``, source, start, file);\n } else {\n failAt(\n `Unknown option \\`${name}\\`. definePage takes id, initialState, configs, hooks, mutations and actions`,\n source,\n start,\n file,\n );\n }\n }\n }\n const mutationNames = namesOf(mutations);\n const actionNames = namesOf(actions);\n const clash = mutationNames?.find((name) => actionNames?.includes(name));\n if (clash) {\n failAt(`\\`${clash}\\` is both a mutation and an action`, source, options.start, file);\n }\n return {\n id,\n mutations: mutationNames,\n actions: actionNames,\n hooks,\n handlerOffsets: offsetsOf([...(mutations ?? []), ...(actions ?? [])]),\n };\n}\n\nfunction isFunction(node: Expression): boolean {\n return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';\n}\n\n// The properties of the object literal that `node` is or names. Null when any can't be read\n// without running the code.\nfunction resolvedProperties(program: Program, node: Expression): StaticProperty[] | null {\n const object = resolveObject(program, node);\n if (!object) {\n return null;\n }\n const properties = staticProperties(object);\n return properties.length === object.properties.length ? properties : null;\n}\n\nfunction namesOf(properties: readonly StaticProperty[] | null): string[] | null {\n return properties?.map((property) => property.name) ?? null;\n}\n\nfunction offsetsOf(properties: readonly StaticProperty[]): Record<string, number> {\n const offsets: Record<string, number> = {};\n for (const property of properties) {\n offsets[property.name] = property.start;\n }\n return offsets;\n}\n\n// Follows `export default state` back to `const state = { ... }`.\nfunction resolveObject(program: Program, node: Expression): ObjectExpression | null {\n const target = unwrapExpression(node);\n if (target.type === 'ObjectExpression') {\n return target;\n }\n if (target.type !== 'Identifier') {\n return null;\n }\n\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n if (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') {\n continue;\n }\n for (const declarator of declaration.declarations) {\n if (declarator.id.type === 'Identifier' && declarator.id.name === target.name) {\n return declarator.init ? resolveObject(program, declarator.init) : null;\n }\n }\n }\n return null;\n}\n\nexport function pageId(node: Expression, source: string, file: string): string {\n const value = unwrapExpression(node);\n if (value.type !== 'Literal' || typeof value.value !== 'string') {\n return failAt(\n \"A page id must be written as a string, such as 'cart'\",\n source,\n node.start,\n file,\n );\n }\n if (!isPageId(value.value)) {\n return failAt(\n `\"${value.value}\" isn't a valid page id. Use letters, digits, \"-\" and \"_\", with \"/\" between folders`,\n source,\n node.start,\n file,\n );\n }\n return value.value;\n}\n","import { failAt } from './errors';\nimport { pageId } from './ast/page/parse';\nimport { defineCall, parseModule } from './module';\nimport { staticProperties, unwrapExpression } from './utils';\n\nexport interface DotModuleIR {\n readonly pages: readonly string[];\n readonly lastPage: { readonly start: number; readonly end: number };\n}\n\nexport function parseDotModule(source: string, file = 'dot.ts'): DotModuleIR {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'defineDot');\n const pagesProperty = staticProperties(options).find((property) => property.name === 'pages');\n if (!pagesProperty) {\n return failAt(\n 'defineDot needs `pages`, a list of page folders with the entry page first',\n source,\n options.start,\n file,\n );\n }\n const { value, start } = pagesProperty;\n const array = unwrapExpression(value);\n if (array.type !== 'ArrayExpression') {\n return failAt('`pages` must be a list of page folders', source, start, file);\n }\n if (array.elements.length === 0) {\n return failAt('`pages` needs at least one page', source, start, file);\n }\n const pages = array.elements.map((element) => {\n if (!element || element.type === 'SpreadElement') {\n return failAt(\n '`pages` must list each page folder as a string',\n source,\n element?.start ?? start,\n file,\n );\n }\n return pageId(element, source, file);\n });\n const last = array.elements.at(-1)!;\n return { pages, lastPage: { start: last.start, end: last.end } };\n}\n","export const UNARY_OPERATORS = ['!', '-', '+', 'typeof'] as const;\n\nexport const BINARY_OPERATORS = [\n '==',\n '!=',\n '===',\n '!==',\n '<',\n '<=',\n '>',\n '>=',\n '+',\n '-',\n '*',\n '/',\n '%',\n '**',\n '&&',\n '||',\n '??',\n] as const;\n\nexport type LiteralValue = string | number | boolean | null;\n\ntype LiteralNode = { readonly type: 'Literal'; readonly value: LiteralValue };\n\ntype IdentifierNode = { readonly type: 'Identifier'; readonly name: string };\n\ntype MemberNode = {\n readonly type: 'Member';\n readonly object: ExprNode;\n readonly property: ExprNode;\n};\n\nexport type UnaryOperator = (typeof UNARY_OPERATORS)[number];\n\ntype UnaryExprNode = {\n readonly type: 'Unary';\n readonly operator: UnaryOperator;\n readonly argument: ExprNode;\n};\n\nexport type BinaryOperator = (typeof BINARY_OPERATORS)[number];\n\ntype BinaryExprNode = {\n readonly type: 'Binary';\n readonly operator: BinaryOperator;\n readonly left: ExprNode;\n readonly right: ExprNode;\n};\n\ntype ConditionalExprNode = {\n readonly type: 'Conditional';\n readonly test: ExprNode;\n readonly consequent: ExprNode;\n readonly alternate: ExprNode;\n};\n\nexport type ExprNode =\n LiteralNode | IdentifierNode | MemberNode | UnaryExprNode | BinaryExprNode | ConditionalExprNode;\n","import type { Expression } from 'oxc-parser';\nimport { parseSync } from 'oxc-parser';\n\nimport { failAt, failOnSyntaxError } from '../../errors';\nimport { BINARY_OPERATORS, type ExprNode, UNARY_OPERATORS } from './types';\n\n// Parses what's inside a `{{ }}` binding into an expression tree.\nexport function parseExpression(source: string): ExprNode {\n if (source.trim().length === 0) {\n failAt('The binding is empty', source, 0);\n }\n const { program, errors } = parseSync('binding.js', source, { preserveParens: false });\n failOnSyntaxError(errors, source);\n const [statement, extra] = program.body;\n if (!statement || extra || statement.type !== 'ExpressionStatement') {\n return failAt('A binding must be one expression', source, statement?.start ?? 0);\n }\n return convert(statement.expression, source);\n}\n\nfunction convert(node: Expression, source: string): ExprNode {\n switch (node.type) {\n case 'Literal':\n if (typeof node.value === 'bigint' || node.value instanceof RegExp) {\n break;\n }\n return { type: 'Literal', value: node.value };\n case 'Identifier':\n return { type: 'Identifier', name: node.name };\n case 'MemberExpression': {\n if (node.object.type === 'Super' || node.property.type === 'PrivateIdentifier') {\n break;\n }\n const object = convert(node.object, source);\n if (node.computed) {\n return { type: 'Member', object, property: convert(node.property, source) };\n }\n return { type: 'Member', object, property: { type: 'Literal', value: node.property.name } };\n }\n case 'UnaryExpression':\n if (!isOneOf(UNARY_OPERATORS, node.operator)) {\n break;\n }\n return { type: 'Unary', operator: node.operator, argument: convert(node.argument, source) };\n case 'BinaryExpression':\n case 'LogicalExpression':\n if (node.left.type === 'PrivateIdentifier' || !isOneOf(BINARY_OPERATORS, node.operator)) {\n break;\n }\n return {\n type: 'Binary',\n operator: node.operator,\n left: convert(node.left, source),\n right: convert(node.right, source),\n };\n case 'ConditionalExpression':\n return {\n type: 'Conditional',\n test: convert(node.test, source),\n consequent: convert(node.consequent, source),\n alternate: convert(node.alternate, source),\n };\n case 'CallExpression':\n case 'NewExpression':\n return failAt(\"Bindings can't call functions\", source, node.start);\n case 'AssignmentExpression':\n case 'UpdateExpression':\n return failAt(\"Bindings can't change values\", source, node.start);\n }\n let detail = '';\n if ('operator' in node) {\n detail = ` \\`${node.operator}\\``;\n }\n return failAt(`Bindings can't use ${node.type}${detail}`, source, node.start);\n}\n\nfunction isOneOf<T extends string>(list: readonly T[], value: string): value is T {\n return (list as readonly string[]).includes(value);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/errors.ts","../src/module.ts","../src/globals.ts","../src/ast/page/parse.ts","../src/dot.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts"],"sourcesContent":["import type { Expression, ObjectExpression, Program, PropertyKey } from 'oxc-parser';\n\ntype TopLevelStatement = Program['body'][number];\n\nfunction propertyName(key: PropertyKey): string | null {\n if (key.type === 'Identifier') {\n return key.name;\n }\n if (key.type === 'Literal' && typeof key.value === 'string') {\n return key.value;\n }\n return null;\n}\n\nexport function unwrapExpression(node: Expression): Expression {\n while (\n node.type === 'TSAsExpression' ||\n node.type === 'TSSatisfiesExpression' ||\n node.type === 'TSNonNullExpression'\n ) {\n node = node.expression;\n }\n return node;\n}\n\nexport interface StaticProperty {\n readonly name: string;\n readonly value: Expression;\n readonly start: number;\n}\n\n// The properties of an object literal whose names are written out. Computed ones are skipped.\nexport function staticProperties(object: ObjectExpression): StaticProperty[] {\n const properties: StaticProperty[] = [];\n for (const property of object.properties) {\n if (property.type !== 'Property' || property.computed) {\n continue;\n }\n const name = propertyName(property.key);\n if (name !== null) {\n properties.push({ name, value: property.value, start: property.start });\n }\n }\n return properties;\n}\n\n// Unwraps `export const ...` and the like to the declaration. Other statements pass through.\nexport function withoutExport(statement: TopLevelStatement): TopLevelStatement | null {\n if (statement.type === 'ExportNamedDeclaration') {\n return statement.declaration;\n }\n return statement;\n}\n","import type { OxcError } from 'oxc-parser';\nimport { locationAt, SourceError } from '@monimesl/dot-core';\n\nexport class ScriptParseError extends SourceError {\n override readonly name = 'ScriptParseError';\n}\n\nexport function failAt(reason: string, source: string, offset: number, file?: string): never {\n throw new ScriptParseError(reason, file, locationAt(source, offset));\n}\n\nexport function failOnSyntaxError(\n errors: readonly OxcError[],\n source: string,\n file?: string,\n): void {\n const [error] = errors;\n if (error) {\n failAt(error.message, source, error.labels[0]?.start ?? 0, file);\n }\n}\n","import { parseSync } from 'oxc-parser';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport { unwrapExpression } from './utils';\nimport { failAt, failOnSyntaxError } from './errors';\n\nexport function parseModule(source: string, file: string): Program {\n const { program, errors } = parseSync(file, source, { lang: 'ts', sourceType: 'module' });\n failOnSyntaxError(errors, source, file);\n return program;\n}\n\nexport function defaultExport(program: Program): Expression | undefined {\n for (const statement of program.body) {\n if (statement.type !== 'ExportDefaultDeclaration') {\n continue;\n }\n const { declaration } = statement;\n switch (declaration.type) {\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n case 'TSInterfaceDeclaration':\n return undefined;\n default:\n return declaration;\n }\n }\n return undefined;\n}\n\n// The `{ ... }` in `export default <callee>({ ... })`.\nexport function defineCall(\n program: Program,\n source: string,\n file: string,\n callee: string,\n): ObjectExpression {\n const exported = defaultExport(program);\n let options: ObjectExpression | undefined;\n if (exported) {\n options = callOptions(unwrapExpression(exported), callee);\n }\n if (!options) {\n return failAt(\n `${fileName(file)} must \\`export default ${callee}({ ... })\\``,\n source,\n exported?.start ?? 0,\n file,\n );\n }\n return options;\n}\n\nfunction callOptions(expression: Expression, callee: string): ObjectExpression | undefined {\n if (expression.type !== 'CallExpression') {\n return undefined;\n }\n if (expression.callee.type !== 'Identifier' || expression.callee.name !== callee) {\n return undefined;\n }\n const [options] = expression.arguments;\n if (options?.type !== 'ObjectExpression') {\n return undefined;\n }\n return options;\n}\n\n// The last segment of a path, with either separator.\nfunction fileName(path: string): string {\n const lastSeparator = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n return path.slice(lastSeparator + 1);\n}\n","import type { Program } from 'oxc-parser';\n\nimport { parseModule } from './module';\nimport { withoutExport } from './utils';\n\ninterface Node {\n readonly type: string;\n readonly [key: string]: unknown;\n}\n\ntype ReferenceVisitor = (identifier: Node, parent: Node | null, key: string) => void;\n\n// Which of `names` a module uses without declaring or importing, for the compiler to import.\nexport function unboundReferences(\n source: string,\n names: readonly string[],\n file = 'module.ts',\n): string[] {\n const program = parseModule(source, file);\n const bound = topLevelBindings(program);\n const references = new Set<string>();\n forEachReference(program, (identifier) => {\n references.add(identifier.name as string);\n });\n return names.filter((name) => references.has(name) && !bound.has(name));\n}\n\n// The first property read off each use of the global `name`, such as \"utils\" for\n// `dash.utils.base64.encode(text)`, and \"\" for a use that reads none, such as passing it along.\n// None when the module declares or imports its own `name`.\nexport function globalMemberUses(source: string, name: string, file = 'module.ts'): string[] {\n const program = parseModule(source, file);\n if (topLevelBindings(program).has(name)) {\n return [];\n }\n const uses: string[] = [];\n forEachReference(program, (identifier, parent, key) => {\n if (identifier.name === name) {\n uses.push(memberRead(parent, key));\n }\n });\n return uses;\n}\n\n// The property name in `name.property`, or \"\" when the identifier isn't read that way.\nfunction memberRead(parent: Node | null, key: string): string {\n if (parent?.type !== 'MemberExpression' || key !== 'object' || parent.computed === true) {\n return '';\n }\n const property = parent.property as Node | undefined;\n if (property?.type !== 'Identifier') {\n return '';\n }\n return property.name as string;\n}\n\nfunction topLevelBindings(program: Program): Set<string> {\n const names = new Set<string>();\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n switch (declaration?.type) {\n case 'ImportDeclaration':\n for (const specifier of declaration.specifiers) {\n names.add(specifier.local.name);\n }\n break;\n case 'VariableDeclaration':\n for (const declarator of declaration.declarations) {\n collectPatternNames(declarator.id, names);\n }\n break;\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n if (declaration.id) {\n names.add(declaration.id.name);\n }\n break;\n }\n }\n return names;\n}\n\nfunction collectPatternNames(pattern: unknown, names: Set<string>): void {\n if (!isNode(pattern)) {\n return;\n }\n switch (pattern.type) {\n case 'Identifier':\n names.add(pattern.name as string);\n break;\n case 'ObjectPattern':\n for (const property of pattern.properties as Node[]) {\n if (property.type === 'RestElement') {\n collectPatternNames(property.argument, names);\n } else {\n collectPatternNames(property.value, names);\n }\n }\n break;\n case 'ArrayPattern':\n for (const element of pattern.elements as unknown[]) {\n collectPatternNames(element, names);\n }\n break;\n case 'RestElement':\n collectPatternNames(pattern.argument, names);\n break;\n case 'AssignmentPattern':\n collectPatternNames(pattern.left, names);\n break;\n }\n}\n\n// Visits each identifier that refers to a variable, in source order. Imports are skipped, since\n// they declare names rather than use them.\nfunction forEachReference(program: Program, visit: ReferenceVisitor): void {\n visitReferences(program as unknown as Node, null, '', visit);\n}\n\nfunction visitReferences(\n node: Node,\n parent: Node | null,\n key: string,\n visit: ReferenceVisitor,\n): void {\n if (node.type === 'ImportDeclaration') {\n return;\n }\n if (node.type === 'Identifier' && isReference(parent, key)) {\n visit(node, parent, key);\n }\n for (const [childKey, value] of Object.entries(node)) {\n const children: unknown[] = Array.isArray(value) ? value : [value];\n for (const child of children) {\n if (isNode(child)) {\n visitReferences(child, node, childKey, visit);\n }\n }\n }\n}\n\n// False for identifiers that name a property or label rather than refer to a variable.\nfunction isReference(parent: Node | null, key: string): boolean {\n switch (parent?.type) {\n case 'MemberExpression':\n return key !== 'property' || parent.computed === true;\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n return key !== 'key' || parent.computed === true;\n case 'LabeledStatement':\n case 'BreakStatement':\n case 'ContinueStatement':\n return key !== 'label';\n default:\n return true;\n }\n}\n\nfunction isNode(value: unknown): value is Node {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n return typeof (value as { type?: unknown }).type === 'string';\n}\n","import { isPageId, isSharedOptionName, MAX_SHARED_OPTIONS, PAGE_HOOKS } from '@monimesl/dot-core';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport type { PageModule, PageStateModule } from './types';\nimport { failAt } from '../../errors';\nimport { defaultExport, defineCall, parseModule } from '../../module';\nimport type { StaticProperty } from '../../utils';\nimport { staticProperties, unwrapExpression, withoutExport } from '../../utils';\n\nconst HOOKS = new Set<string>(PAGE_HOOKS);\nconst SHARE_EXAMPLE = \"such as share: { options: ['show'] }\";\n\nexport function parseStateModule(source: string, file = 'state.ts'): PageStateModule {\n const program = parseModule(source, file);\n const exported = defaultExport(program);\n if (!exported) {\n return failAt('state.ts must have a default export', source, 0, file);\n }\n const properties = resolvedProperties(program, exported);\n return {\n keys: namesOf(properties),\n keyOffsets: offsetsOf(properties ?? []),\n };\n}\n\nexport function parseLogicModule(source: string, file = 'controller.ts'): PageModule {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'definePage');\n let id: string | null = null;\n let share: string[] | null = null;\n let mutations: StaticProperty[] | null = [];\n let actions: StaticProperty[] | null = [];\n const hooks: string[] = [];\n for (const { name, value, start } of staticProperties(options)) {\n switch (name) {\n case 'initialState':\n case 'configs':\n break;\n case 'id':\n id = readPageId(value, source, file);\n break;\n case 'share':\n share = readSharedOptions(value, source, file);\n break;\n case 'hooks':\n hooks.push(...readHooks(value, source, file));\n break;\n case 'mutations':\n mutations = resolvedProperties(program, value);\n break;\n case 'actions':\n actions = resolvedProperties(program, value);\n break;\n default:\n if (isFunction(value)) {\n failAt(`\\`${name}\\` must go in \\`mutations\\` or \\`actions\\``, source, start, file);\n } else {\n failAt(\n `Unknown option \\`${name}\\`. definePage takes id, initialState, configs, share, hooks, mutations and actions`,\n source,\n start,\n file,\n );\n }\n }\n }\n const mutationNames = namesOf(mutations);\n const actionNames = namesOf(actions);\n if (mutationNames && actionNames) {\n const clash = mutationNames.find((name) => actionNames.includes(name));\n if (clash) {\n failAt(`\\`${clash}\\` is both a mutation and an action`, source, options.start, file);\n }\n }\n return {\n id,\n share,\n mutations: mutationNames,\n actions: actionNames,\n hooks,\n handlerOffsets: offsetsOf([...(mutations ?? []), ...(actions ?? [])]),\n };\n}\n\n// `share: { options: ['show'] }`, written out so the build can read it.\nfunction readSharedOptions(node: Expression, source: string, file: string): string[] {\n const object = unwrapExpression(node);\n if (object.type !== 'ObjectExpression') {\n return failAt(`Write \\`share\\` out in place, ${SHARE_EXAMPLE}`, source, node.start, file);\n }\n const properties = staticProperties(object);\n if (properties.length !== object.properties.length) {\n return failAt(`Write \\`share\\` out in place, ${SHARE_EXAMPLE}`, source, object.start, file);\n }\n const options: string[] = [];\n for (const property of properties) {\n if (property.name !== 'options') {\n return failAt(\n `Unknown share option \\`${property.name}\\`. share only takes options`,\n source,\n property.start,\n file,\n );\n }\n const list = unwrapExpression(property.value);\n if (list.type !== 'ArrayExpression') {\n return failAt(\n `share's options must be a list of names, ${SHARE_EXAMPLE}`,\n source,\n list.start,\n file,\n );\n }\n for (const element of list.elements) {\n if (!element || element.type !== 'Literal' || typeof element.value !== 'string') {\n return failAt(\n `share's options must be names written as strings, ${SHARE_EXAMPLE}`,\n source,\n element?.start ?? list.start,\n file,\n );\n }\n const name = element.value;\n if (!isSharedOptionName(name)) {\n return failAt(\n `\"${name}\" can't go in a link. Use letters, digits, \"-\" and \"_\"`,\n source,\n element.start,\n file,\n );\n }\n if (options.includes(name)) {\n return failAt(`\"${name}\" is in share's options twice`, source, element.start, file);\n }\n options.push(name);\n }\n if (options.length > MAX_SHARED_OPTIONS) {\n return failAt(\n `A link can carry at most ${MAX_SHARED_OPTIONS} options`,\n source,\n list.start,\n file,\n );\n }\n }\n return options;\n}\n\n// Only hooks written in an object literal are checked.\nfunction readHooks(node: Expression, source: string, file: string): string[] {\n if (node.type !== 'ObjectExpression') {\n return [];\n }\n const hooks: string[] = [];\n for (const hook of staticProperties(node)) {\n if (!HOOKS.has(hook.name)) {\n failAt(\n `Unknown page hook \\`${hook.name}\\`. The hooks are ${PAGE_HOOKS.join(', ')}`,\n source,\n hook.start,\n file,\n );\n }\n hooks.push(hook.name);\n }\n return hooks;\n}\n\nfunction isFunction(node: Expression): boolean {\n return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';\n}\n\n// The properties of the object literal that `node` is or names. Null when any can't be read\n// without running the code.\nfunction resolvedProperties(program: Program, node: Expression): StaticProperty[] | null {\n const object = resolveObject(program, node);\n if (!object) {\n return null;\n }\n const properties = staticProperties(object);\n if (properties.length !== object.properties.length) {\n return null;\n }\n return properties;\n}\n\nfunction namesOf(properties: readonly StaticProperty[] | null): string[] | null {\n if (properties === null) {\n return null;\n }\n return properties.map((property) => property.name);\n}\n\nfunction offsetsOf(properties: readonly StaticProperty[]): Record<string, number> {\n const offsets: Record<string, number> = {};\n for (const property of properties) {\n offsets[property.name] = property.start;\n }\n return offsets;\n}\n\n// Follows `export default state` back to `const state = { ... }`.\nfunction resolveObject(program: Program, node: Expression): ObjectExpression | null {\n const target = unwrapExpression(node);\n if (target.type === 'ObjectExpression') {\n return target;\n }\n if (target.type !== 'Identifier') {\n return null;\n }\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n if (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') {\n continue;\n }\n for (const declarator of declaration.declarations) {\n if (declarator.id.type !== 'Identifier' || declarator.id.name !== target.name) {\n continue;\n }\n if (!declarator.init) {\n return null;\n }\n return resolveObject(program, declarator.init);\n }\n }\n return null;\n}\n\nexport function readPageId(node: Expression, source: string, file: string): string {\n const value = unwrapExpression(node);\n if (value.type !== 'Literal' || typeof value.value !== 'string') {\n return failAt(\n \"A page id must be written as a string, such as 'cart'\",\n source,\n node.start,\n file,\n );\n }\n if (!isPageId(value.value)) {\n return failAt(\n `\"${value.value}\" isn't a valid page id. Use letters, digits, \"-\" and \"_\", with \"/\" between folders`,\n source,\n node.start,\n file,\n );\n }\n return value.value;\n}\n","import { failAt } from './errors';\nimport { readPageId } from './ast/page/parse';\nimport { defineCall, parseModule } from './module';\nimport { staticProperties, unwrapExpression } from './utils';\n\nexport interface DotModuleIR {\n readonly pages: readonly string[];\n readonly lastPage: { readonly start: number; readonly end: number };\n}\n\nexport function parseDotModule(source: string, file = 'dot.ts'): DotModuleIR {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'defineDot');\n const pagesProperty = staticProperties(options).find((property) => property.name === 'pages');\n if (!pagesProperty) {\n return failAt(\n 'defineDot needs `pages`, a list of page folders with the entry page first',\n source,\n options.start,\n file,\n );\n }\n const { value, start } = pagesProperty;\n const pageList = unwrapExpression(value);\n if (pageList.type !== 'ArrayExpression') {\n return failAt('`pages` must be a list of page folders', source, start, file);\n }\n if (pageList.elements.length === 0) {\n return failAt('`pages` needs at least one page', source, start, file);\n }\n const pages = pageList.elements.map((element) => {\n if (!element || element.type === 'SpreadElement') {\n return failAt(\n '`pages` must list each page folder as a string',\n source,\n element?.start ?? start,\n file,\n );\n }\n return readPageId(element, source, file);\n });\n // The check above fails on a hole, so the last element is there.\n const lastPage = pageList.elements.at(-1)!;\n return { pages, lastPage: { start: lastPage.start, end: lastPage.end } };\n}\n","export const UNARY_OPERATORS = ['!', '-', '+', 'typeof'] as const;\n\nexport const BINARY_OPERATORS = [\n '==',\n '!=',\n '===',\n '!==',\n '<',\n '<=',\n '>',\n '>=',\n '+',\n '-',\n '*',\n '/',\n '%',\n '**',\n '&&',\n '||',\n '??',\n] as const;\n\nexport type LiteralValue = string | number | boolean | null;\n\ntype LiteralNode = { readonly type: 'Literal'; readonly value: LiteralValue };\n\ntype IdentifierNode = { readonly type: 'Identifier'; readonly name: string };\n\ntype MemberNode = {\n readonly type: 'Member';\n readonly object: ExprNode;\n readonly property: ExprNode;\n};\n\nexport type UnaryOperator = (typeof UNARY_OPERATORS)[number];\n\ntype UnaryExprNode = {\n readonly type: 'Unary';\n readonly operator: UnaryOperator;\n readonly argument: ExprNode;\n};\n\nexport type BinaryOperator = (typeof BINARY_OPERATORS)[number];\n\ntype BinaryExprNode = {\n readonly type: 'Binary';\n readonly operator: BinaryOperator;\n readonly left: ExprNode;\n readonly right: ExprNode;\n};\n\ntype ConditionalExprNode = {\n readonly type: 'Conditional';\n readonly test: ExprNode;\n readonly consequent: ExprNode;\n readonly alternate: ExprNode;\n};\n\nexport type ExprNode =\n LiteralNode | IdentifierNode | MemberNode | UnaryExprNode | BinaryExprNode | ConditionalExprNode;\n","import type { Expression } from 'oxc-parser';\nimport { parseSync } from 'oxc-parser';\n\nimport { failAt, failOnSyntaxError } from '../../errors';\nimport { BINARY_OPERATORS, type ExprNode, UNARY_OPERATORS } from './types';\n\n// Parses what's inside a `{{ }}` binding into an expression tree.\nexport function parseExpression(source: string): ExprNode {\n if (source.trim().length === 0) {\n failAt('The binding is empty', source, 0);\n }\n const { program, errors } = parseSync('binding.js', source, { preserveParens: false });\n failOnSyntaxError(errors, source);\n const statement = program.body[0];\n if (program.body.length !== 1 || statement?.type !== 'ExpressionStatement') {\n return failAt('A binding must be one expression', source, statement?.start ?? 0);\n }\n return toExprNode(statement.expression, source);\n}\n\nfunction toExprNode(node: Expression, source: string): ExprNode {\n switch (node.type) {\n case 'Literal':\n if (typeof node.value === 'bigint' || node.value instanceof RegExp) {\n return failUnsupported(node, source);\n }\n return { type: 'Literal', value: node.value };\n case 'Identifier':\n return { type: 'Identifier', name: node.name };\n case 'MemberExpression': {\n if (node.object.type === 'Super' || node.property.type === 'PrivateIdentifier') {\n return failUnsupported(node, source);\n }\n const object = toExprNode(node.object, source);\n if (node.computed) {\n return { type: 'Member', object, property: toExprNode(node.property, source) };\n }\n return { type: 'Member', object, property: { type: 'Literal', value: node.property.name } };\n }\n case 'UnaryExpression':\n if (!isOneOf(UNARY_OPERATORS, node.operator)) {\n return failUnsupported(node, source);\n }\n return {\n type: 'Unary',\n operator: node.operator,\n argument: toExprNode(node.argument, source),\n };\n case 'BinaryExpression':\n case 'LogicalExpression':\n if (node.left.type === 'PrivateIdentifier' || !isOneOf(BINARY_OPERATORS, node.operator)) {\n return failUnsupported(node, source);\n }\n return {\n type: 'Binary',\n operator: node.operator,\n left: toExprNode(node.left, source),\n right: toExprNode(node.right, source),\n };\n case 'ConditionalExpression':\n return {\n type: 'Conditional',\n test: toExprNode(node.test, source),\n consequent: toExprNode(node.consequent, source),\n alternate: toExprNode(node.alternate, source),\n };\n case 'CallExpression':\n case 'NewExpression':\n return failAt(\"Bindings can't call functions\", source, node.start);\n case 'AssignmentExpression':\n case 'UpdateExpression':\n return failAt(\"Bindings can't change values\", source, node.start);\n default:\n return failUnsupported(node, source);\n }\n}\n\nfunction failUnsupported(node: Expression, source: string): never {\n let detail = '';\n if ('operator' in node) {\n detail = ` \\`${node.operator}\\``;\n }\n return failAt(`Bindings can't use ${node.type}${detail}`, source, node.start);\n}\n\nfunction isOneOf<T extends string>(list: readonly T[], value: string): value is T {\n return (list as readonly string[]).includes(value);\n}\n"],"mappings":";;;AAIA,SAAS,aAAa,KAAiC;CACrD,IAAI,IAAI,SAAS,cACf,OAAO,IAAI;CAEb,IAAI,IAAI,SAAS,aAAa,OAAO,IAAI,UAAU,UACjD,OAAO,IAAI;CAEb,OAAO;AACT;AAEA,SAAgB,iBAAiB,MAA8B;CAC7D,OACE,KAAK,SAAS,oBACd,KAAK,SAAS,2BACd,KAAK,SAAS,uBAEd,OAAO,KAAK;CAEd,OAAO;AACT;AASA,SAAgB,iBAAiB,QAA4C;CAC3E,MAAM,aAA+B,CAAC;CACtC,KAAK,MAAM,YAAY,OAAO,YAAY;EACxC,IAAI,SAAS,SAAS,cAAc,SAAS,UAC3C;EAEF,MAAM,OAAO,aAAa,SAAS,GAAG;EACtC,IAAI,SAAS,MACX,WAAW,KAAK;GAAE;GAAM,OAAO,SAAS;GAAO,OAAO,SAAS;EAAM,CAAC;CAE1E;CACA,OAAO;AACT;AAGA,SAAgB,cAAc,WAAwD;CACpF,IAAI,UAAU,SAAS,0BACrB,OAAO,UAAU;CAEnB,OAAO;AACT;;;ACjDA,IAAa,mBAAb,cAAsC,YAAY;CAChD,OAAyB;AAC3B;AAEA,SAAgB,OAAO,QAAgB,QAAgB,QAAgB,MAAsB;CAC3F,MAAM,IAAI,iBAAiB,QAAQ,MAAM,WAAW,QAAQ,MAAM,CAAC;AACrE;AAEA,SAAgB,kBACd,QACA,QACA,MACM;CACN,MAAM,CAAC,SAAS;CAChB,IAAI,OACF,OAAO,MAAM,SAAS,QAAQ,MAAM,OAAO,EAAE,EAAE,SAAS,GAAG,IAAI;AAEnE;;;ACdA,SAAgB,YAAY,QAAgB,MAAuB;CACjE,MAAM,EAAE,SAAS,WAAW,UAAU,MAAM,QAAQ;EAAE,MAAM;EAAM,YAAY;CAAS,CAAC;CACxF,kBAAkB,QAAQ,QAAQ,IAAI;CACtC,OAAO;AACT;AAEA,SAAgB,cAAc,SAA0C;CACtE,KAAK,MAAM,aAAa,QAAQ,MAAM;EACpC,IAAI,UAAU,SAAS,4BACrB;EAEF,MAAM,EAAE,gBAAgB;EACxB,QAAQ,YAAY,MAApB;GACE,KAAK;GACL,KAAK;GACL,KAAK,0BACH;GACF,SACE,OAAO;EACX;CACF;AAEF;AAGA,SAAgB,WACd,SACA,QACA,MACA,QACkB;CAClB,MAAM,WAAW,cAAc,OAAO;CACtC,IAAI;CACJ,IAAI,UACF,UAAU,YAAY,iBAAiB,QAAQ,GAAG,MAAM;CAE1D,IAAI,CAAC,SACH,OAAO,OACL,GAAG,SAAS,IAAI,EAAE,yBAAyB,OAAO,cAClD,QACA,UAAU,SAAS,GACnB,IACF;CAEF,OAAO;AACT;AAEA,SAAS,YAAY,YAAwB,QAA8C;CACzF,IAAI,WAAW,SAAS,kBACtB;CAEF,IAAI,WAAW,OAAO,SAAS,gBAAgB,WAAW,OAAO,SAAS,QACxE;CAEF,MAAM,CAAC,WAAW,WAAW;CAC7B,IAAI,SAAS,SAAS,oBACpB;CAEF,OAAO;AACT;AAGA,SAAS,SAAS,MAAsB;CACtC,MAAM,gBAAgB,KAAK,IAAI,KAAK,YAAY,GAAG,GAAG,KAAK,YAAY,IAAI,CAAC;CAC5E,OAAO,KAAK,MAAM,gBAAgB,CAAC;AACrC;;;AC1DA,SAAgB,kBACd,QACA,OACA,OAAO,aACG;CACV,MAAM,UAAU,YAAY,QAAQ,IAAI;CACxC,MAAM,QAAQ,iBAAiB,OAAO;CACtC,MAAM,6BAAa,IAAI,IAAY;CACnC,iBAAiB,UAAU,eAAe;EACxC,WAAW,IAAI,WAAW,IAAc;CAC1C,CAAC;CACD,OAAO,MAAM,QAAQ,SAAS,WAAW,IAAI,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;AACxE;AAKA,SAAgB,iBAAiB,QAAgB,MAAc,OAAO,aAAuB;CAC3F,MAAM,UAAU,YAAY,QAAQ,IAAI;CACxC,IAAI,iBAAiB,OAAO,CAAC,CAAC,IAAI,IAAI,GACpC,OAAO,CAAC;CAEV,MAAM,OAAiB,CAAC;CACxB,iBAAiB,UAAU,YAAY,QAAQ,QAAQ;EACrD,IAAI,WAAW,SAAS,MACtB,KAAK,KAAK,WAAW,QAAQ,GAAG,CAAC;CAErC,CAAC;CACD,OAAO;AACT;AAGA,SAAS,WAAW,QAAqB,KAAqB;CAC5D,IAAI,QAAQ,SAAS,sBAAsB,QAAQ,YAAY,OAAO,aAAa,MACjF,OAAO;CAET,MAAM,WAAW,OAAO;CACxB,IAAI,UAAU,SAAS,cACrB,OAAO;CAET,OAAO,SAAS;AAClB;AAEA,SAAS,iBAAiB,SAA+B;CACvD,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,aAAa,QAAQ,MAAM;EACpC,MAAM,cAAc,cAAc,SAAS;EAC3C,QAAQ,aAAa,MAArB;GACE,KAAK;IACH,KAAK,MAAM,aAAa,YAAY,YAClC,MAAM,IAAI,UAAU,MAAM,IAAI;IAEhC;GACF,KAAK;IACH,KAAK,MAAM,cAAc,YAAY,cACnC,oBAAoB,WAAW,IAAI,KAAK;IAE1C;GACF,KAAK;GACL,KAAK,oBACH,IAAI,YAAY,IACd,MAAM,IAAI,YAAY,GAAG,IAAI;EAGnC;CACF;CACA,OAAO;AACT;AAEA,SAAS,oBAAoB,SAAkB,OAA0B;CACvE,IAAI,CAAC,OAAO,OAAO,GACjB;CAEF,QAAQ,QAAQ,MAAhB;EACE,KAAK;GACH,MAAM,IAAI,QAAQ,IAAc;GAChC;EACF,KAAK;GACH,KAAK,MAAM,YAAY,QAAQ,YAC7B,IAAI,SAAS,SAAS,eACpB,oBAAoB,SAAS,UAAU,KAAK;QAE5C,oBAAoB,SAAS,OAAO,KAAK;GAG7C;EACF,KAAK;GACH,KAAK,MAAM,WAAW,QAAQ,UAC5B,oBAAoB,SAAS,KAAK;GAEpC;EACF,KAAK;GACH,oBAAoB,QAAQ,UAAU,KAAK;GAC3C;EACF,KAAK,qBACH,oBAAoB,QAAQ,MAAM,KAAK;CAE3C;AACF;AAIA,SAAS,iBAAiB,SAAkB,OAA+B;CACzE,gBAAgB,SAA4B,MAAM,IAAI,KAAK;AAC7D;AAEA,SAAS,gBACP,MACA,QACA,KACA,OACM;CACN,IAAI,KAAK,SAAS,qBAChB;CAEF,IAAI,KAAK,SAAS,gBAAgB,YAAY,QAAQ,GAAG,GACvD,MAAM,MAAM,QAAQ,GAAG;CAEzB,KAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,IAAI,GAAG;EACpD,MAAM,WAAsB,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;EACjE,KAAK,MAAM,SAAS,UAClB,IAAI,OAAO,KAAK,GACd,gBAAgB,OAAO,MAAM,UAAU,KAAK;CAGlD;AACF;AAGA,SAAS,YAAY,QAAqB,KAAsB;CAC9D,QAAQ,QAAQ,MAAhB;EACE,KAAK,oBACH,OAAO,QAAQ,cAAc,OAAO,aAAa;EACnD,KAAK;EACL,KAAK;EACL,KAAK,sBACH,OAAO,QAAQ,SAAS,OAAO,aAAa;EAC9C,KAAK;EACL,KAAK;EACL,KAAK,qBACH,OAAO,QAAQ;EACjB,SACE,OAAO;CACX;AACF;AAEA,SAAS,OAAO,OAA+B;CAC7C,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,OAAO,OAAQ,MAA6B,SAAS;AACvD;;;AC3JA,MAAM,QAAQ,IAAI,IAAY,UAAU;AACxC,MAAM,gBAAgB;AAEtB,SAAgB,iBAAiB,QAAgB,OAAO,YAA6B;CACnF,MAAM,UAAU,YAAY,QAAQ,IAAI;CACxC,MAAM,WAAW,cAAc,OAAO;CACtC,IAAI,CAAC,UACH,OAAO,OAAO,uCAAuC,QAAQ,GAAG,IAAI;CAEtE,MAAM,aAAa,mBAAmB,SAAS,QAAQ;CACvD,OAAO;EACL,MAAM,QAAQ,UAAU;EACxB,YAAY,UAAU,cAAc,CAAC,CAAC;CACxC;AACF;AAEA,SAAgB,iBAAiB,QAAgB,OAAO,iBAA6B;CACnF,MAAM,UAAU,YAAY,QAAQ,IAAI;CACxC,MAAM,UAAU,WAAW,SAAS,QAAQ,MAAM,YAAY;CAC9D,IAAI,KAAoB;CACxB,IAAI,QAAyB;CAC7B,IAAI,YAAqC,CAAC;CAC1C,IAAI,UAAmC,CAAC;CACxC,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,EAAE,MAAM,OAAO,WAAW,iBAAiB,OAAO,GAC3D,QAAQ,MAAR;EACE,KAAK;EACL,KAAK,WACH;EACF,KAAK;GACH,KAAK,WAAW,OAAO,QAAQ,IAAI;GACnC;EACF,KAAK;GACH,QAAQ,kBAAkB,OAAO,QAAQ,IAAI;GAC7C;EACF,KAAK;GACH,MAAM,KAAK,GAAG,UAAU,OAAO,QAAQ,IAAI,CAAC;GAC5C;EACF,KAAK;GACH,YAAY,mBAAmB,SAAS,KAAK;GAC7C;EACF,KAAK;GACH,UAAU,mBAAmB,SAAS,KAAK;GAC3C;EACF,SACE,IAAI,WAAW,KAAK,GAClB,OAAO,KAAK,KAAK,6CAA6C,QAAQ,OAAO,IAAI;OAEjF,OACE,oBAAoB,KAAK,sFACzB,QACA,OACA,IACF;CAEN;CAEF,MAAM,gBAAgB,QAAQ,SAAS;CACvC,MAAM,cAAc,QAAQ,OAAO;CACnC,IAAI,iBAAiB,aAAa;EAChC,MAAM,QAAQ,cAAc,MAAM,SAAS,YAAY,SAAS,IAAI,CAAC;EACrE,IAAI,OACF,OAAO,KAAK,MAAM,sCAAsC,QAAQ,QAAQ,OAAO,IAAI;CAEvF;CACA,OAAO;EACL;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA,gBAAgB,UAAU,CAAC,GAAI,aAAa,CAAC,GAAI,GAAI,WAAW,CAAC,CAAE,CAAC;CACtE;AACF;AAGA,SAAS,kBAAkB,MAAkB,QAAgB,MAAwB;CACnF,MAAM,SAAS,iBAAiB,IAAI;CACpC,IAAI,OAAO,SAAS,oBAClB,OAAO,OAAO,iCAAiC,iBAAiB,QAAQ,KAAK,OAAO,IAAI;CAE1F,MAAM,aAAa,iBAAiB,MAAM;CAC1C,IAAI,WAAW,WAAW,OAAO,WAAW,QAC1C,OAAO,OAAO,iCAAiC,iBAAiB,QAAQ,OAAO,OAAO,IAAI;CAE5F,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,YAAY,YAAY;EACjC,IAAI,SAAS,SAAS,WACpB,OAAO,OACL,0BAA0B,SAAS,KAAK,+BACxC,QACA,SAAS,OACT,IACF;EAEF,MAAM,OAAO,iBAAiB,SAAS,KAAK;EAC5C,IAAI,KAAK,SAAS,mBAChB,OAAO,OACL,4CAA4C,iBAC5C,QACA,KAAK,OACL,IACF;EAEF,KAAK,MAAM,WAAW,KAAK,UAAU;GACnC,IAAI,CAAC,WAAW,QAAQ,SAAS,aAAa,OAAO,QAAQ,UAAU,UACrE,OAAO,OACL,qDAAqD,iBACrD,QACA,SAAS,SAAS,KAAK,OACvB,IACF;GAEF,MAAM,OAAO,QAAQ;GACrB,IAAI,CAAC,mBAAmB,IAAI,GAC1B,OAAO,OACL,IAAI,KAAK,yDACT,QACA,QAAQ,OACR,IACF;GAEF,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO,OAAO,IAAI,KAAK,gCAAgC,QAAQ,QAAQ,OAAO,IAAI;GAEpF,QAAQ,KAAK,IAAI;EACnB;EACA,IAAI,QAAQ,SAAS,oBACnB,OAAO,OACL,4BAA4B,mBAAmB,WAC/C,QACA,KAAK,OACL,IACF;CAEJ;CACA,OAAO;AACT;AAGA,SAAS,UAAU,MAAkB,QAAgB,MAAwB;CAC3E,IAAI,KAAK,SAAS,oBAChB,OAAO,CAAC;CAEV,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,QAAQ,iBAAiB,IAAI,GAAG;EACzC,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,GACtB,OACE,uBAAuB,KAAK,KAAK,oBAAoB,WAAW,KAAK,IAAI,KACzE,QACA,KAAK,OACL,IACF;EAEF,MAAM,KAAK,KAAK,IAAI;CACtB;CACA,OAAO;AACT;AAEA,SAAS,WAAW,MAA2B;CAC7C,OAAO,KAAK,SAAS,wBAAwB,KAAK,SAAS;AAC7D;AAIA,SAAS,mBAAmB,SAAkB,MAA2C;CACvF,MAAM,SAAS,cAAc,SAAS,IAAI;CAC1C,IAAI,CAAC,QACH,OAAO;CAET,MAAM,aAAa,iBAAiB,MAAM;CAC1C,IAAI,WAAW,WAAW,OAAO,WAAW,QAC1C,OAAO;CAET,OAAO;AACT;AAEA,SAAS,QAAQ,YAA+D;CAC9E,IAAI,eAAe,MACjB,OAAO;CAET,OAAO,WAAW,KAAK,aAAa,SAAS,IAAI;AACnD;AAEA,SAAS,UAAU,YAA+D;CAChF,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,YAAY,YACrB,QAAQ,SAAS,QAAQ,SAAS;CAEpC,OAAO;AACT;AAGA,SAAS,cAAc,SAAkB,MAA2C;CAClF,MAAM,SAAS,iBAAiB,IAAI;CACpC,IAAI,OAAO,SAAS,oBAClB,OAAO;CAET,IAAI,OAAO,SAAS,cAClB,OAAO;CAET,KAAK,MAAM,aAAa,QAAQ,MAAM;EACpC,MAAM,cAAc,cAAc,SAAS;EAC3C,IAAI,aAAa,SAAS,yBAAyB,YAAY,SAAS,SACtE;EAEF,KAAK,MAAM,cAAc,YAAY,cAAc;GACjD,IAAI,WAAW,GAAG,SAAS,gBAAgB,WAAW,GAAG,SAAS,OAAO,MACvE;GAEF,IAAI,CAAC,WAAW,MACd,OAAO;GAET,OAAO,cAAc,SAAS,WAAW,IAAI;EAC/C;CACF;CACA,OAAO;AACT;AAEA,SAAgB,WAAW,MAAkB,QAAgB,MAAsB;CACjF,MAAM,QAAQ,iBAAiB,IAAI;CACnC,IAAI,MAAM,SAAS,aAAa,OAAO,MAAM,UAAU,UACrD,OAAO,OACL,yDACA,QACA,KAAK,OACL,IACF;CAEF,IAAI,CAAC,SAAS,MAAM,KAAK,GACvB,OAAO,OACL,IAAI,MAAM,MAAM,sFAChB,QACA,KAAK,OACL,IACF;CAEF,OAAO,MAAM;AACf;;;AC7OA,SAAgB,eAAe,QAAgB,OAAO,UAAuB;CAE3E,MAAM,UAAU,WADA,YAAY,QAAQ,IACT,GAAS,QAAQ,MAAM,WAAW;CAC7D,MAAM,gBAAgB,iBAAiB,OAAO,CAAC,CAAC,MAAM,aAAa,SAAS,SAAS,OAAO;CAC5F,IAAI,CAAC,eACH,OAAO,OACL,6EACA,QACA,QAAQ,OACR,IACF;CAEF,MAAM,EAAE,OAAO,UAAU;CACzB,MAAM,WAAW,iBAAiB,KAAK;CACvC,IAAI,SAAS,SAAS,mBACpB,OAAO,OAAO,0CAA0C,QAAQ,OAAO,IAAI;CAE7E,IAAI,SAAS,SAAS,WAAW,GAC/B,OAAO,OAAO,mCAAmC,QAAQ,OAAO,IAAI;CAEtE,MAAM,QAAQ,SAAS,SAAS,KAAK,YAAY;EAC/C,IAAI,CAAC,WAAW,QAAQ,SAAS,iBAC/B,OAAO,OACL,kDACA,QACA,SAAS,SAAS,OAClB,IACF;EAEF,OAAO,WAAW,SAAS,QAAQ,IAAI;CACzC,CAAC;CAED,MAAM,WAAW,SAAS,SAAS,GAAG,EAAE;CACxC,OAAO;EAAE;EAAO,UAAU;GAAE,OAAO,SAAS;GAAO,KAAK,SAAS;EAAI;CAAE;AACzE;;;AC5CA,MAAa,kBAAkB;CAAC;CAAK;CAAK;CAAK;AAAQ;AAEvD,MAAa,mBAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;ACbA,SAAgB,gBAAgB,QAA0B;CACxD,IAAI,OAAO,KAAK,CAAC,CAAC,WAAW,GAC3B,OAAO,wBAAwB,QAAQ,CAAC;CAE1C,MAAM,EAAE,SAAS,WAAW,UAAU,cAAc,QAAQ,EAAE,gBAAgB,MAAM,CAAC;CACrF,kBAAkB,QAAQ,MAAM;CAChC,MAAM,YAAY,QAAQ,KAAK;CAC/B,IAAI,QAAQ,KAAK,WAAW,KAAK,WAAW,SAAS,uBACnD,OAAO,OAAO,oCAAoC,QAAQ,WAAW,SAAS,CAAC;CAEjF,OAAO,WAAW,UAAU,YAAY,MAAM;AAChD;AAEA,SAAS,WAAW,MAAkB,QAA0B;CAC9D,QAAQ,KAAK,MAAb;EACE,KAAK;GACH,IAAI,OAAO,KAAK,UAAU,YAAY,KAAK,iBAAiB,QAC1D,OAAO,gBAAgB,MAAM,MAAM;GAErC,OAAO;IAAE,MAAM;IAAW,OAAO,KAAK;GAAM;EAC9C,KAAK,cACH,OAAO;GAAE,MAAM;GAAc,MAAM,KAAK;EAAK;EAC/C,KAAK,oBAAoB;GACvB,IAAI,KAAK,OAAO,SAAS,WAAW,KAAK,SAAS,SAAS,qBACzD,OAAO,gBAAgB,MAAM,MAAM;GAErC,MAAM,SAAS,WAAW,KAAK,QAAQ,MAAM;GAC7C,IAAI,KAAK,UACP,OAAO;IAAE,MAAM;IAAU;IAAQ,UAAU,WAAW,KAAK,UAAU,MAAM;GAAE;GAE/E,OAAO;IAAE,MAAM;IAAU;IAAQ,UAAU;KAAE,MAAM;KAAW,OAAO,KAAK,SAAS;IAAK;GAAE;EAC5F;EACA,KAAK;GACH,IAAI,CAAC,QAAQ,iBAAiB,KAAK,QAAQ,GACzC,OAAO,gBAAgB,MAAM,MAAM;GAErC,OAAO;IACL,MAAM;IACN,UAAU,KAAK;IACf,UAAU,WAAW,KAAK,UAAU,MAAM;GAC5C;EACF,KAAK;EACL,KAAK;GACH,IAAI,KAAK,KAAK,SAAS,uBAAuB,CAAC,QAAQ,kBAAkB,KAAK,QAAQ,GACpF,OAAO,gBAAgB,MAAM,MAAM;GAErC,OAAO;IACL,MAAM;IACN,UAAU,KAAK;IACf,MAAM,WAAW,KAAK,MAAM,MAAM;IAClC,OAAO,WAAW,KAAK,OAAO,MAAM;GACtC;EACF,KAAK,yBACH,OAAO;GACL,MAAM;GACN,MAAM,WAAW,KAAK,MAAM,MAAM;GAClC,YAAY,WAAW,KAAK,YAAY,MAAM;GAC9C,WAAW,WAAW,KAAK,WAAW,MAAM;EAC9C;EACF,KAAK;EACL,KAAK,iBACH,OAAO,OAAO,iCAAiC,QAAQ,KAAK,KAAK;EACnE,KAAK;EACL,KAAK,oBACH,OAAO,OAAO,gCAAgC,QAAQ,KAAK,KAAK;EAClE,SACE,OAAO,gBAAgB,MAAM,MAAM;CACvC;AACF;AAEA,SAAS,gBAAgB,MAAkB,QAAuB;CAChE,IAAI,SAAS;CACb,IAAI,cAAc,MAChB,SAAS,MAAM,KAAK,SAAS;CAE/B,OAAO,OAAO,sBAAsB,KAAK,OAAO,UAAU,QAAQ,KAAK,KAAK;AAC9E;AAEA,SAAS,QAA0B,MAAoB,OAA2B;CAChF,OAAQ,KAA2B,SAAS,KAAK;AACnD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-script-parser",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "Dot page script parser: page state and logic -> intermediary representation",
5
5
  "type": "module",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "oxc-parser": "^0.151.0",
35
- "@monimesl/dot-core": "0.1.0-alpha.21"
35
+ "@monimesl/dot-core": "0.1.0-alpha.23"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"