gonia 0.0.3 → 0.1.0
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/dist/vite/index.d.ts +1 -0
- package/dist/vite/plugin.d.ts +41 -6
- package/dist/vite/plugin.js +152 -42
- package/package.json +1 -1
package/dist/vite/index.d.ts
CHANGED
package/dist/vite/plugin.d.ts
CHANGED
|
@@ -2,18 +2,41 @@
|
|
|
2
2
|
* Vite plugin for gonia.js.
|
|
3
3
|
*
|
|
4
4
|
* @remarks
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* - Auto-detects directive usage in templates and injects imports
|
|
6
|
+
* - Transforms directive functions to add $inject arrays at build time
|
|
7
|
+
* - Configures Vite for SSR with gonia.js
|
|
7
8
|
*
|
|
8
9
|
* @packageDocumentation
|
|
9
10
|
*/
|
|
10
11
|
import type { Plugin } from 'vite';
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
+
* Plugin options.
|
|
14
|
+
*/
|
|
15
|
+
export interface GoniaPluginOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Automatically detect and import directives from source code.
|
|
18
|
+
* @defaultValue true
|
|
19
|
+
*/
|
|
20
|
+
autoDirectives?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Additional directives to include (for runtime/dynamic cases).
|
|
23
|
+
* Use directive names without the 'g-' prefix.
|
|
24
|
+
* @example ['text', 'for', 'if']
|
|
25
|
+
*/
|
|
26
|
+
includeDirectives?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Directives to exclude from auto-detection.
|
|
29
|
+
* Use directive names without the 'g-' prefix.
|
|
30
|
+
*/
|
|
31
|
+
excludeDirectives?: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Gonia Vite plugin.
|
|
13
35
|
*
|
|
14
36
|
* @remarks
|
|
15
|
-
*
|
|
16
|
-
*
|
|
37
|
+
* - Auto-detects directive usage and injects imports
|
|
38
|
+
* - Adds $inject arrays to directive functions for minification safety
|
|
39
|
+
* - Configures Vite for SSR with gonia.js
|
|
17
40
|
*
|
|
18
41
|
* @example
|
|
19
42
|
* ```ts
|
|
@@ -25,6 +48,18 @@ import type { Plugin } from 'vite';
|
|
|
25
48
|
* plugins: [gonia()]
|
|
26
49
|
* });
|
|
27
50
|
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* // With options
|
|
55
|
+
* export default defineConfig({
|
|
56
|
+
* plugins: [gonia({
|
|
57
|
+
* autoDirectives: true,
|
|
58
|
+
* includeDirectives: ['text', 'for'], // For dynamic/runtime HTML
|
|
59
|
+
* excludeDirectives: ['model'], // Never include these
|
|
60
|
+
* })]
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
28
63
|
*/
|
|
29
|
-
export declare function gonia(): Plugin;
|
|
64
|
+
export declare function gonia(options?: GoniaPluginOptions): Plugin;
|
|
30
65
|
export default gonia;
|
package/dist/vite/plugin.js
CHANGED
|
@@ -2,60 +2,108 @@
|
|
|
2
2
|
* Vite plugin for gonia.js.
|
|
3
3
|
*
|
|
4
4
|
* @remarks
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* - Auto-detects directive usage in templates and injects imports
|
|
6
|
+
* - Transforms directive functions to add $inject arrays at build time
|
|
7
|
+
* - Configures Vite for SSR with gonia.js
|
|
7
8
|
*
|
|
8
9
|
* @packageDocumentation
|
|
9
10
|
*/
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Map of directive names to their export names from gonia.
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
const DIRECTIVE_MAP = {
|
|
15
|
+
text: 'text',
|
|
16
|
+
html: 'html',
|
|
17
|
+
show: 'show',
|
|
18
|
+
template: 'template',
|
|
19
|
+
slot: 'slot',
|
|
20
|
+
class: 'cclass',
|
|
21
|
+
model: 'model',
|
|
22
|
+
on: 'on',
|
|
23
|
+
for: 'cfor',
|
|
24
|
+
if: 'cif',
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Detect directive names used in source code.
|
|
28
|
+
*/
|
|
29
|
+
function detectDirectives(code, id, isDev) {
|
|
30
|
+
const found = new Set();
|
|
31
|
+
// Pattern 1: g-name as attribute in template literals or strings
|
|
32
|
+
// Matches: g-text, g-for, g-if, etc.
|
|
33
|
+
const attrPattern = /g-([a-z]+)/g;
|
|
34
|
+
let match;
|
|
35
|
+
while ((match = attrPattern.exec(code)) !== null) {
|
|
36
|
+
const name = match[1];
|
|
37
|
+
if (DIRECTIVE_MAP[name]) {
|
|
38
|
+
found.add(name);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Pattern 2: Dynamic directive names we can resolve
|
|
42
|
+
// Matches: `g-${expr}` where expr is a string literal or simple variable
|
|
43
|
+
const dynamicPattern = /`g-\$\{([^}]+)\}`/g;
|
|
44
|
+
while ((match = dynamicPattern.exec(code)) !== null) {
|
|
45
|
+
const expr = match[1].trim();
|
|
46
|
+
// Try to resolve simple string literals
|
|
47
|
+
if (/^['"]([a-z]+)['"]$/.test(expr)) {
|
|
48
|
+
const name = expr.slice(1, -1);
|
|
49
|
+
if (DIRECTIVE_MAP[name]) {
|
|
50
|
+
found.add(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(expr)) {
|
|
54
|
+
// It's a variable - try to find its value
|
|
55
|
+
const varPattern = new RegExp(`(?:const|let|var)\\s+${expr}\\s*=\\s*['"]([a-z]+)['"]`);
|
|
56
|
+
const varMatch = code.match(varPattern);
|
|
57
|
+
if (varMatch && DIRECTIVE_MAP[varMatch[1]]) {
|
|
58
|
+
found.add(varMatch[1]);
|
|
59
|
+
}
|
|
60
|
+
else if (isDev) {
|
|
61
|
+
console.warn(`[gonia] Could not resolve directive name in \`g-\${${expr}}\` at ${id}\n` +
|
|
62
|
+
` Add to vite config: includeDirectives: ['expected-directive']`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return found;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Generate import statement for detected directives.
|
|
70
|
+
*/
|
|
71
|
+
function generateDirectiveImports(directives) {
|
|
72
|
+
if (directives.size === 0)
|
|
73
|
+
return '';
|
|
74
|
+
const imports = [];
|
|
75
|
+
for (const name of directives) {
|
|
76
|
+
const exportName = DIRECTIVE_MAP[name];
|
|
77
|
+
if (exportName) {
|
|
78
|
+
imports.push(exportName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (imports.length === 0)
|
|
82
|
+
return '';
|
|
83
|
+
// Import from gonia/directives which auto-registers
|
|
84
|
+
return `import { ${imports.join(', ')} } from 'gonia/directives';\n`;
|
|
29
85
|
}
|
|
30
86
|
/**
|
|
31
87
|
* Transform source code to add $inject arrays to directive functions.
|
|
32
88
|
*/
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!/\.(ts|js|tsx|jsx)$/.test(id))
|
|
38
|
-
return null;
|
|
39
|
-
// Skip if no directive calls
|
|
40
|
-
if (!code.includes('directive('))
|
|
41
|
-
return null;
|
|
89
|
+
function transformInject(code, id) {
|
|
90
|
+
if (!code.includes('directive(')) {
|
|
91
|
+
return { code, modified: false };
|
|
92
|
+
}
|
|
42
93
|
let result = code;
|
|
43
94
|
let modified = false;
|
|
44
|
-
// Pattern: directive('name', functionName, ...)
|
|
45
|
-
// We need to find the function and add $inject to it
|
|
46
95
|
const directiveCallPattern = /directive\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
|
|
47
96
|
const functionNames = new Set();
|
|
48
97
|
let match;
|
|
49
98
|
while ((match = directiveCallPattern.exec(code)) !== null) {
|
|
50
99
|
functionNames.add(match[2]);
|
|
51
100
|
}
|
|
52
|
-
if (functionNames.size === 0)
|
|
53
|
-
return
|
|
101
|
+
if (functionNames.size === 0) {
|
|
102
|
+
return { code, modified: false };
|
|
103
|
+
}
|
|
54
104
|
for (const fnName of functionNames) {
|
|
55
|
-
// Skip if already has $inject
|
|
56
105
|
if (code.includes(`${fnName}.$inject`))
|
|
57
106
|
continue;
|
|
58
|
-
// Find function declaration: function fnName(params) or const fnName = (params) =>
|
|
59
107
|
const fnDeclPattern = new RegExp(`(?:function\\s+${fnName}\\s*\\(([^)]*)\\)|(?:const|let|var)\\s+${fnName}\\s*=\\s*(?:async\\s*)?(?:function\\s*)?\\(([^)]*)\\))`, 'g');
|
|
60
108
|
const fnMatch = fnDeclPattern.exec(code);
|
|
61
109
|
if (!fnMatch)
|
|
@@ -71,20 +119,20 @@ function transformCode(code, id) {
|
|
|
71
119
|
.filter(Boolean);
|
|
72
120
|
if (params.length === 0)
|
|
73
121
|
continue;
|
|
74
|
-
// Find the directive() call and insert $inject before it
|
|
75
122
|
const directivePattern = new RegExp(`(directive\\s*\\(\\s*['"\`][^'"\`]+['"\`]\\s*,\\s*${fnName})`, 'g');
|
|
76
123
|
const injectStatement = `${fnName}.$inject = ${JSON.stringify(params)};\n`;
|
|
77
124
|
result = result.replace(directivePattern, `${injectStatement}$1`);
|
|
78
125
|
modified = true;
|
|
79
126
|
}
|
|
80
|
-
return
|
|
127
|
+
return { code: result, modified };
|
|
81
128
|
}
|
|
82
129
|
/**
|
|
83
|
-
*
|
|
130
|
+
* Gonia Vite plugin.
|
|
84
131
|
*
|
|
85
132
|
* @remarks
|
|
86
|
-
*
|
|
87
|
-
*
|
|
133
|
+
* - Auto-detects directive usage and injects imports
|
|
134
|
+
* - Adds $inject arrays to directive functions for minification safety
|
|
135
|
+
* - Configures Vite for SSR with gonia.js
|
|
88
136
|
*
|
|
89
137
|
* @example
|
|
90
138
|
* ```ts
|
|
@@ -96,14 +144,76 @@ function transformCode(code, id) {
|
|
|
96
144
|
* plugins: [gonia()]
|
|
97
145
|
* });
|
|
98
146
|
* ```
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* // With options
|
|
151
|
+
* export default defineConfig({
|
|
152
|
+
* plugins: [gonia({
|
|
153
|
+
* autoDirectives: true,
|
|
154
|
+
* includeDirectives: ['text', 'for'], // For dynamic/runtime HTML
|
|
155
|
+
* excludeDirectives: ['model'], // Never include these
|
|
156
|
+
* })]
|
|
157
|
+
* });
|
|
158
|
+
* ```
|
|
99
159
|
*/
|
|
100
|
-
export function gonia() {
|
|
160
|
+
export function gonia(options = {}) {
|
|
161
|
+
const { autoDirectives = true, includeDirectives = [], excludeDirectives = [], } = options;
|
|
162
|
+
let isDev = false;
|
|
163
|
+
// Track which directives have been injected per chunk
|
|
164
|
+
const injectedModules = new Set();
|
|
101
165
|
return {
|
|
102
166
|
name: 'gonia',
|
|
103
167
|
enforce: 'pre',
|
|
168
|
+
configResolved(config) {
|
|
169
|
+
isDev = config.command === 'serve';
|
|
170
|
+
},
|
|
104
171
|
transform(code, id) {
|
|
105
|
-
|
|
106
|
-
|
|
172
|
+
// Skip node_modules (except for $inject transform in gonia itself)
|
|
173
|
+
const isGoniaInternal = id.includes('gonia') && id.includes('node_modules');
|
|
174
|
+
if (id.includes('node_modules') && !isGoniaInternal)
|
|
175
|
+
return null;
|
|
176
|
+
if (!/\.(ts|js|tsx|jsx|html)$/.test(id))
|
|
177
|
+
return null;
|
|
178
|
+
let result = code;
|
|
179
|
+
let modified = false;
|
|
180
|
+
// Collect directives to import
|
|
181
|
+
if (!isGoniaInternal) {
|
|
182
|
+
const detected = new Set();
|
|
183
|
+
// Auto-detect directives if enabled
|
|
184
|
+
if (autoDirectives) {
|
|
185
|
+
for (const name of detectDirectives(code, id, isDev)) {
|
|
186
|
+
detected.add(name);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Add explicitly included directives (always, regardless of autoDirectives)
|
|
190
|
+
for (const name of includeDirectives) {
|
|
191
|
+
detected.add(name);
|
|
192
|
+
}
|
|
193
|
+
// Remove excluded directives
|
|
194
|
+
for (const name of excludeDirectives) {
|
|
195
|
+
detected.delete(name);
|
|
196
|
+
}
|
|
197
|
+
// Generate imports if we found directives and haven't already
|
|
198
|
+
if (detected.size > 0 && !injectedModules.has(id)) {
|
|
199
|
+
// Check if this file already imports from gonia/directives
|
|
200
|
+
if (!code.includes("from 'gonia/directives'") && !code.includes('from "gonia/directives"')) {
|
|
201
|
+
const importStatement = generateDirectiveImports(detected);
|
|
202
|
+
if (importStatement) {
|
|
203
|
+
result = importStatement + result;
|
|
204
|
+
modified = true;
|
|
205
|
+
injectedModules.add(id);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Transform $inject arrays
|
|
211
|
+
const injectResult = transformInject(result, id);
|
|
212
|
+
if (injectResult.modified) {
|
|
213
|
+
result = injectResult.code;
|
|
214
|
+
modified = true;
|
|
215
|
+
}
|
|
216
|
+
if (modified) {
|
|
107
217
|
return {
|
|
108
218
|
code: result,
|
|
109
219
|
map: null // TODO: proper source map support
|