@macroforge/mcp-server 0.1.42 → 0.1.50

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.
Files changed (71) hide show
  1. package/LICENSE +22 -0
  2. package/docs/BOOK.md +165 -0
  3. package/docs/api/api-overview.md +67 -48
  4. package/docs/api/expand-sync.md +88 -53
  5. package/docs/api/native-plugin.md +121 -71
  6. package/docs/api/position-mapper.md +115 -55
  7. package/docs/api/transform-sync.md +86 -60
  8. package/docs/builtin-macros/clone.md +0 -20
  9. package/docs/builtin-macros/debug.md +0 -23
  10. package/docs/builtin-macros/default.md +1 -40
  11. package/docs/builtin-macros/deserialize/example.md +8 -1416
  12. package/docs/builtin-macros/deserialize.md +8 -1416
  13. package/docs/builtin-macros/hash.md +0 -42
  14. package/docs/builtin-macros/macros-overview/detailed-documentation.md +13 -0
  15. package/docs/builtin-macros/macros-overview/enum-support.md +30 -0
  16. package/docs/builtin-macros/macros-overview/interface-support.md +28 -0
  17. package/docs/builtin-macros/macros-overview/overview.md +36 -0
  18. package/docs/builtin-macros/macros-overview/type-alias-support.md +62 -0
  19. package/docs/builtin-macros/macros-overview.md +171 -130
  20. package/docs/builtin-macros/ord.md +0 -25
  21. package/docs/builtin-macros/partial-eq.md +0 -84
  22. package/docs/builtin-macros/partial-ord.md +2 -32
  23. package/docs/builtin-macros/serialize.md +2 -62
  24. package/docs/concepts/architecture.md +125 -48
  25. package/docs/concepts/derive-system/built-in-vs-custom-macros.md +13 -0
  26. package/docs/concepts/derive-system/overview.md +200 -0
  27. package/docs/concepts/derive-system.md +157 -104
  28. package/docs/concepts/how-macros-work.md +98 -47
  29. package/docs/custom-macros/custom-overview.md +79 -57
  30. package/docs/custom-macros/rust-setup.md +138 -99
  31. package/docs/custom-macros/ts-macro-derive/accessing-field-data.md +40 -31
  32. package/docs/custom-macros/ts-macro-derive/adding-imports.md +14 -11
  33. package/docs/custom-macros/ts-macro-derive/attribute-options.md +20 -25
  34. package/docs/custom-macros/ts-macro-derive/complete-example.md +40 -38
  35. package/docs/custom-macros/ts-macro-derive/deriveinput-structure.md +49 -47
  36. package/docs/custom-macros/ts-macro-derive/function-signature.md +12 -0
  37. package/docs/custom-macros/ts-macro-derive/overview.md +9 -7
  38. package/docs/custom-macros/ts-macro-derive/parsing-input.md +20 -18
  39. package/docs/custom-macros/ts-macro-derive/returning-errors.md +15 -13
  40. package/docs/custom-macros/ts-macro-derive.md +322 -228
  41. package/docs/custom-macros/ts-quote/backtick-template-literals.md +19 -7
  42. package/docs/custom-macros/ts-quote/comments-and.md +56 -22
  43. package/docs/custom-macros/ts-quote/complete-example-json-derive-macro.md +89 -98
  44. package/docs/custom-macros/ts-quote/conditionals-ifif.md +35 -29
  45. package/docs/custom-macros/ts-quote/identifier-concatenation-content.md +30 -22
  46. package/docs/custom-macros/ts-quote/iteration-for.md +48 -40
  47. package/docs/custom-macros/ts-quote/local-constants-let.md +23 -21
  48. package/docs/custom-macros/ts-quote/match-expressions-match.md +46 -38
  49. package/docs/custom-macros/ts-quote/overview.md +5 -10
  50. package/docs/custom-macros/ts-quote/pattern-matching-iflet.md +39 -0
  51. package/docs/custom-macros/ts-quote/quick-reference.md +50 -129
  52. package/docs/custom-macros/ts-quote/side-effects-do.md +13 -78
  53. package/docs/custom-macros/ts-quote/string-interpolation-textexpr.md +36 -0
  54. package/docs/custom-macros/ts-quote/tsstream-injection-typescript.md +43 -35
  55. package/docs/custom-macros/ts-quote/while-loops-while.md +31 -23
  56. package/docs/custom-macros/ts-quote.md +800 -520
  57. package/docs/getting-started/first-macro.md +98 -71
  58. package/docs/getting-started/installation.md +109 -65
  59. package/docs/integration/cli.md +214 -105
  60. package/docs/integration/configuration.md +115 -72
  61. package/docs/integration/integration-overview.md +55 -18
  62. package/docs/integration/mcp-server.md +84 -43
  63. package/docs/integration/svelte-preprocessor.md +183 -126
  64. package/docs/integration/typescript-plugin.md +101 -53
  65. package/docs/integration/vite-plugin.md +116 -76
  66. package/docs/language-servers/ls-overview.md +37 -21
  67. package/docs/language-servers/svelte.md +69 -38
  68. package/docs/language-servers/zed.md +81 -44
  69. package/docs/roadmap/roadmap.md +75 -53
  70. package/docs/sections.json +1 -242
  71. package/package.json +27 -28
