@macroforge/mcp-server 0.1.30 → 0.1.32

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.
@@ -1,14 +1,14 @@
1
- ## Comments: `&#123;> ... <&#125;` and `&#123;>> ... <<&#125;`
1
+ ## Comments: `&#123;> "..." <&#125;` and `&#123;>> "..." <<&#125;`
2
2
 
3
- Since Rust's tokenizer strips comments before macros see them, you can't write JSDoc comments directly. Instead, use the comment syntax to output JavaScript comments:
3
+ Since Rust's tokenizer strips whitespace before macros see them, use string literals to preserve exact spacing in comments:
4
4
 
5
5
  ### Block Comments
6
6
 
7
- Use `&#123;> comment <&#125;` for block comments:
7
+ Use `&#123;> "comment" <&#125;` for block comments:
8
8
 
9
9
  ```rust
10
10
  let code = ts_template! {
11
- {> This is a block comment <}
11
+ {> "This is a block comment" <}
12
12
  const x = 42;
13
13
  };
14
14
  ```
@@ -22,12 +22,12 @@ const x = 42;
22
22
 
23
23
  ### Doc Comments (JSDoc)
24
24
 
25
- Use `&#123;>> doc <<&#125;` for JSDoc comments:
25
+ Use `&#123;>> "doc" <<&#125;` for JSDoc comments:
26
26
 
27
27
  ```rust
28
28
  let code = ts_template! {
29
- {>> @param {string} name - The user's name <<}
30
- {>> @returns {string} A greeting message <<}
29
+ {>> "@param {string} name - The user's name" <<}
30
+ {>> "@returns {string} A greeting message" <<}
31
31
  function greet(name: string): string {
32
32
  return "Hello, " + name;
33
33
  }
@@ -42,25 +42,4 @@ let code = ts_template! {
42
42
  function greet(name: string): string {
43
43
  return "Hello, " + name;
44
44
  }
45
- ```
46
-
47
- ### Comments with Interpolation
48
-
49
- Comments support `@&#123;expr&#125;` interpolation for dynamic content:
50
-
51
- ```rust
52
- let param_name = "userId";
53
- let param_type = "number";
54
-
55
- let code = ts_template! {
56
- {>> @param {@{param_type}} @{param_name} - The user ID <<}
57
- function getUser(userId: number) {}
58
- };
59
- ```
60
-
61
- **Generates:**
62
-
63
- ```typescript
64
- /** @param {number} userId - The user ID */
65
- function getUser(userId: number) {}
66
45
  ```
