@weborigami/language 0.2.10 → 0.2.12

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/main.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./src/runtime/internal.js";
2
2
 
3
3
  export * as compile from "./src/compiler/compile.js";
4
+ export { default as isOrigamiFrontMatter } from "./src/compiler/isOrigamiFrontMatter.js";
4
5
  export * from "./src/runtime/errors.js";
5
6
  export { default as evaluate } from "./src/runtime/evaluate.js";
6
7
  export { default as EventTargetMixin } from "./src/runtime/EventTargetMixin.js";
@@ -13,7 +14,6 @@ export { default as InvokeFunctionsTransform } from "./src/runtime/InvokeFunctio
13
14
  export * as moduleCache from "./src/runtime/moduleCache.js";
14
15
  export { default as OrigamiFiles } from "./src/runtime/OrigamiFiles.js";
15
16
  export * as symbols from "./src/runtime/symbols.js";
16
- export { default as taggedTemplate } from "./src/runtime/taggedTemplate.js";
17
17
  export { default as taggedTemplateIndent } from "./src/runtime/taggedTemplateIndent.js";
18
18
  export { default as TreeEvent } from "./src/runtime/TreeEvent.js";
19
19
  export { default as WatchFilesMixin } from "./src/runtime/WatchFilesMixin.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -8,13 +8,13 @@
8
8
  "devDependencies": {
9
9
  "@types/node": "22.13.13",
10
10
  "peggy": "4.2.0.",
11
- "typescript": "5.8.2",
12
- "yaml": "2.7.0"
11
+ "typescript": "5.8.2"
13
12
  },
14
13
  "dependencies": {
15
- "@weborigami/async-tree": "0.2.10",
16
- "@weborigami/types": "0.2.10",
17
- "watcher": "2.3.1"
14
+ "@weborigami/async-tree": "0.2.12",
15
+ "@weborigami/types": "0.2.12",
16
+ "watcher": "2.3.1",
17
+ "yaml": "2.7.0"
18
18
  },
