@fedify/uri-template 2.0.0-pr.475.1 → 2.3.0-dev.1137

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,24 +1,12 @@
1
1
  {
2
2
  "name": "@fedify/uri-template",
3
- "version": "2.0.0-pr.475.1",
4
- "description": "URI Template (RFC 6570) utilities for Fedify",
5
- "keywords": [
6
- "Fedify",
7
- "URI",
8
- "template",
9
- "RFC6570"
10
- ],
11
- "author": {
12
- "name": "Lee ByeongJun",
13
- "email": "lbj199874@gmail.com"
14
- },
3
+ "version": "2.3.0-dev.1137+53a1f26d",
15
4
  "homepage": "https://fedify.dev/",
16
5
  "repository": {
17
6
  "type": "git",
18
7
  "url": "git+https://github.com/fedify-dev/fedify.git",
19
8
  "directory": "packages/uri-template"
20
9
  },
21
- "license": "MIT",
22
10
  "bugs": {
23
11
  "url": "https://github.com/fedify-dev/fedify/issues"
24
12
  },
@@ -26,35 +14,60 @@
26
14
  "https://opencollective.com/fedify",
27
15
  "https://github.com/sponsors/dahlia"
28
16
  ],
17
+ "engines": {
18
+ "deno": ">=2.0.0",
19
+ "node": ">=22.0.0",
20
+ "bun": ">=1.1.0"
21
+ },
22
+ "description": "RFC 6570 URI Template expansion and round-trip pattern matching",
29
23
  "type": "module",
