@weborigami/language 0.0.38 → 0.0.39

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/index.ts CHANGED
@@ -14,7 +14,10 @@ export type Constructor<T> = new (...args: any[]) => T;
14
14
  */
15
15
  export type FileUnpackFunction = (
16
16
  input: StringLike,
17
- options?: { key?: any, parent?: AsyncTree | null }
17
+ options?: {
18
+ key?: any,
19
+ parent?: AsyncTree | null
20
+ }
18
21
  ) => any;
19
22
 
20
23
  /**
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
7
7
  "types": "./index.ts",
8
8
  "devDependencies": {
9
- "@types/node": "20.8.10",
10
- "typescript": "5.2.2"
9
+ "@types/node": "20.11.3",
10
+ "typescript": "5.3.3"
11
11
  },
12
12
  "dependencies": {
13
13
  "@weborigami/types": "*",
@@ -205,9 +205,10 @@ protocol
205
205
  reservedProtocol
206
206
  = "https" { return ops.https; }
207
207
  / "http" { return ops.http; }
208
+ / "package" { return [ops.scope, "@package"] } // Alias
208
209
  / "treehttps" { return ops.treeHttps; }
209
210
  / "treehttp" { return ops.treeHttp; }
210
- / "tree" { return ops.treeHttps; } // Shorthand alias
211
+ / "tree" { return ops.treeHttps; } // Alias
211
212
 
212
213
  scopeReference
213
214
  = key:identifier { return [ops.scope, key]; }
@@ -204,13 +204,14 @@ function peg$parse(input, options) {
204
204
  var peg$c16 = ",";
205
205
  var peg$c17 = "https";
206
206
  var peg$c18 = "http";
207
- var peg$c19 = "treehttps";
208
- var peg$c20 = "treehttp";
209
- var peg$c21 = "tree";
210
- var peg$c22 = "'";
211
- var peg$c23 = "{{";
212
- var peg$c24 = "`";
213
- var peg$c25 = "}}";
207
+ var peg$c19 = "package";
208
+ var peg$c20 = "treehttps";
209
+ var peg$c21 = "treehttp";
210
+ var peg$c22 = "tree";
211
+ var peg$c23 = "'";
212
+ var peg$c24 = "{{";
213
+ var peg$c25 = "`";
214
+ var peg$c26 = "}}";
214
215
 
215
216
  var peg$r0 = /^[^\n\r]/;
216
217
  var peg$r1 = /^[0-9]/;
@@ -244,14 +245,15 @@ function peg$parse(input, options) {
244
245
  var peg$e23 = peg$classExpectation(["+", "-"], false, false);
245
246
  var peg$e24 = peg$literalExpectation("https", false);
246
247
  var peg$e25 = peg$literalExpectation("http", false);
247
- var peg$e26 = peg$literalExpectation("treehttps", false);
248
- var peg$e27 = peg$literalExpectation("treehttp", false);
249
- var peg$e28 = peg$literalExpectation("tree", false);
250
- var peg$e29 = peg$literalExpectation("'", false);
251
- var peg$e30 = peg$otherExpectation("Origami template");
252
- var peg$e31 = peg$literalExpectation("{{", false);
253
- var peg$e32 = peg$literalExpectation("`", false);
254
- var peg$e33 = peg$literalExpectation("}}", false);
248
+ var peg$e26 = peg$literalExpectation("package", false);
249
+ var peg$e27 = peg$literalExpectation("treehttps", false);
250
+ var peg$e28 = peg$literalExpectation("treehttp", false);
251
+ var peg$e29 = peg$literalExpectation("tree", false);
252
+ var peg$e30 = peg$literalExpectation("'", false);
253
+ var peg$e31 = peg$otherExpectation("Origami template");
254
+ var peg$e32 = peg$literalExpectation("{{", false);
255
+ var peg$e33 = peg$literalExpectation("`", false);
256
+ var peg$e34 = peg$literalExpectation("}}", false);
255
257
 
256
258
  var peg$f0 = function() { return ""; };
257
259
  var peg$f1 = function(path) { return [[ops.filesRoot], ...path]; };
@@ -288,18 +290,19 @@ function peg$parse(input, options) {
288
290
  };
289
291
  var peg$f23 = function() { return ops.https; };
290
292
  var peg$f24 = function() { return ops.http; };
291
- var peg$f25 = function() { return ops.treeHttps; };
292
- var peg$f26 = function() { return ops.treeHttp; };
293
- var peg$f27 = function() { return ops.treeHttps; };
294
- var peg$f28 = function(key) { return [ops.scope, key]; };
295
- var peg$f29 = function(chars) { return chars.join(""); };
296
- var peg$f30 = function(contents) { return [ops.lambda, contents]; };
297
- var peg$f31 = function(parts) { return makeTemplate(parts); };
298
- var peg$f32 = function(chars) { return chars.join(""); };
299
- var peg$f33 = function(parts) { return makeTemplate(parts); };
300
- var peg$f34 = function(chars) { return chars.join(""); };
301
- var peg$f35 = function(assignments) { return [ops.tree, ...(assignments ?? [])]; };
302
- var peg$f36 = function(head, tail) {
293
+ var peg$f25 = function() { return [ops.scope, "@package"] };
294
+ var peg$f26 = function() { return ops.treeHttps; };
295
+ var peg$f27 = function() { return ops.treeHttp; };
296
+ var peg$f28 = function() { return ops.treeHttps; };
297
+ var peg$f29 = function(key) { return [ops.scope, key]; };
298
+ var peg$f30 = function(chars) { return chars.join(""); };
299
+ var peg$f31 = function(contents) { return [ops.lambda, contents]; };
300
+ var peg$f32 = function(parts) { return makeTemplate(parts); };
301
+ var peg$f33 = function(chars) { return chars.join(""); };
302
+ var peg$f34 = function(parts) { return makeTemplate(parts); };
303
+ var peg$f35 = function(chars) { return chars.join(""); };
304
+ var peg$f36 = function(assignments) { return [ops.tree, ...(assignments ?? [])]; };
305
+ var peg$f37 = function(head, tail) {
303
306
  return [head].concat(tail);
304
307
  };
305
308
  var peg$currPos = 0;
@@ -1708,9 +1711,9 @@ function peg$parse(input, options) {
1708
1711
  s0 = s1;
1709
1712
  if (s0 === peg$FAILED) {
1710
1713
  s0 = peg$currPos;
1711
- if (input.substr(peg$currPos, 9) === peg$c19) {
1714
+ if (input.substr(peg$currPos, 7) === peg$c19) {
1712
1715
  s1 = peg$c19;
1713
- peg$currPos += 9;
1716
+ peg$currPos += 7;
1714
1717
  } else {
1715
1718
  s1 = peg$FAILED;
1716
1719
  if (peg$silentFails === 0) { peg$fail(peg$e26); }
@@ -1722,9 +1725,9 @@ function peg$parse(input, options) {
1722
1725
  s0 = s1;
1723
1726
  if (s0 === peg$FAILED) {
1724
1727
  s0 = peg$currPos;
1725
- if (input.substr(peg$currPos, 8) === peg$c20) {
1728
+ if (input.substr(peg$currPos, 9) === peg$c20) {
1726
1729
  s1 = peg$c20;
1727
- peg$currPos += 8;
1730
+ peg$currPos += 9;
1728
1731
  } else {
1729
1732
  s1 = peg$FAILED;
1730
1733
  if (peg$silentFails === 0) { peg$fail(peg$e27); }
@@ -1736,9 +1739,9 @@ function peg$parse(input, options) {
1736
1739
  s0 = s1;
1737
1740
  if (s0 === peg$FAILED) {
1738
1741
  s0 = peg$currPos;
1739
- if (input.substr(peg$currPos, 4) === peg$c21) {
1742
+ if (input.substr(peg$currPos, 8) === peg$c21) {
1740
1743
  s1 = peg$c21;
1741
- peg$currPos += 4;
1744
+ peg$currPos += 8;
1742
1745
  } else {
1743
1746
  s1 = peg$FAILED;
1744
1747
  if (peg$silentFails === 0) { peg$fail(peg$e28); }
@@ -1748,6 +1751,21 @@ function peg$parse(input, options) {
1748
1751
  s1 = peg$f27();
1749
1752
  }
1750
1753
  s0 = s1;
1754
+ if (s0 === peg$FAILED) {
1755
+ s0 = peg$currPos;
1756
+ if (input.substr(peg$currPos, 4) === peg$c22) {
1757
+ s1 = peg$c22;
1758
+ peg$currPos += 4;
1759
+ } else {
1760
+ s1 = peg$FAILED;
1761
+ if (peg$silentFails === 0) { peg$fail(peg$e29); }
1762
+ }
1763
+ if (s1 !== peg$FAILED) {
1764
+ peg$savedPos = s0;
1765
+ s1 = peg$f28();
1766
+ }
1767
+ s0 = s1;
1768
+ }
1751
1769
  }
1752
1770
  }
1753
1771
  }
@@ -1763,7 +1781,7 @@ function peg$parse(input, options) {
1763
1781
  s1 = peg$parseidentifier();
1764
1782
  if (s1 !== peg$FAILED) {
1765
1783
  peg$savedPos = s0;
1766
- s1 = peg$f28(s1);
1784
+ s1 = peg$f29(s1);
1767
1785
  }
1768
1786
  s0 = s1;
1769
1787
 
@@ -1775,11 +1793,11 @@ function peg$parse(input, options) {
1775
1793
 
1776
1794
  s0 = peg$currPos;
1777
1795
  if (input.charCodeAt(peg$currPos) === 39) {
1778
- s1 = peg$c22;
1796
+ s1 = peg$c23;
1779
1797
  peg$currPos++;
1780
1798
  } else {
1781
1799
  s1 = peg$FAILED;
1782
- if (peg$silentFails === 0) { peg$fail(peg$e29); }
1800
+ if (peg$silentFails === 0) { peg$fail(peg$e30); }
1783
1801
  }
1784
1802
  if (s1 !== peg$FAILED) {
1785
1803
  s2 = [];
@@ -1789,15 +1807,15 @@ function peg$parse(input, options) {
1789
1807
  s3 = peg$parsesingleQuoteStringChar();
1790
1808
  }
1791
1809
  if (input.charCodeAt(peg$currPos) === 39) {
1792
- s3 = peg$c22;
1810
+ s3 = peg$c23;
1793
1811
  peg$currPos++;
1794
1812
  } else {
1795
1813
  s3 = peg$FAILED;
1796
- if (peg$silentFails === 0) { peg$fail(peg$e29); }
1814
+ if (peg$silentFails === 0) { peg$fail(peg$e30); }
1797
1815
  }
1798
1816
  if (s3 !== peg$FAILED) {
1799
1817
  peg$savedPos = s0;
1800
- s0 = peg$f29(s2);
1818
+ s0 = peg$f30(s2);
1801
1819
  } else {
1802
1820
  peg$currPos = s0;
1803
1821
  s0 = peg$FAILED;
@@ -1817,11 +1835,11 @@ function peg$parse(input, options) {
1817
1835
  s1 = peg$currPos;
1818
1836
  peg$silentFails++;
1819
1837
  if (input.charCodeAt(peg$currPos) === 39) {
1820
- s2 = peg$c22;
1838
+ s2 = peg$c23;
1821
1839
  peg$currPos++;
1822
1840
  } else {
1823
1841
  s2 = peg$FAILED;
1824
- if (peg$silentFails === 0) { peg$fail(peg$e29); }
1842
+ if (peg$silentFails === 0) { peg$fail(peg$e30); }
1825
1843
  }
1826
1844
  if (s2 === peg$FAILED) {
1827
1845
  s2 = peg$parsenewLine();
@@ -1875,11 +1893,11 @@ function peg$parse(input, options) {
1875
1893
  s0 = peg$currPos;
1876
1894
  s1 = peg$parsetemplateDocumentContents();
1877
1895
  peg$savedPos = s0;
1878
- s1 = peg$f30(s1);
1896
+ s1 = peg$f31(s1);
1879
1897
  s0 = s1;
1880
1898
  peg$silentFails--;
1881
1899
  s1 = peg$FAILED;
1882
- if (peg$silentFails === 0) { peg$fail(peg$e30); }
1900
+ if (peg$silentFails === 0) { peg$fail(peg$e31); }
1883
1901
 
1884
1902
  return s0;
1885
1903
  }
@@ -1890,12 +1908,12 @@ function peg$parse(input, options) {
1890
1908
  s0 = peg$currPos;
1891
1909
  s1 = peg$currPos;
1892
1910
  peg$silentFails++;
1893
- if (input.substr(peg$currPos, 2) === peg$c23) {
1894
- s2 = peg$c23;
1911
+ if (input.substr(peg$currPos, 2) === peg$c24) {
1912
+ s2 = peg$c24;
1895
1913
  peg$currPos += 2;
1896
1914
  } else {
1897
1915
  s2 = peg$FAILED;
1898
- if (peg$silentFails === 0) { peg$fail(peg$e31); }
1916
+ if (peg$silentFails === 0) { peg$fail(peg$e32); }
1899
1917
  }
1900
1918
  peg$silentFails--;
1901
1919
  if (s2 === peg$FAILED) {
@@ -1937,7 +1955,7 @@ function peg$parse(input, options) {
1937
1955
  }
1938
1956
  }
1939
1957
  peg$savedPos = s0;
1940
- s1 = peg$f31(s1);
1958
+ s1 = peg$f32(s1);
1941
1959
  s0 = s1;
1942
1960
 
1943
1961
  return s0;
@@ -1959,7 +1977,7 @@ function peg$parse(input, options) {
1959
1977
  }
1960
1978
  if (s1 !== peg$FAILED) {
1961
1979
  peg$savedPos = s0;
1962
- s1 = peg$f32(s1);
1980
+ s1 = peg$f33(s1);
1963
1981
  }
1964
1982
  s0 = s1;
1965
1983
 
@@ -1971,20 +1989,20 @@ function peg$parse(input, options) {
1971
1989
 
1972
1990
  s0 = peg$currPos;
1973
1991
  if (input.charCodeAt(peg$currPos) === 96) {
1974
- s1 = peg$c24;
1992
+ s1 = peg$c25;
1975
1993
  peg$currPos++;
1976
1994
  } else {
1977
1995
  s1 = peg$FAILED;
1978
- if (peg$silentFails === 0) { peg$fail(peg$e32); }
1996
+ if (peg$silentFails === 0) { peg$fail(peg$e33); }
1979
1997
  }
1980
1998
  if (s1 !== peg$FAILED) {
1981
1999
  s2 = peg$parsetemplateLiteralContents();
1982
2000
  if (input.charCodeAt(peg$currPos) === 96) {
1983
- s3 = peg$c24;
2001
+ s3 = peg$c25;
1984
2002
  peg$currPos++;
1985
2003
  } else {
1986
2004
  s3 = peg$FAILED;
1987
- if (peg$silentFails === 0) { peg$fail(peg$e32); }
2005
+ if (peg$silentFails === 0) { peg$fail(peg$e33); }
1988
2006
  }
1989
2007
  if (s3 !== peg$FAILED) {
1990
2008
  s0 = s2;
@@ -2007,19 +2025,19 @@ function peg$parse(input, options) {
2007
2025
  s1 = peg$currPos;
2008
2026
  peg$silentFails++;
2009
2027
  if (input.charCodeAt(peg$currPos) === 96) {
2010
- s2 = peg$c24;
2028
+ s2 = peg$c25;
2011
2029
  peg$currPos++;
2012
2030
  } else {
2013
2031
  s2 = peg$FAILED;
2014
- if (peg$silentFails === 0) { peg$fail(peg$e32); }
2032
+ if (peg$silentFails === 0) { peg$fail(peg$e33); }
2015
2033
  }
2016
2034
  if (s2 === peg$FAILED) {
2017
- if (input.substr(peg$currPos, 2) === peg$c23) {
2018
- s2 = peg$c23;
2035
+ if (input.substr(peg$currPos, 2) === peg$c24) {
2036
+ s2 = peg$c24;
2019
2037
  peg$currPos += 2;
2020
2038
  } else {
2021
2039
  s2 = peg$FAILED;
2022
- if (peg$silentFails === 0) { peg$fail(peg$e31); }
2040
+ if (peg$silentFails === 0) { peg$fail(peg$e32); }
2023
2041
  }
2024
2042
  }
2025
2043
  peg$silentFails--;
@@ -2062,7 +2080,7 @@ function peg$parse(input, options) {
2062
2080
  }
2063
2081
  }
2064
2082
  peg$savedPos = s0;
2065
- s1 = peg$f33(s1);
2083
+ s1 = peg$f34(s1);
2066
2084
  s0 = s1;
2067
2085
 
2068
2086
  return s0;
@@ -2084,7 +2102,7 @@ function peg$parse(input, options) {
2084
2102
  }
2085
2103
  if (s1 !== peg$FAILED) {
2086
2104
  peg$savedPos = s0;
2087
- s1 = peg$f34(s1);
2105
+ s1 = peg$f35(s1);
2088
2106
  }
2089
2107
  s0 = s1;
2090
2108
 
@@ -2095,22 +2113,22 @@ function peg$parse(input, options) {
2095
2113
  var s0, s1, s2, s3;
2096
2114
 
2097
2115
  s0 = peg$currPos;
2098
- if (input.substr(peg$currPos, 2) === peg$c23) {
2099
- s1 = peg$c23;
2116
+ if (input.substr(peg$currPos, 2) === peg$c24) {
2117
+ s1 = peg$c24;
2100
2118
  peg$currPos += 2;
2101
2119
  } else {
2102
2120
  s1 = peg$FAILED;
2103
- if (peg$silentFails === 0) { peg$fail(peg$e31); }
2121
+ if (peg$silentFails === 0) { peg$fail(peg$e32); }
2104
2122
  }
2105
2123
  if (s1 !== peg$FAILED) {
2106
2124
  s2 = peg$parseexpression();
2107
2125
  if (s2 !== peg$FAILED) {
2108
- if (input.substr(peg$currPos, 2) === peg$c25) {
2109
- s3 = peg$c25;
2126
+ if (input.substr(peg$currPos, 2) === peg$c26) {
2127
+ s3 = peg$c26;
2110
2128
  peg$currPos += 2;
2111
2129
  } else {
2112
2130
  s3 = peg$FAILED;
2113
- if (peg$silentFails === 0) { peg$fail(peg$e33); }
2131
+ if (peg$silentFails === 0) { peg$fail(peg$e34); }
2114
2132
  }
2115
2133
  if (s3 !== peg$FAILED) {
2116
2134
  s0 = s2;
@@ -2173,7 +2191,7 @@ function peg$parse(input, options) {
2173
2191
  }
2174
2192
  if (s4 !== peg$FAILED) {
2175
2193
  peg$savedPos = s0;
2176
- s0 = peg$f35(s3);
2194
+ s0 = peg$f36(s3);
2177
2195
  } else {
2178
2196
  peg$currPos = s0;
2179
2197
  s0 = peg$FAILED;
@@ -2230,7 +2248,7 @@ function peg$parse(input, options) {
2230
2248
  }
2231
2249
  s4 = peg$parse__();
2232
2250
  peg$savedPos = s0;
2233
- s0 = peg$f36(s1, s2);
2251
+ s0 = peg$f37(s1, s2);
2234
2252
  } else {
2235
2253
  peg$currPos = s0;
2236
2254
  s0 = peg$FAILED;
@@ -24,6 +24,13 @@ async function getText(value, scope) {
24
24
  value = await value.call(scope);
25
25
  }
26
26
 
27
+ if (Tree.isTreelike(value)) {
28
+ // The mapReduce operation above only implicit casts its top-level input to
29
+ // a tree. If we're asked for the text of a treelike value, we need to
30
+ // explicitly recurse.
31
+ return concatTreeValues.call(scope, value);
32
+ }
33
+
27
34
  // Convert to text, preferring .toString but avoiding dumb Object.toString.
28
35
  // Exception: if the result is an array, we'll concatenate the values.
29
36
  let text;
@@ -10,6 +10,9 @@ import Scope from "./Scope.js";
10
10
  import concatTreeValues from "./concatTreeValues.js";
11
11
  import { OrigamiTree, evaluate, expressionFunction } from "./internal.js";
12
12
 
13
+ // For memoizing lambda functions
14
+ const lambdaFnMap = new Map();
15
+
13
16
  /**
14
17
  * Construct an array.
15
18
  *
@@ -130,6 +133,9 @@ inherited.toString = () => "«ops.inherited»";
130
133
  * @param {Code} code
131
134
  */
