@weborigami/language 0.6.9 → 0.6.10

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.
Files changed (39) hide show
  1. package/index.ts +19 -4
  2. package/main.js +5 -2
  3. package/package.json +2 -2
  4. package/src/compiler/compile.js +11 -3
  5. package/src/compiler/origami.pegjs +4 -2
  6. package/src/compiler/parse.js +77 -68
  7. package/src/compiler/parserHelpers.js +13 -13
  8. package/src/handlers/getPackedPath.js +17 -0
  9. package/src/handlers/jpeg_handler.js +5 -0
  10. package/src/handlers/js_handler.js +3 -3
  11. package/src/handlers/json_handler.js +3 -1
  12. package/src/handlers/tsv_handler.js +1 -1
  13. package/src/handlers/yaml_handler.js +1 -1
  14. package/src/project/jsGlobals.js +3 -3
  15. package/src/protocols/package.js +3 -3
  16. package/src/runtime/asyncStorage.js +7 -0
  17. package/src/runtime/codeFragment.js +4 -3
  18. package/src/runtime/errors.js +82 -129
  19. package/src/runtime/evaluate.js +8 -77
  20. package/src/runtime/execute.js +82 -0
  21. package/src/runtime/explainReferenceError.js +248 -0
  22. package/src/runtime/explainTraverseError.js +77 -0
  23. package/src/runtime/expressionFunction.js +8 -7
  24. package/src/runtime/expressionObject.js +4 -3
  25. package/src/runtime/handleExtension.js +22 -8
  26. package/src/runtime/internal.js +1 -1
  27. package/src/runtime/interop.js +15 -0
  28. package/src/runtime/ops.js +24 -19
  29. package/src/runtime/symbols.js +0 -1
  30. package/src/runtime/typos.js +22 -3
  31. package/test/compiler/compile.test.js +7 -103
  32. package/test/compiler/parse.test.js +38 -31
  33. package/test/project/fixtures/withPackageJson/subfolder/README.md +1 -0
  34. package/test/runtime/errors.test.js +296 -0
  35. package/test/runtime/evaluate.test.js +110 -34
  36. package/test/runtime/execute.test.js +41 -0
  37. package/test/runtime/expressionObject.test.js +3 -3
  38. package/test/runtime/ops.test.js +36 -35
  39. package/test/runtime/typos.test.js +2 -0
