@dogsbay/minja 0.2.0-beta.93 → 0.2.0-beta.98

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/README.md CHANGED
@@ -101,6 +101,8 @@ Options:
101
101
  -d, --max-depth <number> Maximum include depth (default: 10)
102
102
  -t, --timeout <ms> Rendering timeout in milliseconds (default: 5000)
103
103
  -v, --vars <json> Inline context variables as JSON
104
+ -r, --include-root <dir> Refuse {% include %} targets that resolve
105
+ (after symlinks) outside this directory
104
106
  -h, --help display help for command
105
107
  ```
106
108
 
@@ -129,6 +131,24 @@ minja README.md --context vars.json
129
131
  minja document.md --output docs/index.html
130
132
  ```
131
133
 
134
+ **Untrusted input — contain includes to a directory:**
135
+ ```bash
136
+ # Any {% include %} resolving (after symlink resolution) outside docs/
137
+ # is REFUSED and the render fails — without this, an include like
138
+ # "../secrets.txt" or "/etc/hostname" splices any readable file into
139
+ # the output. `..` and absolute paths that stay inside the root are fine.
140
+ minja docs/page.md --include-root docs/
141
+ ```
142
+
143
+ Programmatic equivalent:
144
+ ```ts
145
+ import { render, FileSystemLoader } from '@dogsbay/minja'
146
+ const out = await render(template, {
147
+ basePath: 'docs/',
148
+ loader: new FileSystemLoader('docs/', { root: 'docs/' }),
149
+ })
150
+ ```
151
+
132
152
  **Pipeline usage:**