132
135
  export function lambda(code) {
136
+ if (lambdaFnMap.has(code)) {
137
+ return lambdaFnMap.get(code);
138
+ }
133
139
  /** @this {AsyncTree|null} */
134
140
  async function invoke(input) {
135
141
  // Add ambients to scope.
@@ -142,6 +148,7 @@ export function lambda(code) {
142
148
  return result;
143
149
  }
144
150
  invoke.code = code;
151
+ lambdaFnMap.set(code, invoke);
145
152
  return invoke;
146
153
  }
147
154
  lambda.toString = () => "«ops.lambda»";
@@ -93,7 +93,7 @@ describe("Origami parser", () => {
93
93
  "expression",
94
94
  `
95
95
  {
96
- index.html = index.orit(teamData.yaml)
96
+ index.html = index.ori(teamData.yaml)
97
97
  thumbnails = @map(images, { valueMap: thumbnail.js })
98
98
  }
99
99
  `,
@@ -102,7 +102,7 @@ describe("Origami parser", () => {
102
102
  [
103
103
  "index.html",
104
104
  [
105
- [ops.scope, "index.orit"],
105
+ [ops.scope, "index.ori"],
106
106
  [ops.scope, "teamData.yaml"],
107
107
  ],
108
108
  ],
@@ -1,4 +1,4 @@
1
- import { Tree } from "@weborigami/async-tree";
1
+ import { FunctionTree, Tree } from "@weborigami/async-tree";
2
2
  import assert from "node:assert";
3
3
  import { describe, test } from "node:test";
4
4
  import concatTreeValues from "../../src/runtime/concatTreeValues.js";
@@ -17,4 +17,17 @@ describe("concatTreeValues", () => {
17
17
  const result = await concatTreeValues.call(null, tree);
18
18
  assert.equal(result, "ABCDE");
19
19
  });
20
+
21
+ test("concatenates deep tree-like values", async () => {
22
+ const letters = ["a", "b", "c"];
23
+ const specimens = new FunctionTree(
24
+ (letter) => ({
25
+ lowercase: letter,
26
+ uppercase: letter.toUpperCase(),
27
+ }),
28
+ letters
29
+ );
30
+ const result = await concatTreeValues.call(null, specimens);
31
+ assert.equal(result, "aAbBcC");
32
+ });
20
33
  });