@macroforge/svelte-preprocessor 0.1.33 → 0.1.35
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 +64 -0
- package/dist/index.d.ts +118 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +207 -16
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @macroforge/svelte-preprocessor
|
|
2
|
+
|
|
3
|
+
Svelte preprocessor for expanding Macroforge macros in component script blocks
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@macroforge/svelte-preprocessor)
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
@macroforge/svelte-preprocessor
|
|
10
|
+
|
|
11
|
+
Svelte preprocessor for expanding Macroforge macros in component script blocks.
|
|
12
|
+
|
|
13
|
+
This module provides integration between Macroforge's macro expansion system and
|
|
14
|
+
Svelte's preprocessing pipeline. It intercepts `<script>` blocks in `.svelte` files,
|
|
15
|
+
detects `@derive` decorators, and expands them into generated code before TypeScript
|
|
16
|
+
compilation occurs.
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
1. The preprocessor is registered in `svelte.config.js` as part of the preprocess array
|
|
21
|
+
2. When Svelte compiles a component, it passes each `<script>` block to this preprocessor
|
|
22
|
+
3. The preprocessor checks if the script contains `@derive` decorators
|
|
23
|
+
4. If found, it calls the native `macroforge` binding to expand the macros
|
|
24
|
+
5. The expanded code replaces the original script content
|
|
25
|
+
|
|
26
|
+
## Important Notes
|
|
27
|
+
|
|
28
|
+
- Must be placed BEFORE other preprocessors (like `vitePreprocess()`) in the chain
|
|
29
|
+
- Uses lazy-loading for native bindings to avoid initialization overhead
|
|
30
|
+
- Gracefully degrades if native bindings are unavailable
|
|
31
|
+
- Only processes TypeScript blocks by default (configurable via options)
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @macroforge/svelte-preprocessor
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### Functions
|
|
42
|
+
|
|
43
|
+
- **`macroforgePreprocess`** - Whether to preserve `@derive` decorators in the expanded output.
|
|
44
|
+
|
|
45
|
+
### Types
|
|
46
|
+
|
|
47
|
+
- **`ExpandResult`** - Whether to preserve `@derive` decorators in the expanded output.
|
|
48
|
+
- **`MacroforgePreprocessorOptions`** - Configuration options for the Macroforge Svelte preprocessor.
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
macroforgePreprocess()
|
|
54
|
+
macroforgePreprocess({ keepDecorators: true })
|
|
55
|
+
macroforgePreprocess({ processJavaScript: true })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
See the [full documentation](https://macroforge.dev/docs/api/reference/typescript/svelte-preprocessor) on the Macroforge website.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,28 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @macroforge/svelte-preprocessor
|
|
3
|
+
*
|
|
4
|
+
* Svelte preprocessor for expanding Macroforge macros in component script blocks.
|
|
5
|
+
*
|
|
6
|
+
* This module provides integration between Macroforge's macro expansion system and
|
|
7
|
+
* Svelte's preprocessing pipeline. It intercepts `<script>` blocks in `.svelte` files,
|
|
8
|
+
* detects `@derive` decorators, and expands them into generated code before TypeScript
|
|
9
|
+
* compilation occurs.
|
|
10
|
+
*
|
|
11
|
+
* ## How It Works
|
|
12
|
+
*
|
|
13
|
+
* 1. The preprocessor is registered in `svelte.config.js` as part of the preprocess array
|
|
14
|
+
* 2. When Svelte compiles a component, it passes each `<script>` block to this preprocessor
|
|
15
|
+
* 3. The preprocessor checks if the script contains `@derive` decorators
|
|
16
|
+
* 4. If found, it calls the native `macroforge` binding to expand the macros
|
|
17
|
+
* 5. The expanded code replaces the original script content
|
|
18
|
+
*
|
|
19
|
+
* ## Important Notes
|
|
20
|
+
*
|
|
21
|
+
* - Must be placed BEFORE other preprocessors (like `vitePreprocess()`) in the chain
|
|
22
|
+
* - Uses lazy-loading for native bindings to avoid initialization overhead
|
|
23
|
+
* - Gracefully degrades if native bindings are unavailable
|
|
24
|
+
* - Only processes TypeScript blocks by default (configurable via options)
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
1
28
|
import type { PreprocessorGroup } from "svelte/compiler";
|
|
2
29
|
/**
|
|
3
|
-
*
|
|
30
|
+
* Configuration options for the Macroforge Svelte preprocessor.
|
|
31
|
+
*
|
|
32
|
+
* These options control how the preprocessor identifies and transforms
|
|
33
|
+
* script blocks containing `@derive` decorators.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // Default behavior - TypeScript only, decorators stripped
|
|
38
|
+
* macroforgePreprocess()
|
|
39
|
+
*
|
|
40
|
+
* // Keep decorators for debugging
|
|
41
|
+
* macroforgePreprocess({ keepDecorators: true })
|
|
42
|
+
*
|
|
43
|
+
* // Process both TypeScript and JavaScript
|
|
44
|
+
* macroforgePreprocess({ processJavaScript: true })
|
|
45
|
+
* ```
|
|
4
46
|
*/
|
|
5
47
|
export interface MacroforgePreprocessorOptions {
|
|
6
48
|
/**
|
|
7
|
-
* Whether to
|
|
8
|
-
*
|
|
49
|
+
* Whether to preserve `@derive` decorators in the expanded output.
|
|
50
|
+
*
|
|
51
|
+
* By default, decorators are stripped after expansion since they've served
|
|
52
|
+
* their purpose. Set to `true` if you need to:
|
|
53
|
+
* - Debug macro expansion by seeing both decorators and generated code
|
|
54
|
+
* - Pass decorators through to another tool in the pipeline
|
|
55
|
+
* - Preserve decorators for documentation generation
|
|
56
|
+
*
|
|
9
57
|
* @default false
|
|
10
58
|
*/
|
|
11
59
|
keepDecorators?: boolean;
|
|
12
60
|
/**
|
|
13
|
-
* Whether to process JavaScript
|
|
14
|
-
*
|
|
61
|
+
* Whether to process JavaScript script blocks in addition to TypeScript.
|
|
62
|
+
*
|
|
63
|
+
* By default, only `<script lang="ts">` and `<script lang="typescript">`
|
|
64
|
+
* blocks are processed, since Macroforge is primarily designed for TypeScript.
|
|
65
|
+
*
|
|
66
|
+
* Set to `true` to also process:
|
|
67
|
+
* - `<script>` (no lang attribute)
|
|
68
|
+
* - `<script lang="js">`
|
|
69
|
+
* - `<script lang="javascript">`
|
|
70
|
+
* - `<script type="module">`
|
|
71
|
+
*
|
|
15
72
|
* @default false
|
|
16
73
|
*/
|
|
17
74
|
processJavaScript?: boolean;
|
|
18
75
|
}
|
|
19
76
|
/**
|
|
20
|
-
* Creates a Svelte preprocessor that expands
|
|
77
|
+
* Creates a Svelte preprocessor that expands Macroforge macros in `<script>` blocks.
|
|
21
78
|
*
|
|
22
|
-
* This
|
|
23
|
-
*
|
|
79
|
+
* This is the main entry point for integrating Macroforge with Svelte. The returned
|
|
80
|
+
* preprocessor intercepts script blocks, detects `@derive` decorators, and expands
|
|
81
|
+
* them into generated code using the native Macroforge engine.
|
|
24
82
|
*
|
|
25
|
-
*
|
|
83
|
+
* ## Preprocessor Order
|
|
84
|
+
*
|
|
85
|
+
* **Important:** This preprocessor must be placed BEFORE other preprocessors like
|
|
86
|
+
* `vitePreprocess()` in the preprocess array. Macros must be expanded before
|
|
87
|
+
* TypeScript compilation occurs, or the TypeScript compiler will fail on the
|
|
88
|
+
* decorator syntax.
|
|
89
|
+
*
|
|
90
|
+
* ## Processing Logic
|
|
91
|
+
*
|
|
92
|
+
* The preprocessor performs these steps for each script block:
|
|
93
|
+
*
|
|
94
|
+
* 1. **Language Check** - Verifies the script is TypeScript (or JavaScript if enabled)
|
|
95
|
+
* 2. **Quick Scan** - Skips blocks without `@derive` (performance optimization)
|
|
96
|
+
* 3. **Expansion** - Calls the native engine to expand macros
|
|
97
|
+
* 4. **Diagnostics** - Logs any errors or warnings from expansion
|
|
98
|
+
* 5. **Return** - Returns transformed code or `undefined` if unchanged
|
|
99
|
+
*
|
|
100
|
+
* ## Error Handling
|
|
101
|
+
*
|
|
102
|
+
* The preprocessor is designed to be resilient:
|
|
103
|
+
* - If native bindings fail to load, it silently skips processing
|
|
104
|
+
* - If macro expansion throws, it logs a warning and continues
|
|
105
|
+
* - Svelte compilation proceeds even if preprocessing fails
|
|
106
|
+
*
|
|
107
|
+
* @param options - Configuration options for the preprocessor
|
|
108
|
+
* @returns A Svelte `PreprocessorGroup` with name "macroforge" and a script preprocessor
|
|
109
|
+
*
|
|
110
|
+
* @example Basic usage
|
|
26
111
|
* ```js
|
|
27
112
|
* // svelte.config.js
|
|
28
113
|
* import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
@@ -30,12 +115,35 @@ export interface MacroforgePreprocessorOptions {
|
|
|
30
115
|
*
|
|
31
116
|
* export default {
|
|
32
117
|
* preprocess: [
|
|
33
|
-
* macroforgePreprocess(),
|
|
118
|
+
* macroforgePreprocess(), // Expand macros FIRST
|
|
34
119
|
* vitePreprocess() // Then handle TypeScript/CSS
|
|
35
120
|
* ]
|
|
36
121
|
* };
|
|
37
122
|
* ```
|
|
123
|
+
*
|
|
124
|
+
* @example With options
|
|
125
|
+
* ```js
|
|
126
|
+
* // svelte.config.js
|
|
127
|
+
* import { macroforgePreprocess } from '@macroforge/svelte-preprocessor';
|
|
128
|
+
*
|
|
129
|
+
* export default {
|
|
130
|
+
* preprocess: [
|
|
131
|
+
* macroforgePreprocess({
|
|
132
|
+
* keepDecorators: true, // Keep @derive in output for debugging
|
|
133
|
+
* processJavaScript: true // Also process <script> blocks without lang="ts"
|
|
134
|
+
* })
|
|
135
|
+
* ]
|
|
136
|
+
* };
|
|
137
|
+
* ```
|
|
38
138
|
*/
|
|
39
139
|
export declare function macroforgePreprocess(options?: MacroforgePreprocessorOptions): PreprocessorGroup;
|
|
140
|
+
/**
|
|
141
|
+
* Default export for convenient importing.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```js
|
|
145
|
+
* import macroforgePreprocess from '@macroforge/svelte-preprocessor';
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
40
148
|
export default macroforgePreprocess;
|
|
41
149
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,iBAAiB,CAAC;AAuIvE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,6BAAkC,GAC1C,iBAAiB,CAkJnB;AAED;;;;;;;GAOG;AACH,eAAe,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module @macroforge/svelte-preprocessor
|
|
3
|
+
*
|
|
4
|
+
* Svelte preprocessor for expanding Macroforge macros in component script blocks.
|
|
5
|
+
*
|
|
6
|
+
* This module provides integration between Macroforge's macro expansion system and
|
|
7
|
+
* Svelte's preprocessing pipeline. It intercepts `<script>` blocks in `.svelte` files,
|
|
8
|
+
* detects `@derive` decorators, and expands them into generated code before TypeScript
|
|
9
|
+
* compilation occurs.
|
|
10
|
+
*
|
|
11
|
+
* ## How It Works
|
|
12
|
+
*
|
|
13
|
+
* 1. The preprocessor is registered in `svelte.config.js` as part of the preprocess array
|
|
14
|
+
* 2. When Svelte compiles a component, it passes each `<script>` block to this preprocessor
|
|
15
|
+
* 3. The preprocessor checks if the script contains `@derive` decorators
|
|
16
|
+
* 4. If found, it calls the native `macroforge` binding to expand the macros
|
|
17
|
+
* 5. The expanded code replaces the original script content
|
|
18
|
+
*
|
|
19
|
+
* ## Important Notes
|
|
20
|
+
*
|
|
21
|
+
* - Must be placed BEFORE other preprocessors (like `vitePreprocess()`) in the chain
|
|
22
|
+
* - Uses lazy-loading for native bindings to avoid initialization overhead
|
|
23
|
+
* - Gracefully degrades if native bindings are unavailable
|
|
24
|
+
* - Only processes TypeScript blocks by default (configurable via options)
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Cached reference to the native `expandSync` function from the macroforge package.
|
|
30
|
+
*
|
|
31
|
+
* This variable implements a lazy-loading pattern:
|
|
32
|
+
* - Initially `null`, indicating the binding hasn't been loaded yet
|
|
33
|
+
* - Set to the actual function after first successful load
|
|
34
|
+
* - Remains `null` if loading fails (graceful degradation)
|
|
35
|
+
*
|
|
36
|
+
* The lazy-loading approach avoids loading native bindings at module import time,
|
|
37
|
+
* which improves startup performance when the preprocessor is registered but no
|
|
38
|
+
* components contain macros.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
2
42
|
let expandSync = null;
|
|
43
|
+
/**
|
|
44
|
+
* Lazily loads and caches the native `expandSync` function.
|
|
45
|
+
*
|
|
46
|
+
* This function implements the initialization logic for native bindings:
|
|
47
|
+
*
|
|
48
|
+
* 1. On first call, dynamically imports the `macroforge` package
|
|
49
|
+
* 2. Extracts and caches the `expandSync` function
|
|
50
|
+
* 3. On subsequent calls, returns the cached function immediately
|
|
51
|
+
*
|
|
52
|
+
* The function is async because dynamic imports return promises, even though
|
|
53
|
+
* the underlying `expandSync` function is synchronous. This async wrapper
|
|
54
|
+
* only runs once; after initialization, the cached sync function is used directly.
|
|
55
|
+
*
|
|
56
|
+
* ## Error Handling
|
|
57
|
+
*
|
|
58
|
+
* If the native bindings fail to load (e.g., missing native module, architecture
|
|
59
|
+
* mismatch), the function logs a warning and returns `null`. This allows the
|
|
60
|
+
* preprocessor to gracefully skip macro expansion rather than crashing the build.
|
|
61
|
+
*
|
|
62
|
+
* @returns The cached `expandSync` function, or `null` if loading failed
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
3
65
|
async function ensureExpandSync() {
|
|
4
66
|
if (expandSync === null) {
|
|
5
67
|
try {
|
|
68
|
+
// Dynamic import defers loading until first use
|
|
6
69
|
const macroforge = await import("macroforge");
|
|
7
70
|
expandSync = macroforge.expandSync;
|
|
8
71
|
}
|
|
9
72
|
catch (error) {
|
|
73
|
+
// Log warning but don't throw - allows graceful degradation
|
|
10
74
|
console.warn("[@macroforge/svelte-preprocessor] Failed to load macroforge native bindings:", error);
|
|
11
75
|
expandSync = null;
|
|
12
76
|
}
|
|
@@ -14,12 +78,40 @@ async function ensureExpandSync() {
|
|
|
14
78
|
return expandSync;
|
|
15
79
|
}
|
|
16
80
|
/**
|
|
17
|
-
* Creates a Svelte preprocessor that expands
|
|
81
|
+
* Creates a Svelte preprocessor that expands Macroforge macros in `<script>` blocks.
|
|
18
82
|
*
|
|
19
|
-
* This
|
|
20
|
-
*
|
|
83
|
+
* This is the main entry point for integrating Macroforge with Svelte. The returned
|
|
84
|
+
* preprocessor intercepts script blocks, detects `@derive` decorators, and expands
|
|
85
|
+
* them into generated code using the native Macroforge engine.
|
|
21
86
|
*
|
|
22
|
-
*
|
|
87
|
+
* ## Preprocessor Order
|
|
88
|
+
*
|
|
89
|
+
* **Important:** This preprocessor must be placed BEFORE other preprocessors like
|
|
90
|
+
* `vitePreprocess()` in the preprocess array. Macros must be expanded before
|
|
91
|
+
* TypeScript compilation occurs, or the TypeScript compiler will fail on the
|
|
92
|
+
* decorator syntax.
|
|
93
|
+
*
|
|
94
|
+
* ## Processing Logic
|
|
95
|
+
*
|
|
96
|
+
* The preprocessor performs these steps for each script block:
|
|
97
|
+
*
|
|
98
|
+
* 1. **Language Check** - Verifies the script is TypeScript (or JavaScript if enabled)
|
|
99
|
+
* 2. **Quick Scan** - Skips blocks without `@derive` (performance optimization)
|
|
100
|
+
* 3. **Expansion** - Calls the native engine to expand macros
|
|
101
|
+
* 4. **Diagnostics** - Logs any errors or warnings from expansion
|
|
102
|
+
* 5. **Return** - Returns transformed code or `undefined` if unchanged
|
|
103
|
+
*
|
|
104
|
+
* ## Error Handling
|
|
105
|
+
*
|
|
106
|
+
* The preprocessor is designed to be resilient:
|
|
107
|
+
* - If native bindings fail to load, it silently skips processing
|
|
108
|
+
* - If macro expansion throws, it logs a warning and continues
|
|
109
|
+
* - Svelte compilation proceeds even if preprocessing fails
|
|
110
|
+
*
|
|
111
|
+
* @param options - Configuration options for the preprocessor
|
|
112
|
+
* @returns A Svelte `PreprocessorGroup` with name "macroforge" and a script preprocessor
|
|
113
|
+
*
|
|
114
|
+
* @example Basic usage
|
|
23
115
|
* ```js
|
|
24
116
|
* // svelte.config.js
|
|
25
117
|
* import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
@@ -27,37 +119,100 @@ async function ensureExpandSync() {
|
|
|
27
119
|
*
|
|
28
120
|
* export default {
|
|
29
121
|
* preprocess: [
|
|
30
|
-
* macroforgePreprocess(),
|
|
122
|
+
* macroforgePreprocess(), // Expand macros FIRST
|
|
31
123
|
* vitePreprocess() // Then handle TypeScript/CSS
|
|
32
124
|
* ]
|
|
33
125
|
* };
|
|
34
126
|
* ```
|
|
127
|
+
*
|
|
128
|
+
* @example With options
|
|
129
|
+
* ```js
|
|
130
|
+
* // svelte.config.js
|
|
131
|
+
* import { macroforgePreprocess } from '@macroforge/svelte-preprocessor';
|
|
132
|
+
*
|
|
133
|
+
* export default {
|
|
134
|
+
* preprocess: [
|
|
135
|
+
* macroforgePreprocess({
|
|
136
|
+
* keepDecorators: true, // Keep @derive in output for debugging
|
|
137
|
+
* processJavaScript: true // Also process <script> blocks without lang="ts"
|
|
138
|
+
* })
|
|
139
|
+
* ]
|
|
140
|
+
* };
|
|
141
|
+
* ```
|
|
35
142
|
*/
|
|
36
143
|
export function macroforgePreprocess(options = {}) {
|
|
144
|
+
// Destructure options with defaults
|
|
37
145
|
const { keepDecorators = false, processJavaScript = false } = options;
|
|
146
|
+
/**
|
|
147
|
+
* The script preprocessor function that Svelte calls for each `<script>` block.
|
|
148
|
+
*
|
|
149
|
+
* Svelte passes three properties:
|
|
150
|
+
* - `content`: The text content of the script block
|
|
151
|
+
* - `filename`: Path to the .svelte file being processed
|
|
152
|
+
* - `attributes`: Object of attributes from the script tag (e.g., `{ lang: "ts" }`)
|
|
153
|
+
*
|
|
154
|
+
* @returns An object with `code` property if transformed, or `undefined` if no changes
|
|
155
|
+
*/
|
|
38
156
|
const scriptPreprocessor = async ({ content, filename, attributes, }) => {
|
|
39
|
-
|
|
157
|
+
/*
|
|
158
|
+
* STEP 1: Language Detection
|
|
159
|
+
*
|
|
160
|
+
* Determine if this script block should be processed based on its language.
|
|
161
|
+
* Svelte allows both `lang` and `type` attributes for specifying script language.
|
|
162
|
+
*
|
|
163
|
+
* Examples:
|
|
164
|
+
* - <script lang="ts"> → isTypeScript = true
|
|
165
|
+
* - <script lang="typescript"> → isTypeScript = true
|
|
166
|
+
* - <script> → isJavaScript = true (no lang = JavaScript)
|
|
167
|
+
* - <script lang="js"> → isJavaScript = true
|
|
168
|
+
* - <script type="module"> → isJavaScript = true
|
|
169
|
+
*/
|
|
40
170
|
const lang = attributes.lang || attributes.type;
|
|
41
171
|
const isTypeScript = lang === "ts" || lang === "typescript";
|
|
42
172
|
const isJavaScript = !lang || lang === "js" || lang === "javascript" || lang === "module";
|
|
173
|
+
// Skip non-TypeScript blocks unless processJavaScript is enabled
|
|
43
174
|
if (!isTypeScript && !(processJavaScript && isJavaScript)) {
|
|
44
|
-
return; // Return undefined = no changes
|
|
175
|
+
return; // Return undefined = no changes, Svelte keeps original content
|
|
45
176
|
}
|
|
46
|
-
|
|
177
|
+
/*
|
|
178
|
+
* STEP 2: Quick Scan Optimization
|
|
179
|
+
*
|
|
180
|
+
* Before loading native bindings, do a cheap string check for "@derive".
|
|
181
|
+
* Most components won't have macros, so this saves the cost of loading
|
|
182
|
+
* and calling the native expansion engine in the common case.
|
|
183
|
+
*/
|
|
47
184
|
if (!content.includes("@derive")) {
|
|
48
185
|
return;
|
|
49
186
|
}
|
|
50
|
-
|
|
187
|
+
/*
|
|
188
|
+
* STEP 3: Load Native Bindings
|
|
189
|
+
*
|
|
190
|
+
* The expansion engine is a native module (Rust compiled to Node addon).
|
|
191
|
+
* We lazy-load it on first use to avoid startup overhead.
|
|
192
|
+
*/
|
|
51
193
|
const expand = await ensureExpandSync();
|
|
52
194
|
if (!expand) {
|
|
53
|
-
// Native bindings
|
|
195
|
+
// Native bindings unavailable (missing module, architecture mismatch, etc.)
|
|
196
|
+
// Silently skip - the component will fail later if macros are actually needed
|
|
54
197
|
return;
|
|
55
198
|
}
|
|
56
199
|
try {
|
|
200
|
+
/*
|
|
201
|
+
* STEP 4: Macro Expansion
|
|
202
|
+
*
|
|
203
|
+
* Call the native engine to parse the TypeScript, find @derive decorators,
|
|
204
|
+
* and generate the expanded code with all macro-derived methods/properties.
|
|
205
|
+
*/
|
|
57
206
|
const result = expand(content, filename || "component.svelte", {
|
|
58
207
|
keepDecorators,
|
|
59
208
|
});
|
|
60
|
-
|
|
209
|
+
/*
|
|
210
|
+
* STEP 5: Diagnostic Reporting
|
|
211
|
+
*
|
|
212
|
+
* The expansion engine may report errors (invalid macro syntax, unknown macros)
|
|
213
|
+
* or warnings (deprecated patterns, suggestions). Log these to help developers
|
|
214
|
+
* debug issues without failing the build.
|
|
215
|
+
*/
|
|
61
216
|
for (const diag of result.diagnostics) {
|
|
62
217
|
if (diag.level === "error") {
|
|
63
218
|
console.error(`[@macroforge/svelte-preprocessor] Error in ${filename}: ${diag.message}`);
|
|
@@ -66,23 +221,59 @@ export function macroforgePreprocess(options = {}) {
|
|
|
66
221
|
console.warn(`[@macroforge/svelte-preprocessor] Warning in ${filename}: ${diag.message}`);
|
|
67
222
|
}
|
|
68
223
|
}
|
|
69
|
-
|
|
224
|
+
/*
|
|
225
|
+
* STEP 6: Return Transformed Code
|
|
226
|
+
*
|
|
227
|
+
* Only return a result if the code was actually modified. Returning undefined
|
|
228
|
+
* tells Svelte to keep the original content, which is more efficient than
|
|
229
|
+
* returning identical code.
|
|
230
|
+
*
|
|
231
|
+
* The return object can include:
|
|
232
|
+
* - code: The transformed source code (required)
|
|
233
|
+
* - map: Source map for debugging (optional, not yet implemented)
|
|
234
|
+
*/
|
|
70
235
|
if (result.code && result.code !== content) {
|
|
71
236
|
return {
|
|
72
237
|
code: result.code,
|
|
73
|
-
// TODO: Add source map support when expandSync provides
|
|
238
|
+
// TODO: Add source map support when expandSync provides mappings
|
|
239
|
+
// map: result.source_mapping
|
|
74
240
|
};
|
|
75
241
|
}
|
|
76
242
|
}
|
|
77
243
|
catch (error) {
|
|
78
|
-
|
|
244
|
+
/*
|
|
245
|
+
* Error Recovery
|
|
246
|
+
*
|
|
247
|
+
* If expansion throws (parser error, internal bug, etc.), log a warning
|
|
248
|
+
* but don't fail the build. This allows:
|
|
249
|
+
* - Partial builds during development
|
|
250
|
+
* - Graceful degradation if the macro engine has issues
|
|
251
|
+
* - Svelte's own error reporting to kick in for syntax errors
|
|
252
|
+
*/
|
|
79
253
|
console.warn(`[@macroforge/svelte-preprocessor] Failed to expand macros in ${filename}:`, error instanceof Error ? error.message : String(error));
|
|
80
254
|
}
|
|
81
|
-
|
|
255
|
+
// No changes - either expansion produced identical output or an error occurred
|
|
256
|
+
return;
|
|
82
257
|
};
|
|
258
|
+
/*
|
|
259
|
+
* Return the PreprocessorGroup object that Svelte expects.
|
|
260
|
+
*
|
|
261
|
+
* - name: Identifier shown in Svelte's debug output and error messages
|
|
262
|
+
* - script: The preprocessor function for <script> blocks
|
|
263
|
+
*
|
|
264
|
+
* Note: We only handle script blocks, not markup or style blocks.
|
|
265
|
+
*/
|
|
83
266
|
return {
|
|
84
267
|
name: "macroforge",
|
|
85
268
|
script: scriptPreprocessor,
|
|
86
269
|
};
|
|
87
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Default export for convenient importing.
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```js
|
|
276
|
+
* import macroforgePreprocess from '@macroforge/svelte-preprocessor';
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
88
279
|
export default macroforgePreprocess;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@macroforge/svelte-preprocessor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Svelte preprocessor for expanding Macroforge macros in component script blocks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"test": "npm run build && node --test tests/**/*.test.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"macroforge": "^0.1.
|
|
32
|
+
"macroforge": "^0.1.35"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"svelte": "^5.0.0"
|