133
153
  ```bash
134
154
  # Generate docs from multiple sources
package/bin/minja.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * minja v0.2.0-beta.93
3
+ * minja v0.2.0-beta.98
4
4
  * Minimal, secure Jinja2/Nunjucks subset for documentation preprocessing
5
5
  * @license MIT
6
6
  */
@@ -171,6 +171,24 @@ function isTruthy(value) {
171
171
  }
172
172
 
173
173
  // src/parser.ts
174
+ var KNOWN_TAG_KEYWORDS = /* @__PURE__ */ new Set([
175
+ "set",
176
+ "if",
177
+ "include",
178
+ "switch",
179
+ "leveloffset",
180
+ "raw",
181
+ "endif",
182
+ "elif",
183
+ "else",
184
+ "endswitch",
185
+ "case",
186
+ "endleveloffset",
187
+ "endraw"
188
+ ]);
189
+ function stripBodyForEndTag(body, endTag) {
190
+ return endTag.startsWith("{%-") ? body.replace(/[ \t]*\n[ \t\n]*$/, "") : body;
191
+ }
174
192
  function parse(template) {
175
193
  const errors = [];
176
194
  const ast = [];
@@ -253,12 +271,57 @@ function parse(template) {
253
271
  }
254
272
  }
255
273
  } else if (nearest.type === "tag") {
274
+ const tagStart2 = position;
256
275
  advance(2);
257
276
  const endPos = findNext("%}", position);
258
277
  if (endPos === -1) {
259
278
  errors.push(createError("Unclosed statement tag"));
260
279
  break;
261
280
  }
281
+ const peeked = template.substring(position, endPos).trim();
282
+ const peekKeyword = peeked.replace(/^-\s*/, "").replace(/\s*-$/, "").split(/\s+/)[0] ?? "";
283
+ if (peekKeyword === "raw") {
284
+ const openerLeftStrip = peeked.startsWith("-");
285
+ const openerRightStrip = peeked.endsWith("-");
286
+ if (openerLeftStrip && ast.length > 0 && ast[ast.length - 1].type === "text") {
287
+ const lastNode = ast[ast.length - 1];
288
+ lastNode.value = lastNode.value.replace(/[ \t]*\n[ \t\n]*$/, "");
289
+ }
290
+ extractTo(endPos);
291
+ advance(2);
292
+ if (openerRightStrip) {
293
+ while (position < template.length && /[ \t\n]/.test(template[position])) {
294
+ advance(1);
295
+ }
296
+ }
297
+ const endrawMatch = /\{%-?\s*endraw\s*-?%\}/.exec(template.substring(position));
298
+ if (!endrawMatch) {
299
+ errors.push(createError("Unclosed raw block"));
300
+ break;
301
+ }
302
+ const endrawAbs = position + endrawMatch.index;
303
+ let content = extractTo(endrawAbs);
304
+ const endrawTag = endrawMatch[0];
305
+ if (endrawTag.startsWith("{%-")) {
306
+ content = content.replace(/[ \t]*\n[ \t\n]*$/, "");
307
+ }
308
+ advance(endrawTag.length);
309
+ if (endrawTag.endsWith("-%}")) {
310
+ while (position < template.length && /[ \t\n]/.test(template[position])) {
311
+ advance(1);
312
+ }
313
+ }
314
+ if (content) {
315
+ ast.push({ type: "text", value: content });
316
+ }
317
+ continue;
318
+ }
319
+ if (!KNOWN_TAG_KEYWORDS.has(peekKeyword)) {
320
+ extractTo(endPos);
321
+ advance(2);
322
+ ast.push({ type: "text", value: template.substring(tagStart2, endPos + 2) });
323
+ continue;
324
+ }
262
325
  let statement = extractTo(endPos).trim();
263
326
  const hasLeftStrip = statement.startsWith("-");
264
327
  const hasRightStrip = statement.endsWith("-");
@@ -392,12 +455,13 @@ function parse(template) {
392
455
  }
393
456
  return { ast, errors };
394
457
  function findEndTag(tagName) {
395
- const pattern = new RegExp(`{%\\s*${tagName}\\s*%}`);
458
+ const pattern = new RegExp(`{%-?\\s*${tagName}\\s*-?%}`);
396
459
  const match = pattern.exec(template.substring(position));
397
460
  if (match) {
398
461
  return {
399
462
  start: position + match.index,
400
- length: match[0].length
463
+ length: match[0].length,
464
+ tag: match[0]
401
465
  };
402
466
  }
403
467
  return null;
@@ -429,8 +493,12 @@ function parse(template) {
429
493
  searchPos = nearest.pos + nearest.match[0].length;
430
494
  } else if (nearest.type === "endif") {
431
495
  if (depth === 0) {
432
- const bodyTemplate = extractTo(nearest.pos);
496
+ const bodyTemplate = stripBodyForEndTag(extractTo(nearest.pos), nearest.match[0]);
433
497
  advance(nearest.match[0].length);
498
+ if (nearest.match[0].endsWith("-%}")) {
499
+ while (position < template.length && /[ \t\n]/.test(template[position]))
500
+ advance(1);
501
+ }
434
502
  const bodyResult = parse(bodyTemplate);
435
503
  parseErrors.push(...bodyResult.errors);
436
504
  return {
@@ -444,7 +512,7 @@ function parse(template) {
444
512
  searchPos = nearest.pos + nearest.match[0].length;
445
513
  }
446
514
  } else if (depth === 0 && (nearest.type === "elif" || nearest.type === "else")) {
447
- const bodyTemplate = extractTo(nearest.pos);
515
+ const bodyTemplate = stripBodyForEndTag(extractTo(nearest.pos), nearest.match[0]);
448
516
  const bodyResult = parse(bodyTemplate);
449
517
  if (elifBranches.length === 0 && elseBranch.length === 0) {
450
518
  parseErrors.push(...bodyResult.errors);
@@ -481,7 +549,10 @@ function parse(template) {
481
549
  if (!endifMatch2) {
482
550
  parseErrors.push(createError("Missing endif after else"));
483
551
  } else {
484
- const elseBodyTemplate = extractTo(endifMatch2.start);
552
+ const elseBodyTemplate = stripBodyForEndTag(
553
+ extractTo(endifMatch2.start),
554
+ endifMatch2.tag
555
+ );
485
556
  advance(endifMatch2.length);
486
557
  const elseBodyResult = parse(elseBodyTemplate);
487
558
  parseErrors.push(...elseBodyResult.errors);
@@ -667,12 +738,14 @@ var FetchLoader = class {
667
738
  };
668
739
 
669
740
  // src/renderer.ts
670
- function transformHeadings(text, offset) {
741
+ function transformHeadings(text, offset, initialFence = null, fenceOut) {
671
742
  if (offset === 0) {
743
+ if (fenceOut)
744
+ fenceOut.fence = initialFence;
672
745
  return text;
673
746
  }
674
747
  const lines = text.split("\n");
675
- let fence = null;
748
+ let fence = initialFence;
676
749
  for (let i = 0; i < lines.length; i++) {
677
750
  const line = lines[i];
678
751
  const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
@@ -694,6 +767,8 @@ function transformHeadings(text, offset) {
694
767
  lines[i] = "#".repeat(newLevel) + line.slice(m[1].length);
695
768
  }
696
769
  }
770
+ if (fenceOut)
771
+ fenceOut.fence = fence;
697
772
  return lines.join("\n");
698
773
  }
699
774
  function resolvePath(path, basePath) {
@@ -765,7 +840,14 @@ async function renderInternal(template, options) {
765
840
  async function renderNodes(nodes, options) {
766
841
  const parts = [];
767
842
  for (const node of nodes) {
768
- parts.push(await renderNode(node, options));
843
+ let rendered = await renderNode(node, options);
844
+ if (node.type === "include" && rendered && parts.length > 0) {
845
+ const tail = /(?:^|\n)([ \t]+)$/.exec(parts[parts.length - 1]);
846
+ if (tail) {
847
+ rendered = rendered.replace(/\n(?=[^\n])/g, "\n" + tail[1]);
848
+ }
849
+ }
850
+ parts.push(rendered);
769
851
  }
770
852
  return parts.join("");
771
853
  }
@@ -777,7 +859,15 @@ async function renderNode(node, options) {
777
859
  if (currentOffset === 0) {
778
860
  return node.value;
779
861
  }
780
- return transformHeadings(node.value, currentOffset);
862
+ const fenceOut = { fence: null };
863
+ const out = transformHeadings(
864
+ node.value,
865
+ currentOffset,
866
+ context.get("_levelOffsetFence") ?? null,
867
+ fenceOut
868
+ );
869
+ context.set("_levelOffsetFence", fenceOut.fence);
870
+ return out;
781
871
  }
782
872
  case "variable": {
783
873
  const value = context.get(node.name);
@@ -787,6 +877,8 @@ async function renderNode(node, options) {
787
877
  throw new Error(`Undefined variable: ${node.name}`);
788
878
  case "preserve":
789
879
  return `{{ ${node.name} }}`;
880
+ case "asciidoc-literal":
881
+ return `{${node.name}}`;
790
882
  case "empty":
791
883
  default:
792
884
  return "";
@@ -806,7 +898,7 @@ async function renderNode(node, options) {
806
898
  case "comment":
807
899
  return "";
808
900
  case "if": {
809
- if (options.undefinedBehavior === "preserve" && options.undefinedConditions !== "falsy") {
901
+ if ((options.undefinedBehavior === "preserve" || options.undefinedBehavior === "asciidoc-literal") && options.undefinedConditions !== "falsy") {
810
902
  const undefinedRefs = findUndefinedRefs(node.condition, context);
811
903
  if (undefinedRefs.length > 0) {
812
904
  return ifNodeToSource(node);
@@ -866,7 +958,10 @@ async function renderNode(node, options) {
866
958
  undefinedConditions: options.undefinedConditions
867
959
  });
868
960
  } catch (error) {
869
- if (options.undefinedBehavior === "preserve") {
961
+ if (error instanceof Error && error.name === "IncludeContainmentError") {
962
+ throw error;
963
+ }
964
+ if (options.undefinedBehavior === "preserve" || options.undefinedBehavior === "asciidoc-literal") {
870
965
  return `{% include "${node.path}" %}`;
871
966
  }
872
967
  const message = error instanceof Error ? error.message : String(error);
@@ -889,11 +984,14 @@ async function renderNode(node, options) {
889
984
  const newOffset = node.isRelative ? parentOffset + node.offset : node.offset;
890
985
  const previousOffset = parentOffset;
891
986
  context.set("_levelOffset", newOffset);
987
+ const previousFence = context.get("_levelOffsetFence") ?? null;
988
+ context.set("_levelOffsetFence", null);
892
989
  try {
893
990
  const result = await renderNodes(node.body, options);
894
991
  return result;
895
992
  } finally {
896
993
  context.set("_levelOffset", previousOffset);
994
+ context.set("_levelOffsetFence", previousFence);
897
995
  }
898
996
  }
899
997
  default:
@@ -994,9 +1092,11 @@ var FileSystemLoader = class {
994
1092
  /**
995
1093
  * Create a filesystem loader
996
1094
  * @param basePath - Base directory for resolving relative paths
1095
+ * @param options - See {@link FileSystemLoaderOptions}
997
1096
  */
998
- constructor(basePath = process.cwd()) {
1097
+ constructor(basePath = process.cwd(), options = {}) {
999
1098
  this.basePath = basePath;
1099
+ this.root = options.root;
1000
1100
  }
1001
1101
  /**
1002
1102
  * Load a file from the filesystem
@@ -1009,6 +1109,41 @@ var FileSystemLoader = class {
1009
1109
  const pathModule = await import("path");
1010
1110
  const resolvedBasePath = basePath || this.basePath;
1011
1111
  const resolvedPath = pathModule.isAbsolute(path) ? path : pathModule.resolve(resolvedBasePath, path);
1112
+ if (this.root !== void 0) {
1113
+ const refuse = (detail) => {
1114
+ const err = new Error(`Refusing include outside the include root: ${detail}`);
1115
+ err.name = "IncludeContainmentError";
1116
+ throw err;
1117
+ };
1118
+ if (this.realRoot === void 0) {
1119
+ try {
1120
+ this.realRoot = await fs.realpath(this.root);
1121
+ } catch (error) {
1122
+ const message = error instanceof Error ? error.message : String(error);
1123
+ refuse(`include root ${this.root} does not resolve (${message})`);
1124
+ }
1125
+ }
1126
+ const lexical = pathModule.resolve(resolvedPath);
1127
+ if (lexical !== this.realRoot && !lexical.startsWith(this.realRoot + pathModule.sep) && lexical !== this.root && !lexical.startsWith(pathModule.resolve(this.root) + pathModule.sep)) {
1128
+ refuse(`"${path}" resolves to ${lexical}, which is not inside ${this.realRoot}`);
1129
+ }
1130
+ let realTarget;
1131
+ try {
1132
+ realTarget = await fs.realpath(resolvedPath);
1133
+ } catch (error) {
1134
+ const message = error instanceof Error ? error.message : String(error);
1135
+ throw new Error(`Failed to load ${resolvedPath}: ${message}`);
1136
+ }
1137
+ if (realTarget !== this.realRoot && !realTarget.startsWith(this.realRoot + pathModule.sep)) {
1138
+ refuse(`"${path}" resolves to ${realTarget}, which is not inside ${this.realRoot}`);
1139
+ }
1140
+ try {
1141
+ return await fs.readFile(realTarget, "utf-8");
1142
+ } catch (error) {
1143
+ const message = error instanceof Error ? error.message : String(error);
1144
+ throw new Error(`Failed to load ${resolvedPath}: ${message}`);
1145
+ }
1146
+ }
1012
1147
  try {
1013
1148
  return await fs.readFile(resolvedPath, "utf-8");
1014
1149
  } catch (error) {
@@ -1020,7 +1155,10 @@ var FileSystemLoader = class {
1020
1155
 
1021
1156
  // src/cli.ts
1022
1157
  var program = new Command();
1023
- program.name("minja").description("Minimal, secure Jinja2/Nunjucks subset for documentation preprocessing").version("0.1.0").argument("[template]", "Template file to render (or read from stdin)").option("-c, --context <file>", "Context file (JSON or YAML)").option("-o, --output <file>", "Output file (default: stdout)").option("-d, --max-depth <number>", "Maximum include depth", "10").option("-t, --timeout <ms>", "Rendering timeout in milliseconds", "5000").option("-v, --vars <json>", "Inline context variables as JSON").action(async (templatePath, options) => {
1158
+ program.name("minja").description("Minimal, secure Jinja2/Nunjucks subset for documentation preprocessing").version("0.1.0").argument("[template]", "Template file to render (or read from stdin)").option("-c, --context <file>", "Context file (JSON or YAML)").option("-o, --output <file>", "Output file (default: stdout)").option("-d, --max-depth <number>", "Maximum include depth", "10").option("-t, --timeout <ms>", "Rendering timeout in milliseconds", "5000").option("-v, --vars <json>", "Inline context variables as JSON").option(
1159
+ "-r, --include-root <dir>",
1160
+ "Refuse {% include %} targets that resolve (after symlinks) outside this directory"
1161
+ ).action(async (templatePath, options) => {
1024
1162
  try {
1025
1163
  let template;
1026
1164
  let baseDir = process.cwd();
@@ -1047,7 +1185,10 @@ program.name("minja").description("Minimal, secure Jinja2/Nunjucks subset for do
1047
1185
  const inlineVars = JSON.parse(options.vars);
1048
1186
  context = { ...context, ...inlineVars };
1049
1187
  }
1050
- const loader = new FileSystemLoader(baseDir);
1188
+ const loader = new FileSystemLoader(
1189
+ baseDir,
1190
+ options.includeRoot ? { root: resolve(options.includeRoot) } : {}
1191
+ );
1051
1192
  const result = await render(template, {
1052
1193
  loader,
1053
1194
  basePath: baseDir,
package/dist/browser.d.ts CHANGED
@@ -8,4 +8,5 @@ export { Context } from './context.js';
8
8
  export { FetchLoader } from './loader-fetch.js';
9
9
  export { MemoryLoader } from './loader-memory.js';
10
10
  export type { ASTNode, TextNode, VariableNode, SetNode, IfNode, IncludeNode, CommentNode, Expression, LiteralExpression, VariableExpression, BinaryExpression, UnaryExpression, RenderOptions, Loader, IContext, ParseResult, ParseError, } from './types.js';
11
+ export { includeDirectiveRe, scanIncludes, variableRe, directiveTagRe, commentRe, rawBlockRe } from './scan.js';
11
12
  //# sourceMappingURL=browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,YAAY,EAEV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EAGX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,YAAY,EAEV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EAGX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA"}
package/dist/browser.js CHANGED
@@ -7,4 +7,5 @@ export { parseExpression, evaluateExpression } from './evaluator.js';
7
7
  export { Context } from './context.js';
8
8
  export { FetchLoader } from './loader-fetch.js';
9
9
  export { MemoryLoader } from './loader-memory.js';
10
+ export { includeDirectiveRe, scanIncludes, variableRe, directiveTagRe, commentRe, rawBlockRe } from './scan.js';
10
11
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AA0BjD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA"}
package/dist/cli.js CHANGED
@@ -18,6 +18,7 @@ program
18
18
  .option('-d, --max-depth <number>', 'Maximum include depth', '10')
19
19
  .option('-t, --timeout <ms>', 'Rendering timeout in milliseconds', '5000')
20
20
  .option('-v, --vars <json>', 'Inline context variables as JSON')
21
+ .option('-r, --include-root <dir>', 'Refuse {% include %} targets that resolve (after symlinks) outside this directory')
21
22
  .action(async (templatePath, options) => {
22
23
  try {
23
24
  // Read template from file or stdin
@@ -53,7 +54,7 @@ program
53
54
  context = { ...context, ...inlineVars };
54
55
  }
55
56
  // Render template
56
- const loader = new FileSystemLoader(baseDir);
57
+ const loader = new FileSystemLoader(baseDir, options.includeRoot ? { root: resolve(options.includeRoot) } : {});
57
58
  const result = await render(template, {
58
59
  loader,
59
60
  basePath: baseDir,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -14,5 +14,7 @@ export { parse } from './parser.js';
14
14
  export { parseExpression, evaluateExpression } from './evaluator.js';
15
15
  export { Context, type ContextOptions } from './context.js';
16
16
  export { FetchLoader, FileSystemLoader, MemoryLoader } from './loader.js';
17
+ export type { FileSystemLoaderOptions } from './loader.js';
18
+ export { includeDirectiveRe, scanIncludes, variableRe, directiveTagRe, commentRe, rawBlockRe } from './scan.js';
17
19
  export type { ASTNode, TextNode, VariableNode, SetNode, IfNode, IncludeNode, CommentNode, Expression, LiteralExpression, VariableExpression, BinaryExpression, UnaryExpression, RenderOptions, Loader, IContext, ParseResult, ParseError, } from './types.js';
18
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEzE,YAAY,EAEV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EAGX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACzE,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE/G,YAAY,EAEV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EAGX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -14,4 +14,5 @@ export { parse } from './parser.js';
14
14
  export { parseExpression, evaluateExpression } from './evaluator.js';
15
15
  export { Context } from './context.js';
16
16
  export { FetchLoader, FileSystemLoader, MemoryLoader } from './loader.js';
17
+ export { includeDirectiveRe, scanIncludes, variableRe, directiveTagRe, commentRe, rawBlockRe } from './scan.js';
17
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAuB,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAuB,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEzE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA"}