puglite 1.0.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/README.md +115 -0
- package/angular-webpack/index.js +27 -0
- package/angular-webpack/loader.js +37 -0
- package/builders/browser/index.js +49 -0
- package/builders/browser/schema.json +138 -0
- package/builders/dev-server/index.js +48 -0
- package/builders/dev-server/schema.json +98 -0
- package/builders/karma/README.md +82 -0
- package/builders/karma/index.js +40 -0
- package/builders/karma/schema.json +260 -0
- package/builders/vitest/README.md +218 -0
- package/builders/vitest/index.js +98 -0
- package/builders/vitest/schema.json +8 -0
- package/builders.json +25 -0
- package/lib/attrs.js +150 -0
- package/lib/build.js +27 -0
- package/lib/code-gen.js +769 -0
- package/lib/error.js +56 -0
- package/lib/index.js +416 -0
- package/lib/lexer.d.ts +366 -0
- package/lib/lexer.js +1713 -0
- package/lib/parser-lib/inline-tags.js +23 -0
- package/lib/parser.js +1299 -0
- package/lib/prepublish.js +70 -0
- package/lib/runtime-build.js +27 -0
- package/lib/runtime-lib/dependencies.js +34 -0
- package/lib/runtime-lib/internals.js +8 -0
- package/lib/runtime-lib/sources.js +13 -0
- package/lib/runtime-wrap.js +10 -0
- package/lib/runtime.js +287 -0
- package/lib/strip-comments.js +77 -0
- package/lib/wrap.js +10 -0
- package/package.json +72 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Puglite Karma Test Builder",
|
|
4
|
+
"description": "Karma test runner with Puglite template support",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"main": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the main entry-point file."
|
|
10
|
+
},
|
|
11
|
+
"tsConfig": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "The name of the TypeScript configuration file."
|
|
14
|
+
},
|
|
15
|
+
"karmaConfig": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The name of the Karma configuration file."
|
|
18
|
+
},
|
|
19
|
+
"polyfills": {
|
|
20
|
+
"description": "A list of polyfills to include in the build.",
|
|
21
|
+
"oneOf": [
|
|
22
|
+
{
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"type": "string"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"assets": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"description": "List of static application assets.",
|
|
36
|
+
"default": [],
|
|
37
|
+
"items": {
|
|
38
|
+
"oneOf": [
|
|
39
|
+
{
|
|
40
|
+
"type": "string"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "object",
|
|
44
|
+
"properties": {
|
|
45
|
+
"glob": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"description": "The pattern to match."
|
|
48
|
+
},
|
|
49
|
+
"input": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "The input directory path in which to apply 'glob'."
|
|
52
|
+
},
|
|
53
|
+
"output": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "Absolute path within the output."
|
|
56
|
+
},
|
|
57
|
+
"ignore": {
|
|
58
|
+
"description": "An array of globs to ignore.",
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "string"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"required": ["glob", "input", "output"]
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"styles": {
|
|
72
|
+
"description": "Global styles to be included in the build.",
|
|
73
|
+
"type": "array",
|
|
74
|
+
"default": [],
|
|
75
|
+
"items": {
|
|
76
|
+
"oneOf": [
|
|
77
|
+
{
|
|
78
|
+
"type": "string"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {
|
|
83
|
+
"input": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"description": "The file to include."
|
|
86
|
+
},
|
|
87
|
+
"bundleName": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"pattern": "^[\\w\\-.]*$",
|
|
90
|
+
"description": "The bundle name for this extra entry point."
|
|
91
|
+
},
|
|
92
|
+
"inject": {
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"description": "If the bundle will be referenced in the HTML file.",
|
|
95
|
+
"default": true
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"additionalProperties": false,
|
|
99
|
+
"required": ["input"]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"scripts": {
|
|
105
|
+
"description": "Global scripts to be included in the build.",
|
|
106
|
+
"type": "array",
|
|
107
|
+
"default": [],
|
|
108
|
+
"items": {
|
|
109
|
+
"oneOf": [
|
|
110
|
+
{
|
|
111
|
+
"type": "string"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "object",
|
|
115
|
+
"properties": {
|
|
116
|
+
"input": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "The file to include."
|
|
119
|
+
},
|
|
120
|
+
"bundleName": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"pattern": "^[\\w\\-.]*$",
|
|
123
|
+
"description": "The bundle name for this extra entry point."
|
|
124
|
+
},
|
|
125
|
+
"inject": {
|
|
126
|
+
"type": "boolean",
|
|
127
|
+
"description": "If the bundle will be referenced in the HTML file.",
|
|
128
|
+
"default": true
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"additionalProperties": false,
|
|
132
|
+
"required": ["input"]
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"sourceMap": {
|
|
138
|
+
"description": "Output source maps for scripts and styles.",
|
|
139
|
+
"default": true,
|
|
140
|
+
"oneOf": [
|
|
141
|
+
{
|
|
142
|
+
"type": "boolean"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"scripts": {
|
|
148
|
+
"type": "boolean",
|
|
149
|
+
"description": "Output source maps for all scripts.",
|
|
150
|
+
"default": true
|
|
151
|
+
},
|
|
152
|
+
"styles": {
|
|
153
|
+
"type": "boolean",
|
|
154
|
+
"description": "Output source maps for all styles.",
|
|
155
|
+
"default": true
|
|
156
|
+
},
|
|
157
|
+
"vendor": {
|
|
158
|
+
"type": "boolean",
|
|
159
|
+
"description": "Output source maps for vendor libraries.",
|
|
160
|
+
"default": false
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"additionalProperties": false
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
"progress": {
|
|
168
|
+
"type": "boolean",
|
|
169
|
+
"description": "Log progress to the console while building."
|
|
170
|
+
},
|
|
171
|
+
"watch": {
|
|
172
|
+
"type": "boolean",
|
|
173
|
+
"description": "Run build when files change."
|
|
174
|
+
},
|
|
175
|
+
"poll": {
|
|
176
|
+
"type": "number",
|
|
177
|
+
"description": "Enable and define the file watching poll time period in milliseconds."
|
|
178
|
+
},
|
|
179
|
+
"preserveSymlinks": {
|
|
180
|
+
"type": "boolean",
|
|
181
|
+
"description": "Do not use the real path when resolving modules."
|
|
182
|
+
},
|
|
183
|
+
"browsers": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"description": "Override which browsers tests are run against."
|
|
186
|
+
},
|
|
187
|
+
"codeCoverage": {
|
|
188
|
+
"type": "boolean",
|
|
189
|
+
"description": "Output a code coverage report.",
|
|
190
|
+
"default": false
|
|
191
|
+
},
|
|
192
|
+
"codeCoverageExclude": {
|
|
193
|
+
"type": "array",
|
|
194
|
+
"description": "Globs to exclude from code coverage.",
|
|
195
|
+
"items": {
|
|
196
|
+
"type": "string"
|
|
197
|
+
},
|
|
198
|
+
"default": []
|
|
199
|
+
},
|
|
200
|
+
"fileReplacements": {
|
|
201
|
+
"description": "Replace compilation source files with other compilation source files in the build.",
|
|
202
|
+
"type": "array",
|
|
203
|
+
"items": {
|
|
204
|
+
"oneOf": [
|
|
205
|
+
{
|
|
206
|
+
"type": "object",
|
|
207
|
+
"properties": {
|
|
208
|
+
"src": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"pattern": "\\.(([cm]?j|t)sx?|json)$"
|
|
211
|
+
},
|
|
212
|
+
"replaceWith": {
|
|
213
|
+
"type": "string",
|
|
214
|
+
"pattern": "\\.(([cm]?j|t)sx?|json)$"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"additionalProperties": false,
|
|
218
|
+
"required": ["src", "replaceWith"]
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"type": "object",
|
|
222
|
+
"properties": {
|
|
223
|
+
"replace": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"pattern": "\\.(([cm]?j|t)sx?|json)$"
|
|
226
|
+
},
|
|
227
|
+
"with": {
|
|
228
|
+
"type": "string",
|
|
229
|
+
"pattern": "\\.(([cm]?j|t)sx?|json)$"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"additionalProperties": false,
|
|
233
|
+
"required": ["replace", "with"]
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
"default": []
|
|
238
|
+
},
|
|
239
|
+
"include": {
|
|
240
|
+
"type": "array",
|
|
241
|
+
"description": "Globs of files to include, relative to workspace or project root.",
|
|
242
|
+
"items": {
|
|
243
|
+
"type": "string"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"exclude": {
|
|
247
|
+
"type": "array",
|
|
248
|
+
"description": "Globs of files to exclude, relative to the workspace or project root.",
|
|
249
|
+
"items": {
|
|
250
|
+
"type": "string"
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"webWorkerTsConfig": {
|
|
254
|
+
"type": "string",
|
|
255
|
+
"description": "TypeScript configuration for Web Worker modules."
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
"additionalProperties": false,
|
|
259
|
+
"required": ["karmaConfig"]
|
|
260
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Puglite Vitest Builder
|
|
2
|
+
|
|
3
|
+
Angular builder that runs Vitest with Pug template support.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
In `angular.json`:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"architect": {
|
|
12
|
+
"test": {
|
|
13
|
+
"builder": "puglite:vitest",
|
|
14
|
+
"options": {}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Run tests:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
ng test # Run all tests via builder
|
|
24
|
+
npx vitest <file> # Run specific test file directly
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
The builder:
|
|
30
|
+
1. Calls Vitest's `startVitest()` API directly
|
|
31
|
+
2. Injects a Vite plugin to transform `.pug` files to HTML strings
|
|
32
|
+
3. Enables `jsdom` environment for browser API support (localStorage, window, etc.)
|
|
33
|
+
|
|
34
|
+
## Important: You Probably Don't Need Pug Plugin for Tests
|
|
35
|
+
|
|
36
|
+
**Best practice:** Test component logic only, without importing templates.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// ✅ Test component logic only - NO template imports needed
|
|
40
|
+
describe('UploadImgComponent', () => {
|
|
41
|
+
let component: UploadImgComponent;
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
const mockService = { upload: vi.fn() };
|
|
45
|
+
component = new UploadImgComponent(mockService); // No TestBed
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should update state', () => {
|
|
49
|
+
component.uploadState.set({ status: 'uploading', progress: 50 });
|
|
50
|
+
expect(component.isUploading()).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Template/UI testing happens in E2E:**
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// e2e/upload.spec.ts
|
|
59
|
+
test('should display upload progress', async ({ page }) => {
|
|
60
|
+
await page.goto('/upload');
|
|
61
|
+
await expect(page.locator('.progress')).toHaveText('50%');
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## When You DO Need Pug Plugin
|
|
66
|
+
|
|
67
|
+
Only if you want to import pug templates in tests (NOT recommended):
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import template from './component.pug'; // ← Requires pug plugin
|
|
71
|
+
|
|
72
|
+
@Component({
|
|
73
|
+
selector: 'app-test',
|
|
74
|
+
template: template, // Inline template from import
|
|
75
|
+
})
|
|
76
|
+
class TestComponent extends RealComponent {}
|
|
77
|
+
|
|
78
|
+
TestBed.configureTestingModule({ imports: [TestComponent] })
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Why NOT recommended:**
|
|
82
|
+
- Still requires TestBed (complex setup)
|
|
83
|
+
- Adds unnecessary complexity
|
|
84
|
+
- Better separation: logic in Vitest, UI in E2E
|
|
85
|
+
|
|
86
|
+
## Pug Template Support (Advanced)
|
|
87
|
+
|
|
88
|
+
If you still want to import pug files in tests, the builder's plugin supports it.
|
|
89
|
+
|
|
90
|
+
**✅ Works:** Import pug files as ES modules
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import template from './component.pug';
|
|
94
|
+
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'app-test',
|
|
97
|
+
template: template, // Inline template from import
|
|
98
|
+
})
|
|
99
|
+
class TestComponent extends RealComponent {}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**❌ Doesn't work:** TestBed with external templateUrl
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// This will FAIL in Vitest
|
|
106
|
+
@Component({
|
|
107
|
+
templateUrl: './component.pug' // External template
|
|
108
|
+
})
|
|
109
|
+
class RealComponent {}
|
|
110
|
+
|
|
111
|
+
TestBed.configureTestingModule({ imports: [RealComponent] })
|
|
112
|
+
.compileComponents(); // Error: Component not resolved
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
See `angular-puglite-demo/src/app/app-templateurl.spec.ts` for a concrete example.
|
|
116
|
+
|
|
117
|
+
## TestBed Limitation
|
|
118
|
+
|
|
119
|
+
**TestBed does NOT work with external templates (`.pug` or `.html`) in Vitest.**
|
|
120
|
+
|
|
121
|
+
### Why?
|
|
122
|
+
|
|
123
|
+
- **TestBed's `compileComponents()`** expects to **fetch** external templates like a browser (HTTP requests)
|
|
124
|
+
- **Vitest** runs in Node.js with **no dev server** (unlike Karma which runs in real browser)
|
|
125
|
+
- **Vite plugins** transform ES module **imports** (`import x from 'file.pug'`), but TestBed uses file path strings (`templateUrl: 'file.pug'`)
|
|
126
|
+
- These are two different systems that never connect
|
|
127
|
+
|
|
128
|
+
### Recommended Patterns
|
|
129
|
+
|
|
130
|
+
**Don't use TestBed in Vitest.** Follow these patterns:
|
|
131
|
+
|
|
132
|
+
#### 1. Service Tests (✅ Recommended)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
describe('MyService', () => {
|
|
136
|
+
let service: MyService;
|
|
137
|
+
|
|
138
|
+
beforeEach(() => {
|
|
139
|
+
const httpMock = { get: vi.fn(), post: vi.fn() };
|
|
140
|
+
service = new MyService(httpMock); // Manual instantiation
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should fetch data', () => {
|
|
144
|
+
// Test service logic
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### 2. Component Logic Tests (✅ Recommended)
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
describe('MyComponent', () => {
|
|
153
|
+
let component: MyComponent;
|
|
154
|
+
|
|
155
|
+
beforeEach(() => {
|
|
156
|
+
const mockService = { getData: vi.fn() };
|
|
157
|
+
component = new MyComponent(mockService); // No TestBed
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should update state', () => {
|
|
161
|
+
// Test component methods, signals, computed values
|
|
162
|
+
expect(component.items()).toEqual([]);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### 3. Template/UI Tests (✅ Use E2E)
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// e2e/my-component.spec.ts (Playwright)
|
|
171
|
+
test('should display items', async ({ page }) => {
|
|
172
|
+
await page.goto('/my-component');
|
|
173
|
+
await expect(page.locator('.item')).toBeVisible();
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Alternative: Use Vitest Directly
|
|
178
|
+
|
|
179
|
+
Instead of using this builder, you can run Vitest directly:
|
|
180
|
+
|
|
181
|
+
**package.json:**
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"scripts": {
|
|
185
|
+
"test": "vitest run",
|
|
186
|
+
"test:watch": "vitest",
|
|
187
|
+
"test:ui": "vitest --ui"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**vitest.config.ts:**
|
|
193
|
+
```typescript
|
|
194
|
+
import { defineConfig } from 'vitest/config';
|
|
195
|
+
|
|
196
|
+
export default defineConfig({
|
|
197
|
+
test: {
|
|
198
|
+
environment: 'jsdom',
|
|
199
|
+
globals: true,
|
|
200
|
+
setupFiles: ['src/test-setup.ts']
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**No pug plugin needed** - just test component logic with `new Component()`.
|
|
206
|
+
|
|
207
|
+
## Summary
|
|
208
|
+
|
|
209
|
+
| What | Vitest (logic) | E2E (Playwright) |
|
|
210
|
+
|------|----------------|------------------|
|
|
211
|
+
| Service logic | ✅ `new Service()` | ❌ |
|
|
212
|
+
| Component logic | ✅ `new Component()` | ❌ |
|
|
213
|
+
| Template rendering | ❌ | ✅ |
|
|
214
|
+
| User interactions | ❌ | ✅ |
|
|
215
|
+
| DOM assertions | ❌ | ✅ |
|
|
216
|
+
| Pug plugin needed | ❌ No | N/A |
|
|
217
|
+
|
|
218
|
+
**Recommended: Use Vitest for logic, E2E for UI. No pug plugin needed.**
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puglite Vitest Builder
|
|
3
|
+
*
|
|
4
|
+
* Angular builder that runs Vitest with Pug template transformation.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Transforms .pug files to HTML strings via Vite plugin
|
|
8
|
+
* - Enables jsdom environment for browser API support
|
|
9
|
+
* - Supports file filters for running specific tests
|
|
10
|
+
*
|
|
11
|
+
* Limitation:
|
|
12
|
+
* - TestBed with external templates does NOT work in Vitest
|
|
13
|
+
* - See README.md for recommended testing patterns
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const { createRequire } = require('module');
|
|
18
|
+
const { readFileSync } = require('fs');
|
|
19
|
+
const debug = require('util').debuglog('puglite');
|
|
20
|
+
|
|
21
|
+
const projectRequire = createRequire(path.join(process.cwd(), 'package.json'));
|
|
22
|
+
|
|
23
|
+
async function* buildVitest(options, context) {
|
|
24
|
+
debug('buildVitest() called');
|
|
25
|
+
const { startVitest } = projectRequire('vitest/node');
|
|
26
|
+
|
|
27
|
+
// Get file filters from CLI args
|
|
28
|
+
const cliArgs = process.argv.slice(2).filter(arg => !arg.startsWith('--') && arg.endsWith('.spec.ts'));
|
|
29
|
+
const filters = options.include || cliArgs;
|
|
30
|
+
|
|
31
|
+
// Load puglite compiler modules
|
|
32
|
+
const libPath = path.resolve(__dirname, '../../lib');
|
|
33
|
+
const lex = require(`${libPath}/lexer`);
|
|
34
|
+
const parse = require(`${libPath}/parser`);
|
|
35
|
+
const generateCode = require(`${libPath}/code-gen`);
|
|
36
|
+
const stripComments = require(`${libPath}/strip-comments`);
|
|
37
|
+
const runtimeWrap = require(`${libPath}/runtime-wrap`);
|
|
38
|
+
|
|
39
|
+
// Vite plugin: Transform .pug imports to HTML strings
|
|
40
|
+
const pugVitePlugin = {
|
|
41
|
+
name: 'puglite-vitest',
|
|
42
|
+
enforce: 'pre',
|
|
43
|
+
load(id) {
|
|
44
|
+
const cleanId = id.split('?')[0];
|
|
45
|
+
if (!cleanId.endsWith('.pug')) return null;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const pugSource = readFileSync(cleanId, 'utf-8');
|
|
49
|
+
const tokens = lex(pugSource, { filename: cleanId });
|
|
50
|
+
const strippedTokens = stripComments(tokens, { filename: cleanId });
|
|
51
|
+
const ast = parse(strippedTokens, { filename: cleanId, src: pugSource });
|
|
52
|
+
const js = generateCode(ast, {
|
|
53
|
+
compileDebug: false,
|
|
54
|
+
pretty: false,
|
|
55
|
+
inlineRuntimeFunctions: false,
|
|
56
|
+
templateName: 'template'
|
|
57
|
+
});
|
|
58
|
+
const templateFn = runtimeWrap(js);
|
|
59
|
+
const html = templateFn();
|
|
60
|
+
|
|
61
|
+
return `export default ${JSON.stringify(html)};`;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(`[puglite] Error compiling ${cleanId}:`, error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const vitestConfig = {
|
|
70
|
+
run: true,
|
|
71
|
+
plugins: [pugVitePlugin],
|
|
72
|
+
test: {
|
|
73
|
+
globals: true,
|
|
74
|
+
environment: 'jsdom'
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const vitest = await startVitest('test', filters, vitestConfig);
|
|
80
|
+
|
|
81
|
+
if (!vitest) {
|
|
82
|
+
yield { success: false };
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
await vitest.close();
|
|
87
|
+
|
|
88
|
+
const hasFailures = vitest.state.getCountOfFailedTests() > 0;
|
|
89
|
+
yield { success: !hasFailures };
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('[puglite] Vitest error:', error);
|
|
92
|
+
yield { success: false, error: error.message };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const { createBuilder } = projectRequire('@angular-devkit/architect');
|
|
97
|
+
module.exports = createBuilder(buildVitest);
|
|
98
|
+
module.exports.default = module.exports;
|
package/builders.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@angular-devkit/architect/src/builders-schema.json",
|
|
3
|
+
"builders": {
|
|
4
|
+
"browser": {
|
|
5
|
+
"implementation": "./builders/browser",
|
|
6
|
+
"schema": "./builders/browser/schema.json",
|
|
7
|
+
"description": "Build browser application with Puglite template support"
|
|
8
|
+
},
|
|
9
|
+
"dev-server": {
|
|
10
|
+
"implementation": "./builders/dev-server",
|
|
11
|
+
"schema": "./builders/dev-server/schema.json",
|
|
12
|
+
"description": "Development server with Puglite template support"
|
|
13
|
+
},
|
|
14
|
+
"karma": {
|
|
15
|
+
"implementation": "./builders/karma",
|
|
16
|
+
"schema": "./builders/karma/schema.json",
|
|
17
|
+
"description": "Karma test runner with Puglite template support"
|
|
18
|
+
},
|
|
19
|
+
"vitest": {
|
|
20
|
+
"implementation": "./builders/vitest",
|
|
21
|
+
"schema": "./builders/vitest/schema.json",
|
|
22
|
+
"description": "Vitest test runner with Puglite template support"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|