package/index.ts CHANGED
@@ -23,6 +23,15 @@ export type AnnotatedCode = (AnnotatedCode | AnnotatedCodeItem)[] & {
23
23
  */
24
24
  export type Code = Array<any>;
25
25
 
26
+ /**
27
+ * The context in which code is executed, including the code itself and the
28
+ * runtime state, used for reporting errors and warnings.
29
+ */
30
+ export type CodeContext = {
31
+ code: Code;
32
+ state: RuntimeState;
33
+ };
34
+
26
35
  export type CodeLocation = {
27
36
  end: Position;
28
37
  source: Source;
@@ -63,11 +72,17 @@ export type Position = {
63
72
  }
64
73
 
65
74
  export type RuntimeState = {
66
- /** The container (e.g., file system folder) that holds the code */
75
+ // Global variables that were used when compiling the code. These aren't used
76
+ // by the code itself, but help generate meaningful error messages.
77
+ globals?: any;
78
+
79
+ // The object to which this code is attached
80
+ object?: any;
81
+
82
+ // The container (e.g., file system folder) that holds the code
67
83
  parent?: SyncOrAsyncMap | null;
68
- /** The object to which this code is attached */
69
- object?: SyncOrAsyncMap | null;
70
- /** The current stack of function parameter assignments */
84
+
85
+ // The current stack of function parameter assignments
71
86
  stack?: Array<Record<string, any>>;
72
87
  }
73
88
 
package/main.js CHANGED
@@ -12,9 +12,12 @@ export { default as projectGlobals } from "./src/project/projectGlobals.js";
12
12
  export { default as projectRoot } from "./src/project/projectRoot.js";
13
13
  export { default as projectRootFromPath } from "./src/project/projectRootFromPath.js";
14
14
  export * as Protocols from "./src/protocols/protocols.js";
15
- export { formatError, highlightError } from "./src/runtime/errors.js";
16
- export { default as evaluate } from "./src/runtime/evaluate.js";
15
+ export { formatError, highlightError, lineInfo } from "./src/runtime/errors.js";
17
16
  export { default as EventTargetMixin } from "./src/runtime/EventTargetMixin.js";
17
+ export {
18
+ default as evaluate,
19
+ default as execute,
20
+ } from "./src/runtime/execute.js";
18
21
  export * as expressionFunction from "./src/runtime/expressionFunction.js";
19
22
  export { default as expressionObject } from "./src/runtime/expressionObject.js";
20
23
  export * from "./src/runtime/handleExtension.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.6.9",
3
+ "version": "0.6.10",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -11,7 +11,7 @@
11
11
  "typescript": "5.9.3"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/async-tree": "0.6.9",
14
+ "@weborigami/async-tree": "0.6.10",
15
15
  "exif-parser": "0.1.12",
16
16
  "watcher": "2.3.1",
17
17
  "yaml": "2.8.1"
@@ -2,10 +2,18 @@ import { createExpressionFunction } from "../runtime/expressionFunction.js";
2
2
  import optimize from "./optimize.js";
3
3
  import { parse } from "./parse.js";
4
4
 
5
+ /**
6
+ * Compile the given Origami source code into a JavaScript function.
7
+ *
8
+ * @typedef {import("../../index.ts").Source} Source
9
+ * @param {Source|string} source
10
+ * @param {any} options
11
+ */
5
12
  function compile(source, options) {
6
- const { front, parent, startRule } = options;
7
- const mode = options.mode ?? "program";
13
+ const { front, startRule } = options;
8
14
  const globals = options.globals ?? {};
15
+ const mode = options.mode ?? "program";
16
+ const parent = options.parent ?? null;
9
17
 
10
18
  if (typeof source === "string") {
11
19
  source = { text: source };
@@ -28,7 +36,7 @@ function compile(source, options) {
28
36
  });
29
37
 
30
38
  // Create a function that executes the optimized code.
31
- const fn = createExpressionFunction(optimized, parent);
39
+ const fn = createExpressionFunction(optimized, { globals, parent });
32
40
  return fn;
33
41
  }
34
42
 
@@ -836,8 +836,10 @@ regexLiteral
836
836
  }
837
837
 
838
838
  regexLiteralChar
839
- = [^/\n\r] // No unescaped slashes or newlines
840
- / escapedChar
839
+ = char:escapedChar {
840
+ return `\\${char}`;
841
+ }
842
+ / [^/\n\r] // No unescaped slashes or newlines
841
843
 
842
844
  relationalExpression
843
845
  // We disallow a newline before the relational operator to support a newline
@@ -968,15 +968,18 @@ function peg$parse(input, options) {
968
968
  const regex = new RegExp(chars.join(""), flags);
969
969
  return annotate([ops.literal, regex], location());
970
970
  }
971
- function peg$f109(head, tail) {
971
+ function peg$f109(char) {
972
+ return `\\${char}`;
973
+ }
974
+ function peg$f110(head, tail) {
972
975
  return tail.reduce(makeBinaryOperation, head);
973
976
  }
974
- function peg$f110() { return null; }
975
- function peg$f111() { return options.mode === "shell" }
976
- function peg$f112(head, tail) {
977
+ function peg$f111() { return null; }
978
+ function peg$f112() { return options.mode === "shell" }
979
+ function peg$f113(head, tail) {
977
980
  return tail.reduce(makeBinaryOperation, head);
978
981
  }
979
- function peg$f113(body) {
982
+ function peg$f114(body) {
980
983
  if (options.mode === "program") {
981
984
  throw new Error("Parse error: shorthand function syntax isn't allowed in Origami programs. Use arrow syntax instead.");
982
985
  }
@@ -984,35 +987,35 @@ function peg$parse(input, options) {
984
987
  const parameters = annotate([underscore], location());
985
988
  return makeLambda(parameters, body, location());
986
989
  }
987
- function peg$f114() { return null; }
988
- function peg$f115(chars) {
990
+ function peg$f115() { return null; }
991
+ function peg$f116(chars) {
989
992
  return annotate([ops.literal, chars.join("")], location());
990
993
  }
991
- function peg$f116() {
992
- return annotate([ops.literal, "/"], location());
993
- }
994
994
  function peg$f117() {
995
995
  return annotate([ops.literal, "/"], location());
996
996
  }
997
997
  function peg$f118() {
998
+ return annotate([ops.literal, "/"], location());
999
+ }
1000
+ function peg$f119() {
998
1001
  return true;
999
1002
  }
1000
- function peg$f119(value) {
1003
+ function peg$f120(value) {
1001
1004
  return annotate([markers.spread, value], location());
1002
1005
  }
1003
- function peg$f120(head, tail) {
1006
+ function peg$f121(head, tail) {
1004
1007
  return makeTemplate(ops.templateIndent, head, tail, location());
1005
1008
  }
1006
- function peg$f121(chars) {
1009
+ function peg$f122(chars) {
1007
1010
  return annotate([ops.literal, chars.join("")], location());
1008
1011
  }
1009
- function peg$f122(front, body) {
1012
+ function peg$f123(front, body) {
1010
1013
  return annotate(applyMacro(front, "_template", body), location());
1011
1014
  }
1012
- function peg$f123(front, body) {
1015
+ function peg$f124(front, body) {
1013
1016
  return makeDocument(front, body, location());
1014
1017
  }
1015
- function peg$f124(body) {
1018
+ function peg$f125(body) {
1016
1019
  if (options.front) {
1017
1020
  return makeDocument(options.front, body, location());
1018
1021
  }
@@ -1020,43 +1023,43 @@ function peg$parse(input, options) {
1020
1023
  const parameters = annotate([underscore], location());
1021
1024
  return makeLambda(parameters, body, location());
1022
1025
  }
1023
- function peg$f125(head, tail) {
1026
+ function peg$f126(head, tail) {
1024
1027
  return makeTemplate(ops.templateText, head, tail, location());
1025
1028
  }
1026
- function peg$f126(chars) {
1029
+ function peg$f127(chars) {
1027
1030
  return annotate([ops.literal, chars.join("")], location());
1028
1031
  }
1029
- function peg$f127(expression) {
1032
+ function peg$f128(expression) {
1030
1033
  return annotate(expression, location());
1031
1034
  }
1032
- function peg$f128(operator, expression) {
1035
+ function peg$f129(operator, expression) {
1033
1036
  return makeUnaryOperation(operator, expression, location());
1034
1037
  }
1035
- function peg$f129(scheme, host, path) {
1038
+ function peg$f130(scheme, host, path) {
1036
1039
  const rest = path ? path[1] : [];
1037
1040
  const keys = annotate([host, ...rest], location());
1038
1041
  return makeCall(scheme, keys, location());
1039
1042
  }
1040
- function peg$f130(scheme, keys) {
1043
+ function peg$f131(scheme, keys) {
1041
1044
  return makeCall(scheme, keys, location());
1042
1045
  }
1043
- function peg$f131(chars) {
1046
+ function peg$f132(chars) {
1044
1047
  return annotate([ops.literal, text()], location());
1045
1048
  }
1046
- function peg$f132() {
1049
+ function peg$f133() {
1047
1050
  // A single slash is a path key
1048
1051
  return annotate([ops.literal, ""], location());
1049
1052
  }
1050
- function peg$f133(char) { return /\s/.test(char); }
1051
- function peg$f134(char) { return char; }
1052
- function peg$f135(keys) {
1053
+ function peg$f134(char) { return /\s/.test(char); }
1054
+ function peg$f135(char) { return char; }
1055
+ function peg$f136(keys) {
1053
1056
  return annotate(keys, location());
1054
1057
  }
1055
- function peg$f136() {
1058
+ function peg$f137() {
1056
1059
  return annotate([markers.global, text()], location());
1057
1060
  }
1058
- function peg$f137(char) { return /\s/.test(char); }
1059
- function peg$f138(char) { return char; }
1061
+ function peg$f138(char) { return /\s/.test(char); }
1062
+ function peg$f139(char) { return char; }
1060
1063
  let peg$currPos = options.peg$currPos | 0;
1061
1064
  let peg$savedPos = peg$currPos;
1062
1065
  const peg$posDetailsCache = [{ line: 1, column: 1 }];
@@ -6276,17 +6279,23 @@ function peg$parse(input, options) {
6276
6279
  }
6277
6280
 
6278
6281
  function peg$parseregexLiteralChar() {
6279
- let s0;
6282
+ let s0, s1;
6280
6283
 
6281
- s0 = input.charAt(peg$currPos);
6282
- if (peg$r17.test(s0)) {
6283
- peg$currPos++;
6284
- } else {
6285
- s0 = peg$FAILED;
6286
- if (peg$silentFails === 0) { peg$fail(peg$e99); }
6284
+ s0 = peg$currPos;
6285
+ s1 = peg$parseescapedChar();
6286
+ if (s1 !== peg$FAILED) {
6287
+ peg$savedPos = s0;
6288
+ s1 = peg$f109(s1);
6287
6289
  }
6290
+ s0 = s1;
6288
6291
  if (s0 === peg$FAILED) {
6289
- s0 = peg$parseescapedChar();
6292
+ s0 = input.charAt(peg$currPos);
6293
+ if (peg$r17.test(s0)) {
6294
+ peg$currPos++;
6295
+ } else {
6296
+ s0 = peg$FAILED;
6297
+ if (peg$silentFails === 0) { peg$fail(peg$e99); }
6298
+ }
6290
6299
  }
6291
6300
 
6292
6301
  return s0;
@@ -6345,7 +6354,7 @@ function peg$parse(input, options) {
6345
6354
  }
6346
6355
  }
6347
6356
  peg$savedPos = s0;
6348
- s0 = peg$f109(s1, s2);
6357
+ s0 = peg$f110(s1, s2);
6349
6358
  } else {
6350
6359
  peg$currPos = s0;
6351
6360
  s0 = peg$FAILED;
@@ -6536,7 +6545,7 @@ function peg$parse(input, options) {
6536
6545
  }
6537
6546
  }
6538
6547
  peg$savedPos = s0;
6539
- s0 = peg$f110();
6548
+ s0 = peg$f111();
6540
6549
  } else {
6541
6550
  peg$currPos = s0;
6542
6551
  s0 = peg$FAILED;
@@ -6549,7 +6558,7 @@ function peg$parse(input, options) {
6549
6558
  let s0;
6550
6559
 
6551
6560
  peg$savedPos = peg$currPos;
6552
- s0 = peg$f111();
6561
+ s0 = peg$f112();
6553
6562
  if (s0) {
6554
6563
  s0 = undefined;
6555
6564
  } else {
@@ -6602,7 +6611,7 @@ function peg$parse(input, options) {
6602
6611
  }
6603
6612
  }
6604
6613
  peg$savedPos = s0;
6605
- s0 = peg$f112(s1, s2);
6614
+ s0 = peg$f113(s1, s2);
6606
6615
  } else {
6607
6616
  peg$currPos = s0;
6608
6617
  s0 = peg$FAILED;
@@ -6682,7 +6691,7 @@ function peg$parse(input, options) {
6682
6691
  s5 = peg$parseimplicitParenthesesCallExpression();
6683
6692
  if (s5 !== peg$FAILED) {
6684
6693
  peg$savedPos = s0;
6685
- s0 = peg$f113(s5);
6694
+ s0 = peg$f114(s5);
6686
6695
  } else {
6687
6696
  peg$currPos = s0;
6688
6697
  s0 = peg$FAILED;
@@ -6765,7 +6774,7 @@ function peg$parse(input, options) {
6765
6774
  }
6766
6775
  }
6767
6776
  peg$savedPos = s0;
6768
- s0 = peg$f114();
6777
+ s0 = peg$f115();
6769
6778
  } else {
6770
6779
  peg$currPos = s0;
6771
6780
  s0 = peg$FAILED;
@@ -6796,7 +6805,7 @@ function peg$parse(input, options) {
6796
6805
  s3 = peg$parseexpectSingleQuote();
6797
6806
  if (s3 !== peg$FAILED) {
6798
6807
  peg$savedPos = s0;
6799
- s0 = peg$f115(s2);
6808
+ s0 = peg$f116(s2);
6800
6809
  } else {
6801
6810
  peg$currPos = s0;
6802
6811
  s0 = peg$FAILED;
@@ -6860,7 +6869,7 @@ function peg$parse(input, options) {
6860
6869
  s1 = peg$parseslashFollows();
6861
6870
  if (s1 !== peg$FAILED) {
6862
6871
  peg$savedPos = s0;
6863
- s1 = peg$f116();
6872
+ s1 = peg$f117();
6864
6873
  }
6865
6874
  s0 = s1;
6866
6875
 
@@ -6895,7 +6904,7 @@ function peg$parse(input, options) {
6895
6904
  }
6896
6905
  if (s1 !== peg$FAILED) {
6897
6906
  peg$savedPos = s0;
6898
- s1 = peg$f117();
6907
+ s1 = peg$f118();
6899
6908
  }
6900
6909
  s0 = s1;
6901
6910
 
@@ -6924,7 +6933,7 @@ function peg$parse(input, options) {
6924
6933
  }
6925
6934
  if (s1 !== peg$FAILED) {
6926
6935
  peg$savedPos = s0;
6927
- s1 = peg$f118();
6936
+ s1 = peg$f119();
6928
6937
  }
6929
6938
  s0 = s1;
6930
6939
 
@@ -6941,7 +6950,7 @@ function peg$parse(input, options) {
6941
6950
  s3 = peg$parseexpectPipelineExpression();
6942
6951
  if (s3 !== peg$FAILED) {
6943
6952
  peg$savedPos = s0;
6944
- s0 = peg$f119(s3);
6953
+ s0 = peg$f120(s3);
6945
6954
  } else {
6946
6955
  peg$currPos = s0;
6947
6956
  s0 = peg$FAILED;
@@ -7018,7 +7027,7 @@ function peg$parse(input, options) {
7018
7027
  }
7019
7028
  }
7020
7029
  peg$savedPos = s0;
7021
- s0 = peg$f120(s1, s2);
7030
+ s0 = peg$f121(s1, s2);
7022
7031
  peg$silentFails--;
7023
7032
 
7024
7033
  return s0;
@@ -7072,7 +7081,7 @@ function peg$parse(input, options) {
7072
7081
  s2 = peg$parsetemplateBodyChar();
7073
7082
  }
7074
7083
  peg$savedPos = s0;
7075
- s1 = peg$f121(s1);
7084
+ s1 = peg$f122(s1);
7076
7085
  s0 = s1;
7077
7086
  peg$silentFails--;
7078
7087
 
@@ -7089,7 +7098,7 @@ function peg$parse(input, options) {
7089
7098
  s2 = peg$parse__();
7090
7099
  s3 = peg$parsetemplateBody();
7091
7100
  peg$savedPos = s0;
7092
- s0 = peg$f122(s1, s3);
7101
+ s0 = peg$f123(s1, s3);
7093
7102
  } else {
7094
7103
  peg$currPos = s0;
7095
7104
  s0 = peg$FAILED;
@@ -7100,7 +7109,7 @@ function peg$parse(input, options) {
7100
7109
  if (s1 !== peg$FAILED) {
7101
7110
  s2 = peg$parsetemplateBody();
7102
7111
  peg$savedPos = s0;
7103
- s0 = peg$f123(s1, s2);
7112
+ s0 = peg$f124(s1, s2);
7104
7113
  } else {
7105
7114
  peg$currPos = s0;
7106
7115
  s0 = peg$FAILED;
@@ -7109,7 +7118,7 @@ function peg$parse(input, options) {
7109
7118
  s0 = peg$currPos;
7110
7119
  s1 = peg$parsetemplateBody();
7111
7120
  peg$savedPos = s0;
7112
- s1 = peg$f124(s1);
7121
+ s1 = peg$f125(s1);
7113
7122
  s0 = s1;
7114
7123
  }
7115
7124
  }
@@ -7163,7 +7172,7 @@ function peg$parse(input, options) {
7163
7172
  s4 = peg$parseexpectBacktick();
7164
7173
  if (s4 !== peg$FAILED) {
7165
7174
  peg$savedPos = s0;
7166
- s0 = peg$f125(s2, s3);
7175
+ s0 = peg$f126(s2, s3);
7167
7176
  } else {
7168
7177
  peg$currPos = s0;
7169
7178
  s0 = peg$FAILED;
@@ -7237,7 +7246,7 @@ function peg$parse(input, options) {
7237
7246
  s2 = peg$parsetemplateLiteralChar();
7238
7247
  }
7239
7248
  peg$savedPos = s0;
7240
- s1 = peg$f126(s1);
7249
+ s1 = peg$f127(s1);
7241
7250
  s0 = s1;
7242
7251
 
7243
7252
  return s0;
@@ -7267,7 +7276,7 @@ function peg$parse(input, options) {
7267
7276
  }
7268
7277
  if (s3 !== peg$FAILED) {
7269
7278
  peg$savedPos = s0;
7270
- s0 = peg$f127(s2);
7279
+ s0 = peg$f128(s2);
7271
7280
  } else {
7272
7281
  peg$currPos = s0;
7273
7282
  s0 = peg$FAILED;
@@ -7316,7 +7325,7 @@ function peg$parse(input, options) {
7316
7325
  s3 = peg$parseexpectUnaryExpression();
7317
7326
  if (s3 !== peg$FAILED) {
7318
7327
  peg$savedPos = s0;
7319
- s0 = peg$f128(s1, s3);
7328
+ s0 = peg$f129(s1, s3);
7320
7329
  } else {
7321
7330
  peg$currPos = s0;
7322
7331
  s0 = peg$FAILED;
@@ -7520,7 +7529,7 @@ function peg$parse(input, options) {
7520
7529
  s4 = null;
7521
7530
  }
7522
7531
  peg$savedPos = s0;
7523
- s0 = peg$f129(s1, s3, s4);
7532
+ s0 = peg$f130(s1, s3, s4);
7524
7533
  } else {
7525
7534
  peg$currPos = s0;
7526
7535
  s0 = peg$FAILED;
@@ -7540,7 +7549,7 @@ function peg$parse(input, options) {
7540
7549
  s2 = peg$parsepathKeys();
7541
7550
  if (s2 !== peg$FAILED) {
7542
7551
  peg$savedPos = s0;
7543
- s0 = peg$f130(s1, s2);
7552
+ s0 = peg$f131(s1, s2);
7544
7553
  } else {
7545
7554
  peg$currPos = s0;
7546
7555
  s0 = peg$FAILED;
@@ -7594,7 +7603,7 @@ function peg$parse(input, options) {
7594
7603
  s2 = null;
7595
7604
  }
7596
7605
  peg$savedPos = s0;
7597
- s0 = peg$f131(s1);
7606
+ s0 = peg$f132(s1);
7598
7607
  } else {
7599
7608
  peg$currPos = s0;
7600
7609
  s0 = peg$FAILED;
@@ -7610,7 +7619,7 @@ function peg$parse(input, options) {
7610
7619
  }
7611
7620
  if (s1 !== peg$FAILED) {
7612
7621
  peg$savedPos = s0;
7613
- s1 = peg$f132();
7622
+ s1 = peg$f133();
7614
7623
  }
7615
7624
  s0 = s1;
7616
7625
  }
@@ -7633,7 +7642,7 @@ function peg$parse(input, options) {
7633
7642
  s2 = peg$currPos;
7634
7643
  peg$silentFails++;
7635
7644
  peg$savedPos = peg$currPos;
7636
- s3 = peg$f133(s1);
7645
+ s3 = peg$f134(s1);
7637
7646
  if (s3) {
7638
7647
  s3 = undefined;
7639
7648
  } else {
@@ -7648,7 +7657,7 @@ function peg$parse(input, options) {
7648
7657
  }
7649
7658
  if (s2 !== peg$FAILED) {
7650
7659
  peg$savedPos = s0;
7651
- s0 = peg$f134(s1);
7660
+ s0 = peg$f135(s1);
7652
7661
  } else {
7653
7662
  peg$currPos = s0;
7654
7663
  s0 = peg$FAILED;
@@ -7684,7 +7693,7 @@ function peg$parse(input, options) {
7684
7693
  }
7685
7694
  if (s1 !== peg$FAILED) {
7686
7695
  peg$savedPos = s0;
7687
- s1 = peg$f135(s1);
7696
+ s1 = peg$f136(s1);
7688
7697
  }
7689
7698
  s0 = s1;
7690
7699
  peg$silentFails--;
@@ -7735,7 +7744,7 @@ function peg$parse(input, options) {
7735
7744
  }
7736
7745
  if (s3 !== peg$FAILED) {
7737
7746
  peg$savedPos = s0;
7738
- s0 = peg$f136();
7747
+ s0 = peg$f137();
7739
7748
  } else {
7740
7749
  peg$currPos = s0;
7741
7750
  s0 = peg$FAILED;
@@ -7784,7 +7793,7 @@ function peg$parse(input, options) {
7784
7793
  }
7785
7794
  if (s1 !== peg$FAILED) {
7786
7795
  peg$savedPos = peg$currPos;
7787
- s2 = peg$f137(s1);
7796
+ s2 = peg$f138(s1);
7788
7797
  if (s2) {
7789
7798
  s2 = undefined;
7790
7799
  } else {
@@ -7792,7 +7801,7 @@ function peg$parse(input, options) {
7792
7801
  }
7793
7802
  if (s2 !== peg$FAILED) {
7794
7803
  peg$savedPos = s0;
7795
- s0 = peg$f138(s1);
7804
+ s0 = peg$f139(s1);
7796
7805
  } else {
7797
7806
  peg$currPos = s0;
7798
7807
  s0 = peg$FAILED;
@@ -265,7 +265,7 @@ export function makeDocument(front, body, location) {
265
265
  // In order for template expressions to see the front matter properties,
266
266
  // we translate the top-level front properties to object entries.
267
267
  const entries = Object.entries(front).map(([key, value]) =>
268
- annotate([key, annotate([ops.literal, value], location)], location)
268
+ annotate([key, annotate([ops.literal, value], location)], location),
269
269
  );
270
270
 
271
271
  // Add an entry for the body
@@ -351,7 +351,7 @@ function makeMerge(spreads, location) {
351
351
  });
352
352
  const indirectObject = annotate(
353
353
  [ops.object, ...indirectEntries],
354
- location
354
+ location,
355
355
  );
356
356
  resultEntries.push(indirectObject);
357
357
  } else {
@@ -458,11 +458,11 @@ function makeOptionalCall(target, chain, location) {
458
458
  // Create a reference to the __optional__ parameter
459
459
  const optionalReference = annotate(
460
460
  [markers.reference, optionalKey],
461
- location
461
+ location,
462
462
  );
463
463
  const optionalTraverse = annotate(
464
464
  [markers.traverse, optionalReference],
465
- location
465
+ location,
466
466
  );
467
467
 
468
468
  // Create the call body to be made if the target is not null/undefined
@@ -528,7 +528,7 @@ function makeParamInitializer(parameter, reference, state) {
528
528
  // Literal default value can be inlined
529
529
  const defaultReference = annotate(
530
530
  [ops.defaultValue, reference, defaultValue],
531
- parameter.location
531
+ parameter.location,
532
532
  );
533
533
  return makeParam(baseParam, defaultReference, state);
534
534
  }
@@ -538,18 +538,18 @@ function makeParamInitializer(parameter, reference, state) {
538
538
  const deferred = makeDeferredArguments([defaultValue])[0];
539
539
  const defaultReference = annotate(
540
540
  [ops.defaultValue, reference, deferred],
541
- parameter.location
541
+ parameter.location,
542
542
  );
543
543
  const tempVariableName = `__temp${state.tempVariableCount++}__`;
544
544
  const tempBinding = annotate(
545
545
  [tempVariableName, defaultReference],
546
- parameter.location
546
+ parameter.location,
547
547
  );
548
548
 
549
549
  const selfReference = annotate([ops.inherited, 0], parameter.location);
550
550
  const tempReference = annotate(
551
551
  [selfReference, tempVariableName],
552
- parameter.location
552
+ parameter.location,
553
553
  );
554
554
 
555
555
  const paramBindings = makeParam(baseParam, tempReference, state);
@@ -573,7 +573,7 @@ function makeParamObject(entries, reference, state) {
573
573
  const annotatedKeys = annotate([ops.array, ...keys], entry.location);
574
574
  const objectRest = annotate(
575
575
  [ops.objectRest, reference, annotatedKeys],
576
- entry.location
576
+ entry.location,
577
577
  );
578
578
  return makeParam(entry[1], objectRest, state);
579
579
  }
@@ -596,7 +596,7 @@ function makeParamObject(entries, reference, state) {
596
596
  export function makePath(keys) {
597
597
  // Remove empty segments
598
598
  const args = keys.filter(
599
- (key, index) => index === 0 || (key[1] !== "" && key[1] !== "/")
599
+ (key, index) => index === 0 || (key[1] !== "" && key[1] !== "/"),
600
600
  );
601
601
 
602
602
  // Upgrade head to a reference
@@ -627,7 +627,7 @@ export function makePipeline(arg, fn, location) {
627
627
 
628
628
  function makePossibleSpreadCall(target, args, location) {
629
629
  const hasSpread = args.some(
630
- (arg) => Array.isArray(arg) && arg[0] === markers.spread
630
+ (arg) => Array.isArray(arg) && arg[0] === markers.spread,
631
631
  );
632
632
  if (!hasSpread) {
633
633
  // No spreads, simple call
@@ -651,7 +651,7 @@ function makePossibleSpreadCall(target, args, location) {
651
651
  * Make a tagged template call
652
652
  *
653
653
  * Because the tagged template function may not be an Origami function, we wrap
654
- * each argument in a ops.concat call to convert it to a string.
654
+ * each argument in a ops.deepText call to convert it to a string.
655
655
  *
656
656
  * @param {AnnotatedCode} fn
657
657
  * @param {AnnotatedCode} strings
@@ -660,7 +660,7 @@ function makePossibleSpreadCall(target, args, location) {
660
660
  function makeTaggedTemplateCall(fn, strings, ...values) {
661
661
  const args = values.map((value) =>
662
662
  // @ts-ignore
663
- annotate([ops.concat, value], value.location)
663
+ annotate([ops.deepText, value], value.location),
664
664
  );
665
665
  return annotate([fn, strings, ...args], strings.location);
666
666
  }
@@ -0,0 +1,17 @@
1
+ import { getParent } from "@weborigami/async-tree";
2
+ import path from "node:path";
3
+
4
+ /**
5
+ * Return the path or file name for a packed value based on the options passed
6
+ * to the unpack function.
7
+ *
8
+ * @param {import("@weborigami/async-tree").Packed} packed
9
+ * @param {any} options
10
+ */
11
+ export default function getPackedPath(packed, options = {}) {
12
+ const { key } = options;
13
+ /** @type {any} */
14
+ const parent = getParent(packed, options);
15
+ const filePath = parent?.path ? path.join(parent.path, key) : key;
16
+ return filePath;
17
+ }
@@ -21,6 +21,11 @@ export default {
21
21
  // Downgrade to old Node Buffer for exif-parser.
22
22
  packed = Buffer.from(packed);
23
23
  }
24
+
25
+ if (!(packed instanceof Buffer)) {
26
+ throw new TypeError("JPEG handler can only unpack binary data.");
27
+ }
28
+
24
29
  const parser = exifParser.create(packed);
25
30
  parser.enableTagNames(true);
26
31
  parser.enableSimpleValues(true);