@macroforge/mcp-server 0.1.25 → 0.1.26

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 (40) hide show
  1. package/dist/tools/docs-loader.d.ts +3 -0
  2. package/dist/tools/docs-loader.d.ts.map +1 -1
  3. package/dist/tools/docs-loader.js +4 -0
  4. package/dist/tools/docs-loader.js.map +1 -1
  5. package/dist/tools/index.js +60 -3
  6. package/dist/tools/index.js.map +1 -1
  7. package/docs/builtin-macros/deserialize/all-options.md +33 -0
  8. package/docs/builtin-macros/deserialize/combining-with-serialize.md +27 -0
  9. package/docs/builtin-macros/deserialize/enum-support.md +31 -0
  10. package/docs/builtin-macros/deserialize/error-handling.md +24 -0
  11. package/docs/builtin-macros/deserialize/interface-support.md +18 -0
  12. package/docs/builtin-macros/deserialize/overview.md +16 -0
  13. package/docs/builtin-macros/deserialize/runtime-validation.md +51 -0
  14. package/docs/builtin-macros/deserialize/serde-options.md +83 -0
  15. package/docs/builtin-macros/deserialize/type-alias-support.md +26 -0
  16. package/docs/custom-macros/rust-setup.md +6 -6
  17. package/docs/custom-macros/ts-macro-derive/accessing-field-data.md +53 -0
  18. package/docs/custom-macros/ts-macro-derive/adding-imports.md +21 -0
  19. package/docs/custom-macros/ts-macro-derive/attribute-options.md +50 -0
  20. package/docs/custom-macros/ts-macro-derive/complete-example.md +51 -0
  21. package/docs/custom-macros/ts-macro-derive/deriveinput-structure.md +61 -0
  22. package/docs/custom-macros/ts-macro-derive/overview.md +15 -0
  23. package/docs/custom-macros/ts-macro-derive/parsing-input.md +27 -0
  24. package/docs/custom-macros/ts-macro-derive/returning-errors.md +21 -0
  25. package/docs/custom-macros/ts-quote/backtick-template-literals.md +29 -0
  26. package/docs/custom-macros/ts-quote/comments-and.md +66 -0
  27. package/docs/custom-macros/ts-quote/complete-example-json-derive-macro.md +131 -0
  28. package/docs/custom-macros/ts-quote/conditionals-ifif.md +46 -0
  29. package/docs/custom-macros/ts-quote/identifier-concatenation-content.md +42 -0
  30. package/docs/custom-macros/ts-quote/iteration-for.md +60 -0
  31. package/docs/custom-macros/ts-quote/match-expressions-match.md +58 -0
  32. package/docs/custom-macros/ts-quote/overview.md +13 -0
  33. package/docs/custom-macros/ts-quote/pattern-matching-if-let.md +33 -0
  34. package/docs/custom-macros/ts-quote/quick-reference.md +83 -0
  35. package/docs/custom-macros/ts-quote/side-effects-do.md +23 -0
  36. package/docs/custom-macros/ts-quote/string-interpolation-text-expr.md +30 -0
  37. package/docs/custom-macros/ts-quote/tsstream-injection-typescript.md +61 -0
  38. package/docs/custom-macros/ts-quote/while-loops-while.md +81 -0
  39. package/docs/sections.json +322 -3
  40. package/package.json +2 -2
