@weborigami/language 0.0.67-beta.2 → 0.0.69
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.0.
|
|
3
|
+
"version": "0.0.69",
|
|
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.6.2"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.0.
|
|
15
|
-
"@weborigami/types": "0.0.
|
|
14
|
+
"@weborigami/async-tree": "0.0.69",
|
|
15
|
+
"@weborigami/types": "0.0.69",
|
|
16
16
|
"watcher": "2.3.1"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
makeFunctionCall,
|
|
14
14
|
makeObject,
|
|
15
15
|
makePipeline,
|
|
16
|
+
makeProperty,
|
|
16
17
|
makeTemplate
|
|
17
18
|
} from "./parserHelpers.js";
|
|
18
19
|
|
|
@@ -249,7 +250,7 @@ objectEntry
|
|
|
249
250
|
// A getter definition inside an object literal: `foo = 1`
|
|
250
251
|
objectGetter "object getter"
|
|
251
252
|
= key:objectKey __ "=" __ value:expr {
|
|
252
|
-
return annotate(
|
|
253
|
+
return annotate(makeProperty(key, [ops.getter, value]), location());
|
|
253
254
|
}
|
|
254
255
|
|
|
255
256
|
objectHiddenKey
|
|
@@ -262,7 +263,7 @@ objectKey "object key"
|
|
|
262
263
|
// A property definition in an object literal: `x: 1`
|
|
263
264
|
objectProperty "object property"
|
|
264
265
|
= key:objectKey __ ":" __ value:expr {
|
|
265
|
-
return annotate(
|
|
266
|
+
return annotate(makeProperty(key, value), location());
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
// A shorthand reference inside an object literal: `foo`
|
package/src/compiler/parse.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
makeFunctionCall,
|
|
19
19
|
makeObject,
|
|
20
20
|
makePipeline,
|
|
21
|
+
makeProperty,
|
|
21
22
|
makeTemplate
|
|
22
23
|
} from "./parserHelpers.js";
|
|
23
24
|
|
|
@@ -425,11 +426,11 @@ function peg$parse(input, options) {
|
|
|
425
426
|
return annotate(entries, location());
|
|
426
427
|
};
|
|
427
428
|
var peg$f31 = function(key, value) {
|
|
428
|
-
return annotate(
|
|
429
|
+
return annotate(makeProperty(key, [ops.getter, value]), location());
|
|
429
430
|
};
|
|
430
431
|
var peg$f32 = function(hiddenKey) { return hiddenKey.join(""); };
|
|
431
432
|
var peg$f33 = function(key, value) {
|
|
432
|
-
return annotate(
|
|
433
|
+
return annotate(makeProperty(key, value), location());
|
|
433
434
|
};
|
|
434
435
|
var peg$f34 = function(key) {
|
|
435
436
|
return annotate([key, [ops.inherited, key]], location());
|
|
@@ -13,8 +13,28 @@ export function annotate(parseResult, location) {
|
|
|
13
13
|
return parseResult;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
// The indicated code is being used to define a property named by the given key.
|
|
17
|
+
// Rewrite any [ops.scope, key] calls to be [ops.inherited, key] to avoid
|
|
18
|
+
// infinite recursion.
|
|
19
|
+
function avoidRecursivePropertyCalls(code, key) {
|
|
20
|
+
if (!(code instanceof Array)) {
|
|
21
|
+
return code;
|
|
22
|
+
}
|
|
23
|
+
let modified;
|
|
24
|
+
if (code[0] === ops.scope && code[1] === key) {
|
|
25
|
+
// Rewrite to avoid recursion
|
|
26
|
+
modified = [ops.inherited, key];
|
|
27
|
+
} else {
|
|
28
|
+
// Process any nested code
|
|
29
|
+
modified = code.map((value) => avoidRecursivePropertyCalls(value, key));
|
|
30
|
+
}
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
modified.location = code.location;
|
|
33
|
+
return modified;
|
|
34
|
+
}
|
|
35
|
+
|
|
16
36
|
// Return true if the code will generate an async object.
|
|
17
|
-
function
|
|
37
|
+
function isCodeForAsyncObject(code) {
|
|
18
38
|
if (!(code instanceof Array)) {
|
|
19
39
|
return false;
|
|
20
40
|
}
|
|
@@ -120,28 +140,29 @@ export function makeObject(entries, op) {
|
|
|
120
140
|
|
|
121
141
|
for (let [key, value] of entries) {
|
|
122
142
|
if (key === ops.spread) {
|
|
123
|
-
//
|
|
143
|
+
// Spread entry; accumulate
|
|
124
144
|
if (currentEntries.length > 0) {
|
|
125
145
|
spreads.push([op, ...currentEntries]);
|
|
126
146
|
currentEntries = [];
|
|
127
147
|
}
|
|
128
148
|
spreads.push(value);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
value instanceof Array &&
|
|
132
|
-
value[0] === ops.getter &&
|
|
133
|
-
value[1] instanceof Array &&
|
|
134
|
-
value[1][0] === ops.primitive
|
|
135
|
-
) {
|
|
136
|
-
// Simplify a getter for a primitive value to a regular property
|
|
137
|
-
value = value[1];
|
|
138
|
-
} else if (isAsyncObject(value)) {
|
|
139
|
-
// Add a trailing slash to key if value is an async object
|
|
140
|
-
key = key + "/";
|
|
141
|
-
}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
142
151
|
|
|
143
|
-
|
|
152
|
+
if (
|
|
153
|
+
value instanceof Array &&
|
|
154
|
+
value[0] === ops.getter &&
|
|
155
|
+
value[1] instanceof Array &&
|
|
156
|
+
value[1][0] === ops.primitive
|
|
157
|
+
) {
|
|
158
|
+
// Simplify a getter for a primitive value to a regular property
|
|
159
|
+
value = value[1];
|
|
160
|
+
} else if (isCodeForAsyncObject(value)) {
|
|
161
|
+
// Add a trailing slash to key to indicate value is a subtree
|
|
162
|
+
key = key + "/";
|
|
144
163
|
}
|
|
164
|
+
|
|
165
|
+
currentEntries.push([key, value]);
|
|
145
166
|
}
|
|
146
167
|
|
|
147
168
|
// Finish any current entries.
|
|
@@ -170,6 +191,12 @@ export function makePipeline(steps) {
|
|
|
170
191
|
return value;
|
|
171
192
|
}
|
|
172
193
|
|
|
194
|
+
// Define a property on an object.
|
|
195
|
+
export function makeProperty(key, value) {
|
|
196
|
+
const modified = avoidRecursivePropertyCalls(value, key);
|
|
197
|
+
return [key, modified];
|
|
198
|
+
}
|
|
199
|
+
|
|
173
200
|
export function makeTemplate(parts) {
|
|
174
201
|
// Drop empty/null strings.
|
|
175
202
|
const filtered = parts.filter((part) => part);
|
package/src/runtime/ops.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SiteTree,
|
|
10
10
|
Tree,
|
|
11
11
|
isUnpackable,
|
|
12
|
+
pathFromKeys,
|
|
12
13
|
scope as scopeFn,
|
|
13
14
|
trailingSlash,
|
|
14
15
|
concat as treeConcat,
|
|
@@ -77,12 +78,11 @@ constructor.toString = () => "«ops.constructor»";
|
|
|
77
78
|
*
|
|
78
79
|
* @param {string} protocol
|
|
79
80
|
* @param {string} host
|
|
80
|
-
* @param {
|
|
81
|
+
* @param {string[]} keys
|
|
81
82
|
*/
|
|
82
83
|
function constructHref(protocol, host, ...keys) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let href = [host, ...baseKeys].join("/");
|
|
84
|
+
const path = pathFromKeys(keys);
|
|
85
|
+
let href = [host, path].join("/");
|
|
86
86
|
if (!href.startsWith(protocol)) {
|
|
87
87
|
if (!href.startsWith("//")) {
|
|
88
88
|
href = `//${href}`;
|
|
@@ -99,7 +99,7 @@ function constructHref(protocol, host, ...keys) {
|
|
|
99
99
|
* @param {import("../../index.ts").Constructor<AsyncTree>} treeClass
|
|
100
100
|
* @param {AsyncTree|null} parent
|
|
101
101
|
* @param {string} host
|
|
102
|
-
* @param {
|
|
102
|
+
* @param {string[]} keys
|
|
103
103
|
*/
|
|
104
104
|
async function constructSiteTree(protocol, treeClass, parent, host, ...keys) {
|
|
105
105
|
// If the last key doesn't end in a slash, remove it for now.
|
|
@@ -165,7 +165,7 @@ export async function filesRoot() {
|
|
|
165
165
|
*
|
|
166
166
|
* @this {AsyncTree|null}
|
|
167
167
|
* @param {string} host
|
|
168
|
-
* @param {...string
|
|
168
|
+
* @param {...string} keys
|
|
169
169
|
*/
|
|
170
170
|
export async function http(host, ...keys) {
|
|
171
171
|
const href = constructHref("http:", host, ...keys);
|
|
@@ -178,7 +178,7 @@ http.toString = () => "«ops.http»";
|
|
|
178
178
|
*
|
|
179
179
|
* @this {AsyncTree|null}
|
|
180
180
|
* @param {string} host
|
|
181
|
-
* @param {...string
|
|
181
|
+
* @param {...string} keys
|
|
182
182
|
*/
|
|
183
183
|
export function https(host, ...keys) {
|
|
184
184
|
const href = constructHref("https:", host, ...keys);
|
|
@@ -289,7 +289,7 @@ object.toString = () => "«ops.object»";
|
|
|
289
289
|
*
|
|
290
290
|
* @this {AsyncTree|null}
|
|
291
291
|
* @param {string} host
|
|
292
|
-
* @param {...string
|
|
292
|
+
* @param {...string} keys
|
|
293
293
|
*/
|
|
294
294
|
export function explorableSite(host, ...keys) {
|
|
295
295
|
return constructSiteTree("https:", ExplorableSiteTree, this, host, ...keys);
|
|
@@ -339,7 +339,7 @@ export const traverse = Tree.traverseOrThrow;
|
|
|
339
339
|
*
|
|
340
340
|
* @this {AsyncTree|null}
|
|
341
341
|
* @param {string} host
|
|
342
|
-
* @param {...string
|
|
342
|
+
* @param {...string} keys
|
|
343
343
|
*/
|
|
344
344
|
export function treeHttp(host, ...keys) {
|
|
345
345
|
return constructSiteTree("http:", SiteTree, this, host, ...keys);
|
|
@@ -351,7 +351,7 @@ treeHttp.toString = () => "«ops.treeHttp»";
|
|
|
351
351
|
*
|
|
352
352
|
* @this {AsyncTree|null}
|
|
353
353
|
* @param {string} host
|
|
354
|
-
* @param {...string
|
|
354
|
+
* @param {...string} keys
|
|
355
355
|
*/
|
|
356
356
|
export function treeHttps(host, ...keys) {
|
|
357
357
|
return constructSiteTree("https:", SiteTree, this, host, ...keys);
|
|
@@ -417,6 +417,7 @@ describe("Origami parser", () => {
|
|
|
417
417
|
test("objectEntry", () => {
|
|
418
418
|
assertParse("objectEntry", "foo", ["foo", [ops.inherited, "foo"]]);
|
|
419
419
|
assertParse("objectEntry", "x: y", ["x", [ops.scope, "y"]]);
|
|
420
|
+
assertParse("objectEntry", "a: a", ["a", [ops.inherited, "a"]]);
|
|
420
421
|
});
|
|
421
422
|
|
|
422
423
|
test("objectGetter", () => {
|