@@ -66,11 +66,11 @@ pub fn derive_json_macro(input: TsStream) -> MacroResult {
66
66
 
67
67
  1. **Compile-Time:** The template is parsed during macro expansion
68
68
 
69
- 2. **String Building:** Generates Rust code that builds a TypeScript string at runtime
69
+ 2. **String Building:** Generates Rust code that builds a TypeScript string at runtime
70
70
 
71
- 3. **SWC Parsing:** The generated string is parsed with SWC to produce a typed AST
71
+ 3. **SWC Parsing:** The generated string is parsed with SWC to produce a typed AST
72
72
 
73
- 4. **Result:** Returns `Stmt` that can be used in `MacroResult` patches
73
+ 4. **Result:** Returns `Stmt` that can be used in `MacroResult` patches
74
74
 
75
75
  ## Return Type
76
76
 
@@ -87,11 +87,11 @@ This shows you exactly what was generated, making debugging easy!
87
87
 
88
88
  ## Nesting and Regular TypeScript
89
89
 
90
- You can mix template syntax with regular TypeScript. Braces `&#123;&#125;` are recognized as either:
90
+ You can mix template syntax with regular TypeScript. Braces <code >&#123;&#125;</code > are recognized as either:
91
91
 
92
92
  - **Template tags** if they start with `#`, `$`, `:`, or `/`
93
93
 
94
- - **Regular TypeScript blocks** otherwise
94
+ - **Regular TypeScript blocks** otherwise
95
95
 
96
96
  ```rust
97
97
  ts_template! {
@@ -109,23 +109,27 @@ ts_template! {
109
109
  ## Comparison with Alternatives
110
110
 
111
111
  | `ts_quote!`
112
- | Compile-time validation, type-safe
113
- | Can't handle Vec<Stmt>, verbose
112
+ | Compile-time validation, type-safe
113
+ | Can't handle Vec<Stmt>, verbose
114
+
114
115
 
115
- | `parse_ts_str()`
116
- | Maximum flexibility
117
- | Runtime parsing, less readable
116
+
117
+ | `parse_ts_str()`
118
+ | Maximum flexibility
119
+ | Runtime parsing, less readable
120
+
118
121
 
119
- | `ts_template!`
120
- | Readable, handles loops/conditions
121
- | Small runtime parsing overhead
122
+
123
+ | `ts_template!`
124
+ | Readable, handles loops/conditions
125
+ | Small runtime parsing overhead
122
126
 
123
127
  ## Best Practices
124
128
 
125
129
  1. Use `ts_template!` for complex code generation with loops/conditions
126
130
 
127
- 2. Use `ts_quote!` for simple, static statements
131
+ 2. Use `ts_quote!` for simple, static statements
128
132
 
129
- 3. Keep templates readable - extract complex logic into variables
133
+ 3. Keep templates readable - extract complex logic into variables
130
134
 
131
- 4. Don't nest templates too deeply - split into helper functions
135
+ 4. Don't nest templates too deeply - split into helper functions
@@ -0,0 +1,349 @@
1
+ ## Interpolation: `@&#123;expr&#125;`
2
+
3
+ Insert Rust expressions into the generated TypeScript:
4
+
5
+ ```rust
6
+ let class_name = "User";
7
+ let method = "toString";
8
+
9
+ let code = ts_template! {
10
+ @{class_name}.prototype.@{method} = function() {
11
+ return "User instance";
12
+ };
13
+ };
14
+ ```
15
+
16
+ **Generates:**
17
+
18
+ ```typescript
19
+ User.prototype.toString = function () {
20
+ return "User instance";
21
+ };
22
+ ```
23
+
24
+ <h2 id="ident-blocks">
25
+ Identifier Concatenation: `&#123;| content |&#125;`
26
+ </h2>
27
+
28
+ When you need to build identifiers dynamically (like `getUser`, `setName`), use the ident block syntax. Everything inside `&#123;| |&#125;` is concatenated without spaces:
29
+
30
+ ```rust
31
+ let field_name = "User";
32
+
33
+ let code = ts_template! {
34
+ function {|get@{field_name}|}() {
35
+ return this.@{field_name.to_lowercase()};
36
+ }
37
+ };
38
+ ```
39
+
40
+ **Generates:**
41
+
42
+ ```typescript
43
+ function getUser() {
44
+ return this.user;
45
+ }
46
+ ```
47
+
48
+ Without ident blocks, `@&#123;&#125;` always adds a space after for readability. Use `&#123;| |&#125;` when you explicitly want concatenation:
49
+
50
+ ```rust
51
+ let name = "Status";
52
+
53
+ // With space (default behavior)
54
+ ts_template! { namespace @{name} } // → "namespace Status"
55
+
56
+ // Without space (ident block)
57
+ ts_template! { {|namespace@{name}|} } // → "namespaceStatus"
58
+ ```
59
+
60
+ Multiple interpolations can be combined:
61
+
62
+ ```rust
63
+ let entity = "user";
64
+ let action = "create";
65
+
66
+ ts_template! { {|@{entity}_@{action}|} } // → "user_create"
67
+ ```
68
+
69
+ <h2 id="comments">
70
+ Comments: `&#123;> "..." <&#125;` and
71
+ `&#123;>> "..." <<&#125;`
72
+ </h2>
73
+
74
+ Since Rust's tokenizer strips whitespace before macros see them, use string literals to preserve exact spacing in comments:
75
+
76
+ ### Block Comments
77
+
78
+ Use `&#123;> "comment" <&#125;` for block comments:
79
+
80
+ ```rust
81
+ let code = ts_template! {
82
+ {> "This is a block comment" <}
83
+ const x = 42;
84
+ };
85
+ ```
86
+
87
+ **Generates:**
88
+
89
+ ```typescript
90
+ /* This is a block comment */
91
+ const x = 42;
92
+ ```
93
+
94
+ ### Doc Comments (JSDoc)
95
+
96
+ Use `&#123;>> "doc" <<&#125;` for JSDoc comments:
97
+
98
+ ```rust
99
+ let code = ts_template! {
100
+ {>> "@param {string} name - The user's name" <<}
101
+ {>> "@returns {string} A greeting message" <<}
102
+ function greet(name: string): string {
103
+ return "Hello, " + name;
104
+ }
105
+ };
106
+ ```
107
+
108
+ **Generates:**
109
+
110
+ ```typescript
111
+ /** @param {string} name - The user's name */
112
+ /** @returns {string} A greeting message */
113
+ function greet(name: string): string {
114
+ return "Hello, " + name;
115
+ }
116
+ ```
117
+
118
+ ### Comments with Interpolation
119
+
120
+ Use `format!()` or similar to build dynamic comment strings:
121
+
122
+ ```rust
123
+ let param_name = "userId";
124
+ let param_type = "number";
125
+ let comment = format!("@param {{{}}} {} - The user ID", param_type, param_name);
126
+
127
+ let code = ts_template! {
128
+ {>> @{comment} <<}
129
+ function getUser(userId: number) {}
130
+ };
131
+ ```
132
+
133
+ **Generates:**
134
+
135
+ ```typescript
136
+ /** @param {number} userId - The user ID */
137
+ function getUser(userId: number) {}
138
+ ```
139
+
140
+ <h2 id="string-interpolation">
141
+ String Interpolation: `"text @&#123;expr&#125;"`
142
+ </h2>
143
+
144
+ Interpolation works automatically inside string literals - no <code >format!()</code > needed:
145
+
146
+ ```rust
147
+ let name = "World";
148
+ let count = 42;
149
+
150
+ let code = ts_template! {
151
+ console.log("Hello @{name}!");
152
+ console.log("Count: @{count}, doubled: @{count * 2}");
153
+ };
154
+ ```
155
+
156
+ **Generates:**
157
+
158
+ ```typescript
159
+ console.log("Hello World!");
160
+ console.log("Count: 42, doubled: 84");
161
+ ```
162
+
163
+ This also works with method calls and complex expressions:
164
+
165
+ ```rust
166
+ let field = "username";
167
+
168
+ let code = ts_template! {
169
+ throw new Error("Invalid @{field.to_uppercase()}");
170
+ };
171
+ ```
172
+
173
+ <h2 id="backtick-templates">
174
+ Backtick Template Literals: `"'^...^'"`
175
+ </h2>
176
+
177
+ For JavaScript template literals (backtick strings), use the <code >'^...^'</code > syntax. This outputs actual backticks and passes through `${"${}"}` for JS interpolation:
178
+
179
+ ```rust
180
+ let tag_name = "div";
181
+
182
+ let code = ts_template! {
183
+ const html = "'^<@{tag_name}>\${content}</@{tag_name}>^'";
184
+ };
185
+ ```
186
+
187
+ **Generates:**
188
+
189
+ <CodeBlock code={"const html = `${content}`;"} lang="typescript" />
190
+
191
+ You can mix Rust `@&#123;&#125;` interpolation (evaluated at macro expansion time) with JS `${"${}"}` interpolation (evaluated at runtime):
192
+
193
+ ```rust
194
+ let class_name = "User";
195
+
196
+ let code = ts_template! {
197
+ "'^Hello \${this.name}, you are a @{class_name}^'"
198
+ };
199
+ ```
200
+
201
+ **Generates:**
202
+
203
+ <CodeBlock code={"`Hello ${this.name}, you are a User`"} lang="typescript" />
204
+
205
+ <h2 id="conditionals">
206
+ Conditionals: `&#123;#if&#125;...&#123;/if&#125;`
207
+ </h2>
208
+
209
+ Basic conditional:
210
+
211
+ ```rust
212
+ let needs_validation = true;
213
+
214
+ let code = ts_template! {
215
+ function save() {
216
+ {#if needs_validation}
217
+ if (!this.isValid()) return false;
218
+ {/if}
219
+ return this.doSave();
220
+ }
221
+ };
222
+ ```
223
+
224
+ ### If-Else
225
+
226
+ ```rust
227
+ let has_default = true;
228
+
229
+ let code = ts_template! {
230
+ {#if has_default}
231
+ return defaultValue;
232
+ {:else}
233
+ throw new Error("No default");
234
+ {/if}
235
+ };
236
+ ```
237
+
238
+ ### If-Else-If Chains
239
+
240
+ ```rust
241
+ let level = 2;
242
+
243
+ let code = ts_template! {
244
+ {#if level == 1}
245
+ console.log("Level 1");
246
+ {:else if level == 2}
247
+ console.log("Level 2");
248
+ {:else}
249
+ console.log("Other level");
250
+ {/if}
251
+ };
252
+ ```
253
+
254
+ <h2 id="pattern-matching">
255
+ Pattern Matching: `&#123;#if let&#125;`
256
+ </h2>
257
+
258
+ Use `if let` for pattern matching on `Option`, `Result`, or other Rust enums:
259
+
260
+ ```rust
261
+ let maybe_name: Option<&str> = Some("Alice");
262
+
263
+ let code = ts_template! {
264
+ {#if let Some(name) = maybe_name}
265
+ console.log("Hello, @{name}!");
266
+ {:else}
267
+ console.log("Hello, anonymous!");
268
+ {/if}
269
+ };
270
+ ```
271
+
272
+ **Generates:**
273
+
274
+ ```typescript
275
+ console.log("Hello, Alice!");
276
+ ```
277
+
278
+ This is useful when working with optional values from your IR:
279
+
280
+ ```rust
281
+ let code = ts_template! {
282
+ {#if let Some(default_val) = field.default_value}
283
+ this.@{field.name} = @{default_val};
284
+ {:else}
285
+ this.@{field.name} = undefined;
286
+ {/if}
287
+ };
288
+ ```
289
+
290
+ <h2 id="match-expressions">
291
+ Match Expressions: `&#123;#match&#125;`
292
+ </h2>
293
+
294
+ Use `match` for exhaustive pattern matching:
295
+
296
+ ```rust
297
+ enum Visibility { Public, Private, Protected }
298
+ let visibility = Visibility::Public;
299
+
300
+ let code = ts_template! {
301
+ {#match visibility}
302
+ {:case Visibility::Public}
303
+ public
304
+ {:case Visibility::Private}
305
+ private
306
+ {:case Visibility::Protected}
307
+ protected
308
+ {/match}
309
+ field: string;
310
+ };
311
+ ```
312
+
313
+ **Generates:**
314
+
315
+ ```typescript
316
+ public field: string;
317
+ ```
318
+
319
+ ### Match with Value Extraction
320
+
321
+ ```rust
322
+ let result: Result<i32, &str> = Ok(42);
323
+
324
+ let code = ts_template! {
325
+ const value = {#match result}
326
+ {:case Ok(val)}
327
+ @{val}
328
+ {:case Err(msg)}
329
+ throw new Error("@{msg}")
330
+ {/match};
331
+ };
332
+ ```
333
+
334
+ ### Match with Wildcard
335
+
336
+ ```rust
337
+ let count = 5;
338
+
339
+ let code = ts_template! {
340
+ {#match count}
341
+ {:case 0}
342
+ console.log("none");
343
+ {:case 1}
344
+ console.log("one");
345
+ {:case _}
346
+ console.log("many");
347
+ {/match}
348
+ };
349
+ ```
@@ -0,0 +1,34 @@
1
+ ## Local Constants: `&#123;$let&#125;`
2
+
3
+ Define local variables within the template scope:
4
+
5
+ ```rust
6
+ let items = vec![("user", "User"), ("post", "Post")];
7
+
8
+ let code = ts_template! {
9
+ {#for (key, class_name) in items}
10
+ {$let upper = class_name.to_uppercase()}
11
+ console.log("Processing @{upper}");
12
+ const @{key} = new @{class_name}();
13
+ {/for}
14
+ };
15
+ ```
16
+
17
+ This is useful for computing derived values inside loops without cluttering the Rust code.
18
+
19
+ <h2 id="mutable-variables">
20
+ Mutable Variables: `&#123;$let mut&#125;`
21
+ </h2>
22
+
23
+ When you need to modify a variable within the template (e.g., in a <code >while</code > loop), use `&#123;$let mut&#125;`:
24
+
25
+ ```rust
26
+ let code = ts_template! {
27
+ {$let mut count = 0}
28
+ {#for item in items}
29
+ console.log("Item @{count}: @{item}");
30
+ {$do count += 1}
31
+ {/for}
32
+ console.log("Total: @{count}");
33
+ };
34
+ ```
@@ -5,9 +5,11 @@
5
5
  ## Available Macros
6
6
 
7
7
  | `ts_template!`
8
- | Any TypeScript code
9
- | General code generation
10
-
11
- | `body!`
12
- | Class body members
13
- | Methods and properties
8
+ | Any TypeScript code
9
+ | General code generation
10
+
11
+
12
+
13
+ | `body!`
14
+ | Class body members
15
+ | Methods and properties