@weborigami/language 0.3.4-jse.6 → 0.3.4-jse.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.3.4-jse.6",
3
+ "version": "0.3.4-jse.8",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -11,8 +11,8 @@
11
11
  "typescript": "5.8.2"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/async-tree": "0.3.4-jse.6",
15
- "@weborigami/types": "0.3.4-jse.6",
14
+ "@weborigami/async-tree": "0.3.4-jse.8",
15
+ "@weborigami/types": "0.3.4-jse.8",
16
16
  "watcher": "2.3.1",
17
17
  "yaml": "2.7.0"
18
18
  },
@@ -37,8 +37,8 @@ export default function optimize(code, options = {}) {
37
37
  const [op, ...args] = code;
38
38
  switch (op) {
39
39
  case markers.global:
40
- // Replace global op with the globals
41
- return annotate([globals, args[0]], code.location);
40
+ // Replace with the indicated global
41
+ return globals[args[0]];
42
42
 
43
43
  case markers.traverse:
44
44
  return resolvePath(code, globals, locals, cache);
@@ -140,7 +140,7 @@ function compoundReference(key, globals, locals, location) {
140
140
  const type = referenceType(head, globals, locals);
141
141
  let result;
142
142
  if (type === REFERENCE_GLOBAL) {
143
- result = globalReference(head, globals, location);
143
+ result = globalReference(head, globals);
144
144
  } else if (type === REFERENCE_LOCAL) {
145
145
  result = localReference(head, locals, location);
146
146
  } else {
@@ -177,9 +177,9 @@ function getLocalReferenceDepth(locals, key) {
177
177
  return depth;
178
178
  }
179
179
 
180
- function globalReference(key, globals, location) {
180
+ function globalReference(key, globals) {
181
181
  const normalized = trailingSlash.remove(key);
182
- return annotate([globals, normalized], location);
182
+ return globals[normalized];
183
183
  }
184
184
 
185
185
  function inlineLiteral(code) {
@@ -249,24 +249,29 @@ function reference(code, globals, locals) {
249
249
 
250
250
  // See if the whole key is a global or local variable
251
251
  let type = referenceType(key, globals, locals);
252
- let result;
253
252
  if (type === REFERENCE_GLOBAL) {
254
- result = globalReference(key, globals, location);
253
+ return {
254
+ type,
255
+ result: globalReference(key, globals),
256
+ };
255
257
  } else if (type === REFERENCE_LOCAL) {
256
- result = localReference(key, locals, location);
257
- } else {
258
- // Try key as a compound reference x.y.z
259
- const compound = compoundReference(key, globals, locals, location);
260
- result = compound?.result;
261
- type = compound?.type;
258
+ return {
259
+ type,
260
+ result: localReference(key, locals, location),
261
+ };
262
262
  }
263
263
 
264
- if (!result) {
265
- // If none of the above worked, it must be an external reference
266
- result = externalReference(key, locals, location);
264
+ // Try key as a compound reference x.y.z
265
+ const compound = compoundReference(key, globals, locals, location);
266
+ if (compound.type !== REFERENCE_EXTERNAL) {
267
+ return compound;
267
268
  }
268
269
 
269
- return { type, result };
270
+ // Not a compound reference, must be external
271
+ return {
272
+ type: REFERENCE_EXTERNAL,
273
+ result: externalReference(key, locals, location),
274
+ };
270
275
  }
271
276
 
272
277
  function referenceType(key, globals, locals) {
@@ -287,7 +292,13 @@ function resolvePath(code, globals, locals, cache) {
287
292
 
288
293
  let { type, result } = reference(head, globals, locals);
289
294
 
290
- result.push(...tail);
295
+ if (tail.length > 0) {
296
+ if (result instanceof Array) {
297
+ result.push(...tail);
298
+ } else {
299
+ result = annotate([result, ...tail], code.location);
300
+ }
301
+ }
291
302
 
292
303
  if (type === REFERENCE_EXTERNAL && cache !== null) {
293
304
  // Cache external path
@@ -164,10 +164,17 @@ comment "comment"
164
164
  / singleLineComment
165
165
 
166
166
  computedPropertyAccess
167
- = __ "[" expression:expression expectClosingBracket {
167
+ = computedPropertySpace "[" expression:expectExpression expectClosingBracket {
168
168
  return annotate([markers.property, expression], location());
169
169
  }
170
170
 
171
+ // A space before a computed property access. This is allowed when in not in
172
+ // shell mode, but not in shell mode. In shell mode `foo [bar]` should parse as
173
+ // a function call with a single argument of an array, not as a property access.
174
+ computedPropertySpace
175
+ = shellMode
176
+ / !shellMode __
177
+
171
178
  conditionalExpression
172
179
  = condition:logicalOrExpression tail:(__
173
180
  "?" __ @shorthandFunction __
@@ -254,7 +261,7 @@ expectDoubleQuote
254
261
  expectExpression
255
262
  = expression
256
263
  / .? {
257
- error("Expected an Origami expression");
264
+ error("Expected an expression");
258
265
  }
259
266
 
260
267
  expectFrontDelimiter
@@ -282,6 +289,12 @@ expectPipelineExpression
282
289
  error("Expected an expression");
283
290
  }
284
291
 
292
+ expectUnaryExpression
293
+ = unaryExpression
294
+ / .? {
295
+ error("Expected an expression");
296
+ }
297
+
285
298
  exponentiationExpression
286
299
  = left:unaryExpression right:(whitespace "**" whitespace @exponentiationExpression)? {
287
300
  return right ? annotate([ops.exponentiation, left, right], location()) : left;
@@ -319,7 +332,7 @@ frontMatterYaml "YAML front matter"
319
332
 
320
333
  // An expression in parentheses: `(foo)`
321
334
  group "parenthetical group"
322
- = "(" expression:expression expectClosingParenthesis {
335
+ = "(" expression:expectExpression expectClosingParenthesis {
323
336
  return annotate(expression, location());
324
337
  }
325
338
 
@@ -767,7 +780,12 @@ templateBodyText "template text"
767
780
 
768
781
  templateDocument "template document"
769
782
  = front:frontMatterExpression __ body:templateBody {
783
+ // TODO: Deprecate @template
770
784
  const macroName = text().includes("@template") ? "@template" : "_template";
785
+ if (macroName === "@template") {
786
+ // If the front matter is a macro, apply it to the body
787
+ console.warn("Warning: the @template() macro is deprecated. Use _template() instead.");
788
+ }
771
789
  return annotate(applyMacro(front, macroName, body), location());
772
790
  }
773
791
  / front:frontMatterYaml body:templateBody {
@@ -811,7 +829,7 @@ textChar
811
829
 
812
830
  // A unary prefix operator: `!x`
813
831
  unaryExpression
814
- = operator:unaryOperator __ expression:expectExpression {
832
+ = operator:unaryOperator __ expression:expectUnaryExpression {
815
833
  return makeUnaryOperation(operator, expression, location());
816
834
  }
817
835
  / callExpression
@@ -848,7 +866,8 @@ uriKey
848
866
  // A single character in a URI key
849
867
  uriKeyChar
850
868
  // Accept anything that doesn't end the URI key or path
851
- = [^/,\)\]\}\s]
869
+ // Note: Peggy doesn't support `/s` so we list space and tab explicitly.
870
+ = [^/,\)\]\} \t]
852
871
  / escapedChar
853
872
 
854
873
  // A slash-separated path of keys: `a/b/c`
@@ -871,8 +890,9 @@ unaryOperator
871
890
  / minus
872
891
 
873
892
  whitespace
874
- = inlineSpace
875
- / newLine
893
+ // JavaScript considers a large number of characters whitespace so we use the
894
+ // `/s` definition to avoid missing any.
895
+ = char:. &{ return /\s/.test(char); } { return char; }
876
896
  / comment
877
897
 
878
898
  whitespaceWithNewLine