@@ -0,0 +1,50 @@
1
+ ## Attribute Options
2
+
3
+ ### Name (Required)
4
+
5
+ The first argument is the macro name that users will reference in `@derive()`:
6
+
7
+ ```rust
8
+ #[ts_macro_derive(JSON)] // Users write: @derive(JSON)
9
+ pub fn derive_json(...)
10
+ ```
11
+
12
+ ### Description
13
+
14
+ Provides documentation for the macro:
15
+
16
+ ```rust
17
+ #[ts_macro_derive(
18
+ JSON,
19
+ description = "Generates toJSON() returning a plain object"
20
+ )]
21
+ pub fn derive_json(...)
22
+ ```
23
+
24
+ ### Attributes
25
+
26
+ Declare which field-level decorators your macro accepts:
27
+
28
+ ```rust
29
+ #[ts_macro_derive(
30
+ Debug,
31
+ description = "Generates toString()",
32
+ attributes(debug) // Allows @debug({ ... }) on fields
33
+ )]
34
+ pub fn derive_debug(...)
35
+ ```
36
+
37
+ >
38
+ > Declared attributes become available as `@attributeName({ options })` decorators in TypeScript.
39
+
40
+ ## Function Signature
41
+
42
+ ```rust
43
+ pub fn my_macro(mut input: TsStream) -> Result<TsStream, MacroforgeError>
44
+ ```
45
+
46
+ | `input: TsStream`
47
+ | Token stream containing the class/interface AST
48
+
49
+ | `Result<TsStream, MacroforgeError>`
50
+ | Returns generated code or an error with source location
@@ -0,0 +1,51 @@
1
+ ## Complete Example
2
+
3
+ ```rust
4
+ use macroforge_ts::macros::{ts_macro_derive, body};
5
+ use macroforge_ts::ts_syn::{
6
+ Data, DeriveInput, FieldIR, MacroforgeError, TsStream, parse_ts_macro_input,
7
+ };
8
+
9
+ // Helper function to check if a field has a decorator
10
+ fn has_decorator(field: &FieldIR, name: &str) -> bool {
11
+ field.decorators.iter().any(|d| d.name.eq_ignore_ascii_case(name))
12
+ }
13
+
14
+ #[ts_macro_derive(
15
+ Validate,
16
+ description = "Generates a validate() method",
17
+ attributes(validate)
18
+ )]
19
+ pub fn derive_validate(mut input: TsStream) -> Result<TsStream, MacroforgeError> {
20
+ let input = parse_ts_macro_input!(input as DeriveInput);
21
+
22
+ match &input.data {
23
+ Data::Class(class) => {
24
+ let validations: Vec<_> = class.fields()
25
+ .iter()
26
+ .filter(|f| has_decorator(f, "validate"))
27
+ .collect();
28
+
29
+ Ok(body! {
30
+ validate(): string[] {
31
+ const errors: string[] = [];
32
+ {#for field in validations}
33
+ if (!this.@{field.name}) {
34
+ errors.push("@{field.name} is required");
35
+ }
36
+ {/for}
37
+ return errors;
38
+ }
39
+ })
40
+ }
41
+ _ => Err(MacroforgeError::new(
42
+ input.decorator_span(),
43
+ "@derive(Validate) only works on classes",
44
+ )),
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Next Steps
50
+
51
+ - [Learn the template syntax]({base}/docs/custom-macros/ts-quote)
@@ -0,0 +1,61 @@
1
+ ## DeriveInput Structure
2
+
3
+ ```rust
4
+ struct DeriveInput {
5
+ pub ident: Ident, // The type name
6
+ pub span: SpanIR, // Span of the type definition
7
+ pub attrs: Vec<Attribute>, // Decorators (excluding @derive)
8
+ pub data: Data, // The parsed type data
9
+ pub context: MacroContextIR, // Macro context with spans
10
+
11
+ // Helper methods
12
+ fn name(&self) -> &str; // Get the type name
13
+ fn decorator_span(&self) -> SpanIR; // Span of @derive decorator
14
+ fn as_class(&self) -> Option<&DataClass>;
15
+ fn as_interface(&self) -> Option<&DataInterface>;
16
+ fn as_enum(&self) -> Option<&DataEnum>;
17
+ }
18
+
19
+ enum Data {
20
+ Class(DataClass),
21
+ Interface(DataInterface),
22
+ Enum(DataEnum),
23
+ TypeAlias(DataTypeAlias),
24
+ }
25
+
26
+ impl DataClass {
27
+ fn fields(&self) -> &[FieldIR];
28
+ fn methods(&self) -> &[MethodSigIR];
29
+ fn field_names(&self) -> impl Iterator<Item = &str>;
30
+ fn field(&self, name: &str) -> Option<&FieldIR>;
31
+ fn body_span(&self) -> SpanIR; // For inserting code into class body
32
+ fn type_params(&self) -> &[String]; // Generic type parameters
33
+ fn heritage(&self) -> &[String]; // extends/implements clauses
34
+ fn is_abstract(&self) -> bool;
35
+ }
36
+
37
+ impl DataInterface {
38
+ fn fields(&self) -> &[InterfaceFieldIR];
39
+ fn methods(&self) -> &[InterfaceMethodIR];
40
+ fn field_names(&self) -> impl Iterator<Item = &str>;
41
+ fn field(&self, name: &str) -> Option<&InterfaceFieldIR>;
42
+ fn body_span(&self) -> SpanIR;
43
+ fn type_params(&self) -> &[String];
44
+ fn heritage(&self) -> &[String]; // extends clauses
45
+ }
46
+
47
+ impl DataEnum {
48
+ fn variants(&self) -> &[EnumVariantIR];
49
+ fn variant_names(&self) -> impl Iterator<Item = &str>;
50
+ fn variant(&self, name: &str) -> Option<&EnumVariantIR>;
51
+ }
52
+
53
+ impl DataTypeAlias {
54
+ fn body(&self) -> &TypeBody;
55
+ fn type_params(&self) -> &[String];
56
+ fn is_union(&self) -> bool;
57
+ fn is_object(&self) -> bool;
58
+ fn as_union(&self) -> Option<&[TypeMember]>;
59
+ fn as_object(&self) -> Option<&[InterfaceFieldIR]>;
60
+ }
61
+ ```
@@ -0,0 +1,15 @@
1
+ # ts_macro_derive
2
+
3
+ *The `#[ts_macro_derive]` attribute is a Rust procedural macro that registers your function as a Macroforge derive macro.*
4
+
5
+ ## Basic Syntax
6
+
7
+ ```rust
8
+ use macroforge_ts::macros::ts_macro_derive;
9
+ use macroforge_ts::ts_syn::{TsStream, MacroforgeError};
10
+
11
+ #[ts_macro_derive(MacroName)]
12
+ pub fn my_macro(mut input: TsStream) -> Result<TsStream, MacroforgeError> {
13
+ // Macro implementation
14
+ }
15
+ ```
@@ -0,0 +1,27 @@
1
+ ## Parsing Input
2
+
3
+ Use `parse_ts_macro_input!` to convert the token stream:
4
+
5
+ ```rust
6
+ use macroforge_ts::ts_syn::{Data, DeriveInput, parse_ts_macro_input};
7
+
8
+ #[ts_macro_derive(MyMacro)]
9
+ pub fn my_macro(mut input: TsStream) -> Result<TsStream, MacroforgeError> {
10
+ let input = parse_ts_macro_input!(input as DeriveInput);
11
+
12
+ // Access class data
13
+ match &input.data {
14
+ Data::Class(class) => {
15
+ let class_name = input.name();
16
+ let fields = class.fields();
17
+ // ...
18
+ }
19
+ Data::Interface(interface) => {
20
+ // Handle interfaces
21
+ }
22
+ Data::Enum(_) => {
23
+ // Handle enums (if supported)
24
+ }
25
+ }
26
+ }
27
+ ```
@@ -0,0 +1,21 @@
1
+ ## Returning Errors
2
+
3
+ Use `MacroforgeError` to report errors with source locations:
4
+
5
+ ```rust
6
+ #[ts_macro_derive(ClassOnly)]
7
+ pub fn class_only(mut input: TsStream) -> Result<TsStream, MacroforgeError> {
8
+ let input = parse_ts_macro_input!(input as DeriveInput);
9
+
10
+ match &input.data {
11
+ Data::Class(_) => {
12
+ // Generate code...
13
+ Ok(body! { /* ... */ })
14
+ }
15
+ _ => Err(MacroforgeError::new(
16
+ input.decorator_span(),
17
+ "@derive(ClassOnly) can only be used on classes",
18
+ )),
19
+ }
20
+ }
21
+ ```
@@ -0,0 +1,29 @@
1
+ ## Backtick Template Literals: `"'^...^'"`
2
+
3
+ For JavaScript template literals (backtick strings), use the `'^...^'` syntax. This outputs actual backticks and passes through `${"${}"}` for JS interpolation:
4
+
5
+ ```rust
6
+ let tag_name = "div";
7
+
8
+ let code = ts_template! {
9
+ const html = "'^<@{tag_name}>\${content}</@{tag_name}>^'";
10
+ };
11
+ ```
12
+
13
+ **Generates:**
14
+
15
+ <CodeBlock code={'const html = `${content}`;'} lang="typescript" />
16
+
17
+ You can mix Rust `@&#123;&#125;` interpolation (evaluated at macro expansion time) with JS `${"${}"}` interpolation (evaluated at runtime):
18
+
19
+ ```rust
20
+ let class_name = "User";
21
+
22
+ let code = ts_template! {
23
+ "'^Hello \${this.name}, you are a @{class_name}^'"
24
+ };
25
+ ```
26
+
27
+ **Generates:**
28
+
29
+ <CodeBlock code={'`Hello ${this.name}, you are a User`'} lang="typescript" />
@@ -0,0 +1,66 @@
1
+ ## Comments: `&#123;> ... <&#125;` and `&#123;>> ... <<&#125;`
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:
4
+
5
+ ### Block Comments
6
+
7
+ Use `&#123;> comment <&#125;` for block comments:
8
+
9
+ ```rust
10
+ let code = ts_template! {
11
+ {> This is a block comment <}
12
+ const x = 42;
13
+ };
14
+ ```
15
+
16
+ **Generates:**
17
+
18
+ ```typescript
19
+ /* This is a block comment */
20
+ const x = 42;
21
+ ```
22
+
23
+ ### Doc Comments (JSDoc)
24
+
25
+ Use `&#123;>> doc <<&#125;` for JSDoc comments:
26
+
27
+ ```rust
28
+ let code = ts_template! {
29
+ {>> @param {string} name - The user's name <<}
30
+ {>> @returns {string} A greeting message <<}
31
+ function greet(name: string): string {
32
+ return "Hello, " + name;
33
+ }
34
+ };
35
+ ```
36
+
37
+ **Generates:**
38
+
39
+ ```typescript
40
+ /** @param {string} name - The user's name */
41
+ /** @returns {string} A greeting message */
42
+ function greet(name: string): string {
43
+ return "Hello, " + name;
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
+ ```
@@ -0,0 +1,131 @@
1
+ ## Complete Example: JSON Derive Macro
2
+
3
+ Here's a comparison showing how `ts_template!` simplifies code generation:
4
+
5
+ ### Before (Manual AST Building)
6
+
7
+ ```rust
8
+ pub fn derive_json_macro(input: TsStream) -> MacroResult {
9
+ let input = parse_ts_macro_input!(input as DeriveInput);
10
+
11
+ match &input.data {
12
+ Data::Class(class) => {
13
+ let class_name = input.name();
14
+
15
+ let mut body_stmts = vec![ts_quote!( const result = {}; as Stmt )];
16
+
17
+ for field_name in class.field_names() {
18
+ body_stmts.push(ts_quote!(
19
+ result.$(ident!("{}", field_name)) = this.$(ident!("{}", field_name));
20
+ as Stmt
21
+ ));
22
+ }
23
+
24
+ body_stmts.push(ts_quote!( return result; as Stmt ));
25
+
26
+ let runtime_code = fn_assign!(
27
+ member_expr!(Expr::Ident(ident!(class_name)), "prototype"),
28
+ "toJSON",
29
+ body_stmts
30
+ );
31
+
32
+ // ...
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ### After (With ts_template!)
39
+
40
+ ```rust
41
+ pub fn derive_json_macro(input: TsStream) -> MacroResult {
42
+ let input = parse_ts_macro_input!(input as DeriveInput);
43
+
44
+ match &input.data {
45
+ Data::Class(class) => {
46
+ let class_name = input.name();
47
+ let fields = class.field_names();
48
+
49
+ let runtime_code = ts_template! {
50
+ @{class_name}.prototype.toJSON = function() {
51
+ const result = {};
52
+ {#for field in fields}
53
+ result.@{field} = this.@{field};
54
+ {/for}
55
+ return result;
56
+ };
57
+ };
58
+
59
+ // ...
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ## How It Works
66
+
67
+ 1. **Compile-Time:** The template is parsed during macro expansion
68
+
69
+ 2. **String Building:** Generates Rust code that builds a TypeScript string at runtime
70
+
71
+ 3. **SWC Parsing:** The generated string is parsed with SWC to produce a typed AST
72
+
73
+ 4. **Result:** Returns `Stmt` that can be used in `MacroResult` patches
74
+
75
+ ## Return Type
76
+
77
+ `ts_template!` returns a `Result<Stmt, TsSynError>` by default. The macro automatically unwraps and provides helpful error messages showing the generated TypeScript code if parsing fails:
78
+
79
+ ```text
80
+ Failed to parse generated TypeScript:
81
+ User.prototype.toJSON = function( {
82
+ return {};
83
+ }
84
+ ```
85
+
86
+ This shows you exactly what was generated, making debugging easy!
87
+
88
+ ## Nesting and Regular TypeScript
89
+
90
+ You can mix template syntax with regular TypeScript. Braces `&#123;&#125;` are recognized as either:
91
+
92
+ - **Template tags** if they start with `#`, `$`, `:`, or `/`
93
+
94
+ - **Regular TypeScript blocks** otherwise
95
+
96
+ ```rust
97
+ ts_template! {
98
+ const config = {
99
+ {#if use_strict}
100
+ strict: true,
101
+ {:else}
102
+ strict: false,
103
+ {/if}
104
+ timeout: 5000
105
+ };
106
+ }
107
+ ```
108
+
109
+ ## Comparison with Alternatives
110
+
111
+ | `ts_quote!`
112
+ | Compile-time validation, type-safe
113
+ | Can't handle Vec<Stmt>, verbose
114
+
115
+ | `parse_ts_str()`
116
+ | Maximum flexibility
117
+ | Runtime parsing, less readable
118
+
119
+ | `ts_template!`
120
+ | Readable, handles loops/conditions
121
+ | Small runtime parsing overhead
122
+
123
+ ## Best Practices
124
+
125
+ 1. Use `ts_template!` for complex code generation with loops/conditions
126
+
127
+ 2. Use `ts_quote!` for simple, static statements
128
+
129
+ 3. Keep templates readable - extract complex logic into variables
130
+
131
+ 4. Don't nest templates too deeply - split into helper functions
@@ -0,0 +1,46 @@
1
+ ## Conditionals: `&#123;#if&#125;...&#123;/if&#125;`
2
+
3
+ Basic conditional:
4
+
5
+ ```rust
6
+ let needs_validation = true;
7
+
8
+ let code = ts_template! {
9
+ function save() {
10
+ {#if needs_validation}
11
+ if (!this.isValid()) return false;
12
+ {/if}
13
+ return this.doSave();
14
+ }
15
+ };
16
+ ```
17
+
18
+ ### If-Else
19
+
20
+ ```rust
21
+ let has_default = true;
22
+
23
+ let code = ts_template! {
24
+ {#if has_default}
25
+ return defaultValue;
26
+ {:else}
27
+ throw new Error("No default");
28
+ {/if}
29
+ };
30
+ ```
31
+
32
+ ### If-Else-If Chains
33
+
34
+ ```rust
35
+ let level = 2;
36
+
37
+ let code = ts_template! {
38
+ {#if level == 1}
39
+ console.log("Level 1");
40
+ {:else if level == 2}
41
+ console.log("Level 2");
42
+ {:else}
43
+ console.log("Other level");
44
+ {/if}
45
+ };
46
+ ```
@@ -0,0 +1,42 @@
1
+ ## Identifier Concatenation: `&#123;| content |&#125;`
2
+
3
+ When you need to build identifiers dynamically (like `getUser`, `setName`), use the ident block syntax. Everything inside `&#123;| |&#125;` is concatenated without spaces:
4
+
5
+ ```rust
6
+ let field_name = "User";
7
+
8
+ let code = ts_template! {
9
+ function {|get@{field_name}|}() {
10
+ return this.@{field_name.to_lowercase()};
11
+ }
12
+ };
13
+ ```
14
+
15
+ **Generates:**
16
+
17
+ ```typescript
18
+ function getUser() {
19
+ return this.user;
20
+ }
21
+ ```
22
+
23
+ Without ident blocks, `@&#123;&#125;` always adds a space after for readability. Use `&#123;| |&#125;` when you explicitly want concatenation:
24
+
25
+ ```rust
26
+ let name = "Status";
27
+
28
+ // With space (default behavior)
29
+ ts_template! { namespace @{name} } // → "namespace Status"
30
+
31
+ // Without space (ident block)
32
+ ts_template! { {|namespace@{name}|} } // → "namespaceStatus"
33
+ ```
34
+
35
+ Multiple interpolations can be combined:
36
+
37
+ ```rust
38
+ let entity = "user";
39
+ let action = "create";
40
+
41
+ ts_template! { {|@{entity}_@{action}|} } // → "user_create"
42
+ ```
@@ -0,0 +1,60 @@
1
+ ## Iteration: `&#123;#for&#125;`
2
+
3
+ ```rust
4
+ let fields = vec!["name", "email", "age"];
5
+
6
+ let code = ts_template! {
7
+ function toJSON() {
8
+ const result = {};
9
+ {#for field in fields}
10
+ result.@{field} = this.@{field};
11
+ {/for}
12
+ return result;
13
+ }
14
+ };
15
+ ```
16
+
17
+ **Generates:**
18
+
19
+ ```typescript
20
+ function toJSON() {
21
+ const result = {};
22
+ result.name = this.name;
23
+ result.email = this.email;
24
+ result.age = this.age;
25
+ return result;
26
+ }
27
+ ```
28
+
29
+ ### Tuple Destructuring in Loops
30
+
31
+ ```rust
32
+ let items = vec![("user", "User"), ("post", "Post")];
33
+
34
+ let code = ts_template! {
35
+ {#for (key, class_name) in items}
36
+ const @{key} = new @{class_name}();
37
+ {/for}
38
+ };
39
+ ```
40
+
41
+ ### Nested Iterations
42
+
43
+ ```rust
44
+ let classes = vec![
45
+ ("User", vec!["name", "email"]),
46
+ ("Post", vec!["title", "content"]),
47
+ ];
48
+
49
+ ts_template! {
50
+ {#for (class_name, fields) in classes}
51
+ @{class_name}.prototype.toJSON = function() {
52
+ return {
53
+ {#for field in fields}
54
+ @{field}: this.@{field},
55
+ {/for}
56
+ };
57
+ };
58
+ {/for}
59
+ }
60
+ ```
@@ -0,0 +1,58 @@
1
+ ## Match Expressions: `&#123;#match&#125;`
2
+
3
+ Use `match` for exhaustive pattern matching:
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;
19
+ };
20
+ ```
21
+
22
+ **Generates:**
23
+
24
+ ```typescript
25
+ public field: string;
26
+ ```
27
+
28
+ ### Match with Value Extraction
29
+
30
+ ```rust
31
+ let result: Result<i32, &str> = Ok(42);
32
+
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};
40
+ };
41
+ ```
42
+
43
+ ### Match with Wildcard
44
+
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}
57
+ };
58
+ ```
@@ -0,0 +1,13 @@
1
+ # Template Syntax
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.*
4
+
5
+ ## Available Macros
6
+
7
+ | `ts_template!`
8
+ | Any TypeScript code
9
+ | General code generation
10
+
11
+ | `body!`
12
+ | Class body members
13
+ | Methods and properties