@@ -1,58 +1,66 @@
1
- ## Match Expressions: `{#match}`
1
+ ## Match Expressions: `{#match}`
2
2
 
3
3
  Use `match` for exhaustive pattern matching:
4
4
 
5
- ```rust
6
- enum Visibility { Public, Private, Protected }
7
- let visibility = Visibility::Public;
8
-
9
- let code = ts_template! {
10
- {#match visibility}
11
- {:case Visibility::Public}
12
- public
13
- {:case Visibility::Private}
14
- private
15
- {:case Visibility::Protected}
16
- protected
17
- {/match}
18
- field: string;
5
+ Rust
6
+
7
+ ```
8
+ enum Visibility { Public, Private, Protected }
9
+ let visibility = Visibility::Public;
10
+
11
+ let code = ts_template! {
12
+     {#match visibility}
13
+         {:case Visibility::Public}
14
+             public
15
+         {:case Visibility::Private}
16
+             private
17
+         {:case Visibility::Protected}
18
+             protected
19
+     {/match}
20
+     field: string;
19
21
  };
20
22
  ```
21
23
 
22
24
  **Generates:**
23
25
 
24
- ```typescript
25
- public field: string;
26
+ TypeScript
27
+
28
+ ```
29
+ public field: string;
26
30
  ```
27
31
 
28
32
  ### Match with Value Extraction
29
33
 
30
- ```rust
31
- let result: Result<i32, &str> = Ok(42);
34
+ Rust
32
35
 
33
- let code = ts_template! {
34
- const value = {#match result}
35
- {:case Ok(val)}
36
- @{val}
37
- {:case Err(msg)}
38
- throw new Error("@{msg}")
39
- {/match};
36
+ ```
37
+ let result: Result<i32, &str> = Ok(42);
38
+
39
+ let code = ts_template! {
40
+     const value = {#match result}
41
+         {:case Ok(val)}
42
+             @{val}
43
+         {:case Err(msg)}
44
+             throw new Error("@{msg}")
45
+     {/match};
40
46
  };
41
47
  ```
42
48
 
43
49
  ### Match with Wildcard
44
50
 
45
- ```rust
46
- let count = 5;
47
-
48
- let code = ts_template! {
49
- {#match count}
50
- {:case 0}
51
- console.log("none");
52
- {:case 1}
53
- console.log("one");
54
- {:case _}
55
- console.log("many");
56
- {/match}
51
+ Rust
52
+
53
+ ```
54
+ let count = 5;
55
+
56
+ let code = ts_template! {
57
+     {#match count}
58
+         {:case 0}
59
+             console.log("none");
60
+         {:case 1}
61
+             console.log("one");
62
+         {:case _}
63
+             console.log("many");
64
+     {/match}
57
65
  };
58
66
  ```
@@ -1,15 +1,10 @@
1
1
  # Template Syntax
2
2
 
3
- *The `macroforge_ts_quote` crate provides template-based code generation for TypeScript. The `ts_template!` macro uses Rust-inspired syntax for control flow and interpolation, making it easy to generate complex TypeScript code.*
3
+ The `macroforge_ts_quote` crate provides template-based code generation for TypeScript. The `ts_template!` macro uses Svelte + Rust-inspired syntax for control flow and interpolation, making it easy to generate complex TypeScript code.
4
4
 
5
5
  ## Available Macros
6
6
 
7
- | `ts_template!`
8
- | Any TypeScript code
9
- | General code generation
10
-
11
-
12
-
13
- | `body!`
14
- | Class body members
15
- | Methods and properties
7
+ | Macro | Output | Use Case |
8
+ | -------------- | ------------------- | ----------------------- |
9
+ | `ts_template!` | Any TypeScript code | General code generation |
10
+ | `body!` | Class body members | Methods and properties |
@@ -0,0 +1,39 @@
1
+ ## Pattern Matching: `{#if let}`
2
+
3
+ Use `if let` for pattern matching on `Option`, `Result`, or other Rust enums:
4
+
5
+ Rust
6
+
7
+ ```
8
+ let maybe_name: Option<&str> = Some("Alice");
9
+
10
+ let code = ts_template! {
11
+     {#if let Some(name) = maybe_name}
12
+         console.log("Hello, @{name}!");
13
+     {:else}
14
+         console.log("Hello, anonymous!");
15
+     {/if}
16
+ };
17
+ ```
18
+
19
+ **Generates:**
20
+
21
+ TypeScript
22
+
23
+ ```
24
+ console.log("Hello, Alice!");
25
+ ```
26
+
27
+ This is useful when working with optional values from your IR:
28
+
29
+ Rust
30
+
31
+ ```
32
+ let code = ts_template! {
33
+     {#if let Some(default_val) = field.default_value}
34
+         this.@{field.name} = @{default_val};
35
+     {:else}
36
+         this.@{field.name} = undefined;
37
+     {/if}
38
+ };
39
+ ```
@@ -1,131 +1,52 @@
1
1
  ## Quick Reference
2
2
 
3
- | `@&#123;expr&#125;`
4
- | Interpolate a Rust expression (adds space after)
5
-
6
-
7
-
8
- | `&#123;| content |&#125;`
9
- | Ident block: concatenates without spaces (e.g., <code
10
- >&#123;|get@&#123;name&#125;|&#125;</code
11
- >
12
- `getUser`)</td
13
- >
14
-
15
-
16
-
17
- <td>`&#123;> "comment" <&#125;`
18
- | Block comment: outputs `/* comment */` (string preserves
19
- whitespace)</td
20
- >
21
-
22
-
23
-
24
- <td>`&#123;>> "doc" <<&#125;`
25
- | Doc comment: outputs `/** doc */` (string preserves whitespace)</td
26
- >
27
-
28
-
29
-
30
- <td>`@@&#123;`
31
- | Escape for literal `@&#123;` (e.g.,
32
- `"@@&#123;foo&#125;"`
33
- → `@&#123;foo&#125;`)</td
34
- >
35
-
36
-
37
-
38
- <td>`"text @&#123;expr&#125;"`
39
- | String interpolation (auto-detected)
40
-
41
-
42
-
43
- | `"'^template $&#123;js&#125;^'"`
44
- | JS backtick template literal (outputs <code
45
- >`template $&#123;js&#125;`</code
46
- >)</td
47
- >
48
-
49
-
50
-
51
- <td>`&#123;#if cond&#125;...&#123;/if&#125;`
52
- | Conditional block
53
-
54
-
55
-
56
- | <code
57
- >&#123;#if cond&#125;...&#123;:else&#125;...&#123;/if&#125;</code
58
- ></td
59
- >
60
- <td>Conditional with else
61
-
62
-
63
-
64
- | <code
65
- >&#123;#if a&#125;...&#123;:else if
66
- b&#125;...&#123;:else&#125;...&#123;/if&#125;</code
67
- ></td
68
- >
69
- <td>Full if/else-if/else chain
70
-
71
-
72
-
73
- | <code
74
- >&#123;#if let pattern = expr&#125;...&#123;/if&#125;</code
75
- ></td
76
- >
77
- <td>Pattern matching if-let
78
-
79
-
80
-
81
- | <code
82
- >&#123;#match expr&#125;&#123;:case
83
- pattern&#125;...&#123;/match&#125;</code
84
- ></td
85
- >
86
- <td>Match expression with case arms
87
-
88
-
89
-
90
- | <code>&#123;#for item in list&#125;...&#123;/for&#125;</code
91
- ></td
92
- >
93
- <td>Iterate over a collection
94
-
95
-
96
-
97
- | `&#123;#while cond&#125;...&#123;/while&#125;`
98
- | While loop
99
-
100
-
101
-
102
- | <code
103
- >&#123;#while let pattern = expr&#125;...&#123;/while&#125;</code
104
- ></td
105
- >
106
- <td>While-let pattern matching loop
107
-
108
-
109
-
110
- | `&#123;$let name = expr&#125;`
111
- | Define a local constant
112
-
113
-
114
-
115
- | `&#123;$let mut name = expr&#125;`
116
- | Define a mutable local variable
117
-
118
-
119
-
120
- | `&#123;$do expr&#125;`
121
- | Execute a side-effectful expression
122
-
123
-
124
-
125
- | `&#123;$typescript stream&#125;`
126
- <td
127
- >Inject a TsStream, preserving its source and runtime_patches
128
- (imports)</td
129
- >
130
-
131
- **Note:** A single `@` not followed by `&#123;` passes through unchanged (e.g., `email@domain.com` works as expected).
3
+ | Syntax | Description |
4
+ | -------------------------------------------------------------- | ----------------------------------------------------------------------------- |
5
+ | `@{expr}` | Interpolate a Rust expression (adds space after) |
6
+ | `{&#124; content &#124;}` | Ident block: concatenates without spaces (e.g., `{&#124;get@{name}&#124;}` → `getUser`) |
7
+ | `{> "comment" <}` | Block comment: outputs `/* comment */` (string preserves whitespace) |
8
+ | `{>> "doc" <<}` | Doc comment: outputs `/** doc */` (string preserves whitespace) |
9
+ | `@@{` | Escape for literal `@{` (e.g., `"@@{foo}"` → `@{foo}`) |
10
+ | `"text @{expr}"` | String interpolation (auto-detected) |
11
+ | `"'^template ${js}^'"` | JS backtick template literal (outputs `` `template ${js}` ``) |
12
+ | `{#if cond}...{/if}` | Conditional block |
13
+ | `{#if cond}...{:else}...{/if}` | Conditional with else |
14
+ | `{#if a}...{:else if b}...{:else}...{/if}` | Full if/else-if/else chain |
15
+ | `{#if let pattern = expr}...{/if}` | Pattern matching if-let |
16
+ | `{#match expr}{:case pattern}...{/match}` | Match expression with case arms |
17
+ | `{#for item in list}...{/for}` | Iterate over a collection |
18
+ | `{#while cond}...{/while}` | While loop |
19
+ | `{#while let pattern = expr}...{/while}` | While-let pattern matching loop |
20
+ | `{$let name = expr}` | Define a local constant |
21
+ | `{$let mut name = expr}` | Define a mutable local variable |
22
+ | `{$do expr}` | Execute a side-effectful expression |
23
+ | `{$typescript stream}` | Inject a TsStream, preserving its source and runtime\_patches (imports) |
24
+
25
+ **Note:** A single `@` not followed by `{` passes through unchanged (e.g., `email@domain.com` works as expected).
26
+
27
+ ## Interpolation: `@{expr}`
28
+
29
+ Insert Rust expressions into the generated TypeScript:
30
+
31
+ Rust
32
+
33
+ ```
34
+ let class_name = "User";
35
+ let method = "toString";
36
+
37
+ let code = ts_template! {
38
+     @{class_name}.prototype.@{method} = function() {
39
+         return "User instance";
40
+     };
41
+ };
42
+ ```
43
+
44
+ **Generates:**
45
+
46
+ TypeScript
47
+
48
+ ```
49
+ User.prototype.toString = function () {
50
+   return "User instance";
51
+ };
52
+ ```
@@ -1,87 +1,22 @@
1
- ## Side Effects: `&#123;$do&#125;`
1
+ ## Side Effects: `{$do}`
2
2
 
3
3
  Execute an expression for its side effects without producing output. This is commonly used with mutable variables:
4
4
 
5
- ```rust
6
- let code = ts_template! {
7
- {$let mut results: Vec<String> = Vec::new()}
8
- {#for field in fields}
9
- {$do results.push(format!("this.{}", field))}
10
- {/for}
11
- return [@{results.join(", ")}];
12
- };
13
- ```
14
-
15
- Common uses for `&#123;$do&#125;`:
16
-
17
- - Incrementing counters: `&#123;$do i += 1&#125;`
18
-
19
- - Building collections: `&#123;$do vec.push(item)&#125;`
20
-
21
- - Setting flags: `&#123;$do found = true&#125;`
22
-
23
- - Any mutating operation
24
-
25
- <h2 id="typescript-injection">
26
- TsStream Injection: `&#123;$typescript&#125;`
27
- </h2>
28
-
29
- Inject another TsStream into your template, preserving both its source code and runtime patches (like imports added via `add_import()`):
30
-
31
- ```rust
32
- // Create a helper method with its own import
33
- let mut helper = body! {
34
- validateEmail(email: string): boolean {
35
- return Result.ok(true);
36
- }
37
- };
38
- helper.add_import("Result", "macroforge/utils");
5
+ Rust
39
6
 
40
- // Inject the helper into the main template
41
- let result = body! {
42
- {$typescript helper}
43
-
44
- process(data: Record<string, unknown>): void {
45
- // ...
46
- }
47
- };
48
- // result now includes helper's source AND its Result import
49
7
  ```
50
-
51
- This is essential for composing multiple macro outputs while preserving imports and patches:
52
-
53
- ```rust
54
- let extra_methods = if include_validation {
55
- Some(body! {
56
- validate(): boolean { return true; }
57
- })
58
- } else {
59
- None
8
+ let code = ts_template! {
9
+     {$let mut results: Vec<String> = Vec::new()}
10
+     {#for field in fields}
11
+         {$do results.push(format!("this.{}", field))}
12
+     {/for}
13
+     return [@{results.join(", ")}];
60
14
  };
61
-
62
- body! {
63
- mainMethod(): void {}
64
-
65
- {#if let Some(methods) = extra_methods}
66
- {$typescript methods}
67
- {/if}
68
- }
69
- ```
70
-
71
- ## Escape Syntax
72
-
73
- If you need a literal `@&#123;` in your output (not interpolation), use `@@&#123;`:
74
-
75
- ```rust
76
- ts_template! {
77
- // This outputs a literal @{foo}
78
- const example = "Use @@{foo} for templates";
79
- }
80
15
  ```
81
16
 
82
- **Generates:**
17
+ Common uses for `{$do}`:
83
18
 
84
- ```typescript
85
- // This outputs a literal @{foo}
86
- const example = "Use @{foo} for templates";
87
- ```
19
+ * Incrementing counters: `{$do i += 1}`
20
+ * Building collections: `{$do vec.push(item)}`
21
+ * Setting flags: `{$do found = true}`
22
+ * Any mutating operation
@@ -0,0 +1,36 @@
1
+ ## String Interpolation: `"text @{expr}"`
2
+
3
+ Interpolation works automatically inside string literals - no `format!()` needed:
4
+
5
+ Rust
6
+
7
+ ```
8
+ let name = "World";
9
+ let count = 42;
10
+
11
+ let code = ts_template! {
12
+     console.log("Hello @{name}!");
13
+     console.log("Count: @{count}, doubled: @{count * 2}");
14
+ };
15
+ ```
16
+
17
+ **Generates:**
18
+
19
+ TypeScript
20
+
21
+ ```
22
+ console.log("Hello World!");
23
+ console.log("Count: 42, doubled: 84");
24
+ ```
25
+
26
+ This also works with method calls and complex expressions:
27
+
28
+ Rust
29
+
30
+ ```
31
+ let field = "username";
32
+
33
+ let code = ts_template! {
34
+     throw new Error("Invalid @{field.to_uppercase()}");
35
+ };
36
+ ```
@@ -1,61 +1,69 @@
1
- ## TsStream Injection: `&#123;$typescript&#125;`
1
+ ## TsStream Injection: `{$typescript}`
2
2
 
3
3
  Inject another TsStream into your template, preserving both its source code and runtime patches (like imports added via `add_import()`):
4
4
 
5
- ```rust
6
- // Create a helper method with its own import
7
- let mut helper = body! {
8
- validateEmail(email: string): boolean {
9
- return Result.ok(true);
10
- }
5
+ Rust
6
+
7
+ ```
8
+ // Create a helper method with its own import
9
+ let mut helper = body! {
10
+     validateEmail(email: string): boolean {
11
+         return Result.ok(true);
12
+     }
11
13
  };
12
- helper.add_import("Result", "macroforge/utils");
14
+ helper.add_import("Result", "macroforge/utils");
13
15
 
14
- // Inject the helper into the main template
15
- let result = body! {
16
- {$typescript helper}
16
+ // Inject the helper into the main template
17
+ let result = body! {
18
+     {$typescript helper}
17
19
 
18
- process(data: Record<string, unknown>): void {
19
- // ...
20
- }
20
+     process(data: Record<string, unknown>): void {
21
+         // ...
22
+     }
21
23
  };
22
- // result now includes helper's source AND its Result import
24
+ // result now includes helper's source AND its Result import
23
25
  ```
24
26
 
25
27
  This is essential for composing multiple macro outputs while preserving imports and patches:
26
28
 
27
- ```rust
28
- let extra_methods = if include_validation {
29
- Some(body! {
30
- validate(): boolean { return true; }
31
- })
32
- } else {
33
- None
29
+ Rust
30
+
31
+ ```
32
+ let extra_methods = if include_validation {
33
+     Some(body! {
34
+         validate(): boolean { return true; }
35
+     })
36
+ } else {
37
+     None
34
38
  };
35
39
 
36
- body! {
37
- mainMethod(): void {}
40
+ body! {
41
+     mainMethod(): void {}
38
42
 
39
- {#if let Some(methods) = extra_methods}
40
- {$typescript methods}
41
- {/if}
43
+     {#if let Some(methods) = extra_methods}
44
+         {$typescript methods}
45
+     {/if}
42
46
  }
43
47
  ```
44
48
 
45
49
  ## Escape Syntax
46
50
 
47
- If you need a literal `@&#123;` in your output (not interpolation), use `@@&#123;`:
51
+ If you need a literal `@{` in your output (not interpolation), use `@@{`:
48
52
 
49
- ```rust
50
- ts_template! {
51
- // This outputs a literal @{foo}
52
- const example = "Use @@{foo} for templates";
53
+ Rust
54
+
55
+ ```
56
+ ts_template! {
57
+     // This outputs a literal @{foo}
58
+     const example = "Use @@{foo} for templates";
53
59
  }
54
60
  ```
55
61
 
56
62
  **Generates:**
57
63
 
58
- ```typescript
59
- // This outputs a literal @{foo}
60
- const example = "Use @{foo} for templates";
64
+ TypeScript
65
+
66
+ ```
67
+ // This outputs a literal @{foo}
68
+ const example = "Use @{foo} for templates";
61
69
  ```
@@ -1,37 +1,43 @@
1
- ## While Loops: `&#123;#while&#125;`
1
+ ## While Loops: `{#while}`
2
2
 
3
3
  Use `while` for loops that need to continue until a condition is false:
4
4
 
5
- ```rust
6
- let items = get_items();
7
- let mut idx = 0;
5
+ Rust
8
6
 
9
- let code = ts_template! {
10
- {$let mut i = 0}
11
- {#while i < items.len()}
12
- console.log("Item @{i}");
13
- {$do i += 1}
14
- {/while}
7
+ ```
8
+ let items = get_items();
9
+ let mut idx = 0;
10
+
11
+ let code = ts_template! {
12
+     {$let mut i = 0}
13
+     {#while i < items.len()}
14
+         console.log("Item @{i}");
15
+         {$do i += 1}
16
+     {/while}
15
17
  };
16
18
  ```
17
19
 
18
20
  ### While-Let Pattern Matching
19
21
 
20
- Use `while let` for iterating with pattern matching, similar to `if let`:
22
+ Use `while let` for iterating with pattern matching, similar to `if let`:
23
+
24
+ Rust
21
25
 
22
- ```rust
23
- let mut items = vec!["a", "b", "c"].into_iter();
26
+ ```
27
+ let mut items = vec!["a", "b", "c"].into_iter();
24
28
 
25
- let code = ts_template! {
26
- {#while let Some(item) = items.next()}
27
- console.log("@{item}");
28
- {/while}
29
+ let code = ts_template! {
30
+     {#while let Some(item) = items.next()}
31
+         console.log("@{item}");
32
+     {/while}
29
33
  };
30
34
  ```
31
35
 
32
36
  **Generates:**
33
37
 
34
- ```typescript
38
+ TypeScript
39
+
40
+ ```
35
41
  console.log("a");
36
42
  console.log("b");
37
43
  console.log("c");
@@ -39,10 +45,12 @@ console.log("c");
39
45
 
40
46
  This is especially useful when working with iterators or consuming optional values:
41
47
 
42
- ```rust
43
- let code = ts_template! {
44
- {#while let Some(next_field) = remaining_fields.pop()}
45
- result.@{next_field.name} = this.@{next_field.name};
46
- {/while}
48
+ Rust
49
+
50
+ ```
51
+ let code = ts_template! {
52
+     {#while let Some(next_field) = remaining_fields.pop()}
53
+         result.@{next_field.name} = this.@{next_field.name};
54
+     {/while}
47
55
  };
48
56
  ```