30
- "module": "./dist/index.js",
31
- "main": "./dist/index.cjs",
32
- "types": "./dist/index.d.ts",
24
+ "main": "./dist/mod.cjs",
25
+ "module": "./dist/mod.js",
26
+ "types": "./dist/mod.d.ts",
33
27
  "exports": {
34
28
  ".": {
35
- "types": {
36
- "require": "./dist/index.d.cts",
37
- "default": "./dist/index.d.ts"
29
+ "require": {
30
+ "types": "./dist/mod.d.cts",
31
+ "default": "./dist/mod.cjs"
38
32
  },
39
- "default": {
40
- "require": "./dist/index.cjs",
41
- "default": "./dist/index.js"
33
+ "import": {
34
+ "types": "./dist/mod.d.ts",
35
+ "default": "./dist/mod.js"
42
36
  }
43
37
  },
44
38
  "./package.json": "./package.json"
45
39
  },
46
40
  "files": [
47
- "dist/",
48
- "package.json"
41
+ "dist",
42
+ "package.json",
43
+ "README.md"
49
44
  ],
45
+ "keywords": [
46
+ "Fedify",
47
+ "URI Template",
48
+ "RFC 6570",
49
+ "ActivityPub",
50
+ "Fediverse"
51
+ ],
52
+ "author": {
53
+ "name": "Chanhaeng Lee",
54
+ "email": "2chanhaeng@gmail.com",
55
+ "url": "https://chomu.dev/"
56
+ },
57
+ "license": "MIT",
50
58
  "devDependencies": {
51
59
  "@types/node": "^22.17.0",
52
- "tsdown": "^0.12.9",
53
- "typescript": "^5.9.3"
60
+ "tsdown": "^0.22.0",
61
+ "typescript": "^6.0.0",
62
+ "@fedify/fixture": "^2.0.0"
54
63
  },
64
+ "dependencies": {},
65
+ "sideEffects": false,
55
66
  "scripts": {
56
- "build": "deno task codegen && tsdown",
57
- "prepublish": "pnpm run build",
58
- "test": "tsdown && node --experimental-transform-types --test"
67
+ "build:self": "tsdown",
68
+ "build": "pnpm --filter @fedify/uri-template... run build:self",
69
+ "prepublish": "pnpm build",
70
+ "test:bun": "bun test src/",
71
+ "test": "cd src && node --experimental-transform-types --test"
59
72
  }
60
73
  }
@@ -1,30 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
-
23
- //#endregion
24
-
25
- Object.defineProperty(exports, '__toESM', {
26
- enumerable: true,
27
- get: function () {
28
- return __toESM;
29
- }
30
- });
package/dist/ast.d.cts DELETED
@@ -1,39 +0,0 @@
1
- //#region src/ast.d.ts
2
- /**
3
- * RFC 6570 operator set. Keep in sync with {@link OperatorSpec} in spec.ts.
4
- * The operator controls separators, first-char prefix, and reserved char handling.
5
- */
6
- type Operator = "" | "+" | "#" | "." | "/" | ";" | "?" | "&";
7
- /**
8
- * A variable specification inside an expression
9
- * - `explode` (`*`) and `prefix` (`:n`) modifies are Level 4 features.
10
- * - Parser guarantees: if `prefix` is present, it is a positive integer.
11
- */
12
- interface VarSpec {
13
- name: string;
14
- explode: boolean;
15
- prefix?: number;
16
- }
17
- type Node = Literal | Expression;
18
- interface Literal {
19
- kind: "literal";
20
- value: string;
21
- start?: number;
22
- end?: number;
23
- }
24
- interface Expression {
25
- kind: "expression";
26
- op: Operator;
27
- vars: VarSpec[];
28
- start?: number;
29
- end?: number;
30
- }
31
- /**
32
- * Template AST root. Expansion and matching both consume this structure.
33
- * @note Literals are kept as-is to avoid re-encoding surprises.
34
- */
35
- interface TemplateAst {
36
- nodes: Node[];
37
- }
38
- //#endregion
39
- export { Expression, Literal, Node, Operator, TemplateAst, VarSpec };
package/dist/ast.d.ts DELETED
@@ -1,39 +0,0 @@
1
- //#region src/ast.d.ts
2
- /**
3
- * RFC 6570 operator set. Keep in sync with {@link OperatorSpec} in spec.ts.
4
- * The operator controls separators, first-char prefix, and reserved char handling.
5
- */
6
- type Operator = "" | "+" | "#" | "." | "/" | ";" | "?" | "&";
7
- /**
8
- * A variable specification inside an expression
9
- * - `explode` (`*`) and `prefix` (`:n`) modifies are Level 4 features.
10
- * - Parser guarantees: if `prefix` is present, it is a positive integer.
11
- */
12
- interface VarSpec {
13
- name: string;
14
- explode: boolean;
15
- prefix?: number;
16
- }
17
- type Node = Literal | Expression;
18
- interface Literal {
19
- kind: "literal";
20
- value: string;
21
- start?: number;
22
- end?: number;
23
- }
24
- interface Expression {
25
- kind: "expression";
26
- op: Operator;
27
- vars: VarSpec[];
28
- start?: number;
29
- end?: number;
30
- }
31
- /**
32
- * Template AST root. Expansion and matching both consume this structure.
33
- * @note Literals are kept as-is to avoid re-encoding surprises.
34
- */
35
- interface TemplateAst {
36
- nodes: Node[];
37
- }
38
- //#endregion
39
- export { Expression, Literal, Node, Operator, TemplateAst, VarSpec };
package/dist/compile.cjs DELETED
@@ -1,30 +0,0 @@
1
- const require_expand = require('./expand.cjs');
2
- const require_match = require('./match.cjs');
3
- const require_parser = require('./parser.cjs');
4
-
5
- //#region src/compile.ts
6
- /**
7
- * Compile a template string once.
8
- * Returns a handle with:
9
- * - `ast()` -> the parsed AST (for diagnostics/introspection)
10
- * - `expand()` -> RFC 6570 expansion (L1–L4)
11
- * - `match()` -> symmetric pattern matching
12
- *
13
- * Rationale:
14
- * Compilation isolates parsing cost and allows future VM/bytecode backends
15
- * to optimize hot routes without changing the API.
16
- */
17
- function compile(template) {
18
- const ast = require_parser.parse(template);
19
- return {
20
- ast: () => ast,
21
- expand: (vars) => require_expand.expand(ast, vars),
22
- match: (url, mo) => {
23
- const result = require_match.match(ast, url, mo);
24
- return result ? { vars: result.vars } : null;
25
- }
26
- };
27
- }
28
-
29
- //#endregion
30
- exports.compile = compile;
@@ -1,80 +0,0 @@
1
- import { TemplateAst } from "./ast.cjs";
2
- import { Vars } from "./expand.cjs";
3
- import { EncodingPolicy, MatchOptions } from "./match.cjs";
4
-
5
- //#region src/compile.d.ts
6
-
7
- /**
8
- * Options that control how a compiled template behaves during matching.
9
- *
10
- * ### encoding
11
- * Determines how percent-encoded sequences are handled.
12
- *
13
- * ### strict
14
- * If true (default), malformed percent triplets (e.g. "%GZ" or lone "%")
15
- * cause matching to fail immediately.
16
- * Disabling strict mode may allow more lenient parsing but can lead to ambiguity.
17
- */
18
- interface CompileOptions {
19
- encoding?: EncodingPolicy;
20
- strict?: boolean;
21
- }
22
- /**
23
- * A compiled URI template that can efficiently expand and match URLs.
24
- *
25
- * @typeParam V - The type of variables expected by this template
26
- *
27
- * @example
28
- * ```typescript
29
- * const t = compile("{+path}/here");
30
- * const url = t.expand({ path: "/foo/bar" }); // "/foo/bar/here"
31
- * const match = t.match("/foo/bar/here"); // { vars: { path: "/foo/bar" } }
32
- * ```
33
- *
34
- * @example
35
- * ```typescript
36
- * const t = compile("/repos{/owner,repo}{?q,lang}");
37
- * const url = t.expand({ owner: "alice", repo: "hello/world", q: "a b", lang: "en" });
38
- * // "/repos/alice/hello%2Fworld?q=a%20b&lang=en"
39
- * ```
40
- */
41
- interface CompiledTemplate<V = Record<string, unknown>> {
42
- /**
43
- * Get the parsed AST of this template.
44
- * Useful for diagnostics and introspection.
45
- *
46
- * @returns The parsed template AST
47
- */
48
- ast(): TemplateAst;
49
- /**
50
- * Expand the template with the given variables according to RFC 6570.
51
- *
52
- * @param vars - Variables to substitute into the template
53
- * @returns The expanded URL string
54
- */
55
- expand(vars: V & Vars): string;
56
- /**
57
- * Match a URL against this template and extract variables.
58
- *
59
- * @param url - The URL to match against the template
60
- * @param opts - Optional matching options
61
- * @returns An object with extracted variables if matched, null otherwise
62
- */
63
- match(url: string, opts?: MatchOptions): null | {
64
- vars: V;
65
- };
66
- }
67
- /**
68
- * Compile a template string once.
69
- * Returns a handle with:
70
- * - `ast()` -> the parsed AST (for diagnostics/introspection)
71
- * - `expand()` -> RFC 6570 expansion (L1–L4)
72
- * - `match()` -> symmetric pattern matching
73
- *
74
- * Rationale:
75
- * Compilation isolates parsing cost and allows future VM/bytecode backends
76
- * to optimize hot routes without changing the API.
77
- */
78
- declare function compile<V = Record<string, unknown>>(template: string): CompiledTemplate<V>;
79
- //#endregion
80
- export { CompileOptions, CompiledTemplate, compile };
package/dist/compile.d.ts DELETED
@@ -1,80 +0,0 @@
1
- import { TemplateAst } from "./ast.js";
2
- import { Vars } from "./expand.js";
3
- import { EncodingPolicy, MatchOptions } from "./match.js";
4
-
5
- //#region src/compile.d.ts
6
-
7
- /**
8
- * Options that control how a compiled template behaves during matching.
9
- *
10
- * ### encoding
11
- * Determines how percent-encoded sequences are handled.
12
- *
13
- * ### strict
14
- * If true (default), malformed percent triplets (e.g. "%GZ" or lone "%")
15
- * cause matching to fail immediately.
16
- * Disabling strict mode may allow more lenient parsing but can lead to ambiguity.
17
- */
18
- interface CompileOptions {
19
- encoding?: EncodingPolicy;
20
- strict?: boolean;
21
- }
22
- /**
23
- * A compiled URI template that can efficiently expand and match URLs.
24
- *
25
- * @typeParam V - The type of variables expected by this template
26
- *
27
- * @example
28
- * ```typescript
29
- * const t = compile("{+path}/here");
30
- * const url = t.expand({ path: "/foo/bar" }); // "/foo/bar/here"
31
- * const match = t.match("/foo/bar/here"); // { vars: { path: "/foo/bar" } }
32
- * ```
33
- *
34
- * @example
35
- * ```typescript
36
- * const t = compile("/repos{/owner,repo}{?q,lang}");
37
- * const url = t.expand({ owner: "alice", repo: "hello/world", q: "a b", lang: "en" });
38
- * // "/repos/alice/hello%2Fworld?q=a%20b&lang=en"
39
- * ```
40
- */
41
- interface CompiledTemplate<V = Record<string, unknown>> {
42
- /**
43
- * Get the parsed AST of this template.
44
- * Useful for diagnostics and introspection.
45
- *
46
- * @returns The parsed template AST
47
- */
48
- ast(): TemplateAst;
49
- /**
50
- * Expand the template with the given variables according to RFC 6570.
51
- *
52
- * @param vars - Variables to substitute into the template
53
- * @returns The expanded URL string
54
- */
55
- expand(vars: V & Vars): string;
56
- /**
57
- * Match a URL against this template and extract variables.
58
- *
59
- * @param url - The URL to match against the template
60
- * @param opts - Optional matching options
61
- * @returns An object with extracted variables if matched, null otherwise
62
- */
63
- match(url: string, opts?: MatchOptions): null | {
64
- vars: V;
65
- };
66
- }
67
- /**
68
- * Compile a template string once.
69
- * Returns a handle with:
70
- * - `ast()` -> the parsed AST (for diagnostics/introspection)
71
- * - `expand()` -> RFC 6570 expansion (L1–L4)
72
- * - `match()` -> symmetric pattern matching
73
- *
74
- * Rationale:
75
- * Compilation isolates parsing cost and allows future VM/bytecode backends
76
- * to optimize hot routes without changing the API.
77
- */
78
- declare function compile<V = Record<string, unknown>>(template: string): CompiledTemplate<V>;
79
- //#endregion
80
- export { CompileOptions, CompiledTemplate, compile };
package/dist/compile.js DELETED
@@ -1,30 +0,0 @@
1
- import { expand } from "./expand.js";
2
- import { match } from "./match.js";
3
- import { parse } from "./parser.js";
4
-
5
- //#region src/compile.ts
6
- /**
7
- * Compile a template string once.
8
- * Returns a handle with:
9
- * - `ast()` -> the parsed AST (for diagnostics/introspection)
10
- * - `expand()` -> RFC 6570 expansion (L1–L4)
11
- * - `match()` -> symmetric pattern matching
12
- *
13
- * Rationale:
14
- * Compilation isolates parsing cost and allows future VM/bytecode backends
15
- * to optimize hot routes without changing the API.
16
- */
17
- function compile(template) {
18
- const ast = parse(template);
19
- return {
20
- ast: () => ast,
21
- expand: (vars) => expand(ast, vars),
22
- match: (url, mo) => {
23
- const result = match(ast, url, mo);
24
- return result ? { vars: result.vars } : null;
25
- }
26
- };
27
- }
28
-
29
- //#endregion
30
- export { compile };
package/dist/error.cjs DELETED
@@ -1,29 +0,0 @@
1
-
2
- //#region src/error.ts
3
- /**
4
- * Error thrown when parsing an invalid RFC 6570 URI template.
5
- */
6
- var ParseError = class ParseError extends Error {
7
- /**
8
- * The error name, always "RFC6570ParseError".
9
- */
10
- name = "RFC6570ParseError";
11
- /**
12
- * The index in the template string where the error occurred.
13
- */
14
- index;
15
- /**
16
- * Create a new ParseError.
17
- *
18
- * @param message - The error message
19
- * @param index - The index in the template string where the error occurred
20
- */
21
- constructor(message, index) {
22
- super(message);
23
- this.index = index;
24
- Object.setPrototypeOf(this, ParseError.prototype);
25
- }
26
- };
27
-
28
- //#endregion
29
- exports.ParseError = ParseError;
package/dist/error.js DELETED
@@ -1,28 +0,0 @@
1
- //#region src/error.ts
2
- /**
3
- * Error thrown when parsing an invalid RFC 6570 URI template.
4
- */
5
- var ParseError = class ParseError extends Error {
6
- /**
7
- * The error name, always "RFC6570ParseError".
8
- */
9
- name = "RFC6570ParseError";
10
- /**
11
- * The index in the template string where the error occurred.
12
- */
13
- index;
14
- /**
15
- * Create a new ParseError.
16
- *
17
- * @param message - The error message
18
- * @param index - The index in the template string where the error occurred
19
- */
20
- constructor(message, index) {
21
- super(message);
22
- this.index = index;
23
- Object.setPrototypeOf(this, ParseError.prototype);
24
- }
25
- };
26
-
27
- //#endregion
28
- export { ParseError };
package/dist/expand.cjs DELETED
@@ -1,94 +0,0 @@
1
- const require_spec = require('./spec.cjs');
2
-
3
- //#region src/expand.ts
4
- function emitNamed(spec, name, raw) {
5
- return spec.named ? raw === "" && spec.ifEmpty === "empty" ? `${name}${spec.kvSep}` : `${name}${spec.kvSep}${raw}` : raw;
6
- }
7
- function expandVar(op, v, value) {
8
- const spec = require_spec.OP[op];
9
- const enc = (str) => require_spec.encodeComponentIdempotent(str, spec.allowReserved, spec.reservedSet);
10
- if (value === void 0 || value === null) return [];
11
- if (Array.isArray(value)) {
12
- const items = value.filter((x) => x !== void 0).map((x) => enc(String(x)));
13
- if (items.length === 0) {
14
- if (spec.first === ".") return [""];
15
- if (spec.named && spec.ifEmpty === "nameOnly") return [v.name];
16
- if (spec.named && spec.ifEmpty === "empty") return [`${v.name}${spec.kvSep}`];
17
- return [];
18
- }
19
- if (v.explode) return items.map((it) => emitNamed(spec, v.name, it));
20
- return [emitNamed(spec, v.name, items.join(","))];
21
- }
22
- if (typeof value === "object" && value && !Array.isArray(value)) {
23
- const entries = Object.entries(value).filter(([, vv]) => vv !== void 0);
24
- if (entries.length === 0) {
25
- if (spec.named && spec.ifEmpty === "nameOnly") return [v.name];
26
- if (spec.named && spec.ifEmpty === "empty") return [`${v.name}${spec.kvSep}`];
27
- return [];
28
- }
29
- if (v.explode) return entries.map(([k, vv]) => `${enc(k)}${spec.kvSep}${enc(String(vv))}`);
30
- const joined = entries.map(([k, vv]) => `${enc(k)},${enc(String(vv))}`).join(",");
31
- return [emitNamed(spec, v.name, joined)];
32
- }
33
- let s = String(value);
34
- if (v.prefix !== void 0) s = s.slice(0, v.prefix);
35
- const e = enc(s);
36
- if (e.length === 0) {
37
- if (spec.first === ".") return [""];
38
- if (spec.named && spec.ifEmpty === "nameOnly") return [v.name];
39
- if (spec.named && spec.ifEmpty === "empty") return [`${v.name}${spec.kvSep}`];
40
- return [];
41
- }
42
- return [emitNamed(spec, v.name, e)];
43
- }
44
- /**
45
- * Expand a parsed template with variables according to RFC 6570 (Level 1-4).
46
- *
47
- * @param ast - The parsed template AST to expand
48
- * @param vars - Variables to substitute into the template
49
- * @returns The expanded URL string
50
- *
51
- * @remarks
52
- * - Idempotent percent encoding (existing `%XX` kept)
53
- * - Operator-specific empty/undefined rules:
54
- * - ";" empty -> `nameOnly` (";x")
55
- * - "?" "&" empty -> "key=" ("?x=")
56
- * - `undefined` -> `omit` (all operators)
57
- * - Label "." emits the dot even if empty ("X{.y}" with y="" -> "X.")
58
- *
59
- * @example
60
- * ```typescript
61
- * import { parse } from "./parser.ts";
62
- * import { expand } from "./expand.ts";
63
- *
64
- * const ast = parse("{+x,hello,y}");
65
- * const url = expand(ast, { x: "1024", hello: "Hello World!", y: "768" });
66
- * // Returns: "1024,Hello%20World!,768"
67
- * ```
68
- *
69
- * @example
70
- * ```typescript
71
- * import { parse } from "./parser.ts";
72
- * import { expand } from "./expand.ts";
73
- *
74
- * const ast = parse("{+path}/here");
75
- * const url = expand(ast, { path: "/foo/bar" });
76
- * // Returns: "/foo/bar/here"
77
- * ```
78
- */
79
- function expand(ast, vars) {
80
- let out = "";
81
- for (const node of ast.nodes) if (node.kind === "literal") out += node.value;
82
- else {
83
- const spec = require_spec.OP[node.op];
84
- const pieces = [];
85
- for (const v of node.vars) pieces.push(...expandVar(node.op, v, vars[v.name]));
86
- if (pieces.length === 0) continue;
87
- if (spec.first) out += spec.first;
88
- out += pieces.join(spec.itemSep);
89
- }
90
- return out;
91
- }
92
-
93
- //#endregion
94
- exports.expand = expand;
package/dist/expand.d.cts DELETED
@@ -1,72 +0,0 @@
1
- import { TemplateAst } from "./ast.cjs";
2
-
3
- //#region src/expand.d.ts
4
-
5
- /**
6
- * A scalar value that can be used in template expansion.
7
- */
8
- type Scalar = string | number | boolean;
9
- /**
10
- * A list of scalar values that can be used in template expansion.
11
- */
12
- type List = (Scalar | undefined)[];
13
- /**
14
- * A map-like object with scalar values.
15
- */
16
- type MapLike = Record<string, Scalar | undefined>;
17
- /**
18
- * Valid value types for template variables.
19
- */
20
- type VarsValue = Scalar | List | MapLike | undefined;
21
- /**
22
- * A collection of variables for template expansion.
23
- * Maps variable names to their values.
24
- *
25
- * @example
26
- * ```typescript
27
- * const vars: Vars = {
28
- * var: "value",
29
- * list: ["red", "green", "blue"],
30
- * keys: { semi: ";", dot: ".", comma: "," }
31
- * };
32
- * ```
33
- */
34
- type Vars = Record<string, VarsValue>;
35
- /**
36
- * Expand a parsed template with variables according to RFC 6570 (Level 1-4).
37
- *
38
- * @param ast - The parsed template AST to expand
39
- * @param vars - Variables to substitute into the template
40
- * @returns The expanded URL string
41
- *
42
- * @remarks
43
- * - Idempotent percent encoding (existing `%XX` kept)
44
- * - Operator-specific empty/undefined rules:
45
- * - ";" empty -> `nameOnly` (";x")
46
- * - "?" "&" empty -> "key=" ("?x=")
47
- * - `undefined` -> `omit` (all operators)
48
- * - Label "." emits the dot even if empty ("X{.y}" with y="" -> "X.")
49
- *
50
- * @example
51
- * ```typescript
52
- * import { parse } from "./parser.ts";
53
- * import { expand } from "./expand.ts";
54
- *
55
- * const ast = parse("{+x,hello,y}");
56
- * const url = expand(ast, { x: "1024", hello: "Hello World!", y: "768" });
57
- * // Returns: "1024,Hello%20World!,768"
58
- * ```
59
- *
60
- * @example
61
- * ```typescript
62
- * import { parse } from "./parser.ts";
63
- * import { expand } from "./expand.ts";
64
- *
65
- * const ast = parse("{+path}/here");
66
- * const url = expand(ast, { path: "/foo/bar" });
67
- * // Returns: "/foo/bar/here"
68
- * ```
69
- */
70
- declare function expand(ast: TemplateAst, vars: Vars): string;
71
- //#endregion
72
- export { Vars, expand };