19
19
  "scripts": {
20
20
  "build": "peggy --allowed-start-rules=\"*\" --format es src/compiler/origami.pegjs --output src/compiler/parse.js",
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Return true if the given text is Origami front matter
3
+ *
4
+ * Our heurstic is to see skip any initial alphanumeric or underscore
5
+ * characters, then see if the next character is a parenthesis, dot, slash,
6
+ * curly brace, or equals sign. If so, we assume this is an Origami expression.
7
+ *
8
+ * The goal is to identify Origami front matter like:
9
+ *
10
+ * ```
11
+ * fn(x) function call
12
+ * index.ori() file extension
13
+ * src/data.json file path
14
+ * // Hello comment
15
+ * { a: 1 } object literal
16
+ * ```
17
+ *
18
+ * These are generally invalid ways to start YAML. The last is valid YAML, but
19
+ * Origami supports the same syntax for basic object literals so interpreting as
20
+ * Origami should generally be acceptable.
21
+ *
22
+ * @param {string} text
23
+ */
24
+ export default function isOrigamiFrontMatter(text) {
25
+ return /^[ \t\r\n]*[A-Za-z0-9_]*[\(\.\/\{=]/.test(text);
26
+ }
@@ -14,6 +14,7 @@
14
14
  import * as ops from "../runtime/ops.js";
15
15
  import {
16
16
  annotate,
17
+ applyMacro,
17
18
  downgradeReference,
18
19
  makeArray,
19
20
  makeBinaryOperation,
@@ -24,8 +25,10 @@ import {
24
25
  makeProperty,
25
26
  makeReference,
26
27
  makeTemplate,
27
- makeUnaryOperation
28
+ makeUnaryOperation,
29
+ makeYamlObject
28
30
  } from "./parserHelpers.js";
31
+ import isOrigamiFrontMatter from "./isOrigamiFrontMatter.js";
29
32
 
30
33
  }}
31
34
 
@@ -206,6 +209,18 @@ expectDoubleQuote
206
209
  error("Expected closing quote");
207
210
  }
208
211
 
212
+ expectExpression
213
+ = expression
214
+ / .? {
215
+ error("Expected an Origami expression");
216
+ }
217
+
218
+ expectFrontDelimiter
219
+ = frontDelimiter
220
+ / .? {
221
+ error("Expected \"---\"");
222
+ }
223
+
209
224
  expectGuillemet
210
225
  = '»'
211
226
  / .? {
@@ -239,6 +254,27 @@ floatLiteral "floating-point number"
239
254
  return annotate([ops.literal, parseFloat(text())], location());
240
255
  }
241
256
 
257
+ // Marker for the beginning or end of front matter
258
+ frontDelimiter
259
+ = "---\n"
260
+
261
+ // Origami front matter
262
+ frontMatterExpression
263
+ // If we detect Origami front matter, we need to see an expression
264
+ = frontDelimiter &{
265
+ return isOrigamiFrontMatter(input.slice(location().end.offset))
266
+ } @expectExpression expectFrontDelimiter
267
+
268
+ frontMatterText
269
+ = chars:( !frontDelimiter @. )* {
270
+ return chars.join("");
271
+ }
272
+
273
+ frontMatterYaml "YAML front matter"
274
+ = frontDelimiter yaml:frontMatterText frontDelimiter {
275
+ return makeYamlObject(yaml, location());
276
+ }
277
+
242
278
  // An expression in parentheses: `(foo)`
243
279
  group "parenthetical group"
244
280
  = "(" expression:expression expectClosingParenthesis {
@@ -619,10 +655,10 @@ stringLiteral "string"
619
655
  / singleQuoteString
620
656
  / guillemetString
621
657
 
622
- // A top-level document defining a template. This is the same as a template
623
- // literal, but can contain backticks at the top level.
624
- templateDocument "template"
625
- = head:templateDocumentText tail:(templateSubstitution templateDocumentText)* {
658
+ // The body of a template document is a kind of template literal that can
659
+ // contain backticks at the top level.
660
+ templateBody "template"
661
+ = head:templateBodyText tail:(templateSubstitution templateBodyText)* {
626
662
  const lambdaParameters = annotate(
627
663
  [annotate([ops.literal, "_"], location())],
628
664
  location()
@@ -633,15 +669,25 @@ templateDocument "template"
633
669
  );
634
670
  }
635
671
 
636
- // Template documents can contain backticks at the top level.
637
- templateDocumentChar
672
+ // Template document bodies can contain backticks at the top level
673
+ templateBodyChar
638
674
  = !("${") @textChar
639
675
 
640
- templateDocumentText "template text"
641
- = chars:templateDocumentChar* {
676
+ templateBodyText "template text"
677
+ = chars:templateBodyChar* {
642
678
  return annotate([ops.literal, chars.join("")], location());
643
679
  }
644
680
 
681
+ templateDocument "template document"
682
+ = front:frontMatterExpression __ body:templateBody {
683
+ return annotate(applyMacro(front, "@template", body), location());
684
+ }
685
+ / front:frontMatterYaml? body:templateBody {
686
+ return front
687
+ ? annotate([ops.document, front, body], location())
688
+ : annotate(body, location());
689
+ }
690
+
645
691
  // A backtick-quoted template literal
646
692
  templateLiteral "template literal"
647
693
  = "`" head:templateLiteralText tail:(templateSubstitution templateLiteralText)* expectBacktick {
@@ -659,7 +705,7 @@ templateLiteralText
659
705
 
660
706
  // A substitution in a template literal: `${x}`
661
707
  templateSubstitution "template substitution"
662
- = "${" expression:expression "}" {
708
+ = "${" expression:expectExpression "}" {
663
709
  return annotate(expression, location());
664
710
  }
665
711