@analogjs/vite-plugin-angular 2.0.0-alpha.2 → 2.0.0-alpha.20
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 +2 -0
- package/package.json +8 -4
- package/src/index.d.ts +0 -2
- package/src/index.js +0 -2
- package/src/index.js.map +1 -1
- package/src/lib/angular-pending-tasks.plugin.js +3 -2
- package/src/lib/angular-pending-tasks.plugin.js.map +1 -1
- package/src/lib/angular-storybook-plugin.d.ts +2 -2
- package/src/lib/angular-storybook-plugin.js +11 -4
- package/src/lib/angular-storybook-plugin.js.map +1 -1
- package/src/lib/angular-vite-plugin.d.ts +17 -22
- package/src/lib/angular-vite-plugin.js +378 -210
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/angular-vitest-plugin.js +1 -6
- package/src/lib/angular-vitest-plugin.js.map +1 -1
- package/src/lib/component-resolvers.js +1 -1
- package/src/lib/component-resolvers.js.map +1 -1
- package/src/lib/host.d.ts +4 -7
- package/src/lib/host.js +47 -80
- package/src/lib/host.js.map +1 -1
- package/src/lib/live-reload-plugin.d.ts +6 -0
- package/src/lib/live-reload-plugin.js +63 -0
- package/src/lib/live-reload-plugin.js.map +1 -0
- package/src/lib/models.d.ts +11 -0
- package/src/lib/models.js +2 -0
- package/src/lib/models.js.map +1 -0
- package/src/lib/nx-folder-plugin.d.ts +7 -0
- package/src/lib/nx-folder-plugin.js +18 -0
- package/src/lib/nx-folder-plugin.js.map +1 -0
- package/src/lib/tools/README.md +3 -0
- package/src/lib/tools/builders.json +15 -0
- package/src/lib/tools/package.json +7 -0
- package/src/lib/tools/src/builders/vite/schema.d.ts +6 -0
- package/src/lib/tools/src/builders/vite/schema.json +39 -0
- package/src/lib/tools/src/builders/vite/vite-build.impl.d.ts +2 -0
- package/src/lib/tools/src/builders/vite/vite-build.impl.js +40 -0
- package/src/lib/tools/src/builders/vite/vite-build.impl.js.map +1 -0
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.d.ts +2 -0
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js +64 -0
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js.map +1 -0
- package/src/lib/tools/src/builders/vite-dev-server/schema.d.ts +5 -0
- package/src/lib/tools/src/builders/vite-dev-server/schema.json +25 -0
- package/src/lib/tools/src/index.d.ts +0 -0
- package/src/lib/tools/src/index.js +1 -0
- package/src/lib/tools/src/index.js.map +1 -0
- package/src/lib/utils/devkit.js +3 -11
- package/src/lib/utils/devkit.js.map +1 -1
- package/src/lib/utils/hmr-candidates.d.ts +32 -0
- package/src/lib/utils/hmr-candidates.js +272 -0
- package/src/lib/utils/hmr-candidates.js.map +1 -0
- package/src/lib/utils/source-file-cache.d.ts +2 -2
- package/esbuild.d.ts +0 -3
- package/esbuild.js +0 -31
- package/esbuild.js.map +0 -1
- package/src/lib/authoring/analog.d.ts +0 -1
- package/src/lib/authoring/analog.js +0 -550
- package/src/lib/authoring/analog.js.map +0 -1
- package/src/lib/authoring/constants.d.ts +0 -26
- package/src/lib/authoring/constants.js +0 -47
- package/src/lib/authoring/constants.js.map +0 -1
- package/src/lib/authoring/frontmatter.d.ts +0 -2
- package/src/lib/authoring/frontmatter.js +0 -26
- package/src/lib/authoring/frontmatter.js.map +0 -1
- package/src/lib/authoring/markdown-transform.d.ts +0 -4
- package/src/lib/authoring/markdown-transform.js +0 -14
- package/src/lib/authoring/markdown-transform.js.map +0 -1
- package/src/lib/authoring/marked-setup.service.d.ts +0 -23
- package/src/lib/authoring/marked-setup.service.js +0 -119
- package/src/lib/authoring/marked-setup.service.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { dirname, relative, resolve } from 'node:path';
|
|
1
|
+
import { basename, dirname, isAbsolute, relative, resolve } from 'node:path';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import * as compilerCli from '@angular/compiler-cli';
|
|
3
|
-
import * as ts from 'typescript';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
|
-
import { normalizePath, preprocessCSS, } from 'vite';
|
|
5
|
+
import { normalizePath, preprocessCSS, defaultClientConditions, } from 'vite';
|
|
6
|
+
import * as ngCompiler from '@angular/compiler';
|
|
6
7
|
import { createCompilerPlugin } from './compiler-plugin.js';
|
|
7
8
|
import { StyleUrlsResolver, TemplateUrlsResolver, } from './component-resolvers.js';
|
|
8
9
|
import { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers, } from './host.js';
|
|
@@ -12,17 +13,16 @@ import { createJitResourceTransformer, SourceFileCache, angularMajor, } from './
|
|
|
12
13
|
import { angularVitestPlugins } from './angular-vitest-plugin.js';
|
|
13
14
|
import { angularStorybookPlugin } from './angular-storybook-plugin.js';
|
|
14
15
|
const require = createRequire(import.meta.url);
|
|
15
|
-
import { getFrontmatterMetadata } from './authoring/frontmatter.js';
|
|
16
|
-
import { defaultMarkdownTemplateTransforms, } from './authoring/markdown-transform.js';
|
|
17
16
|
import { routerPlugin } from './router-plugin.js';
|
|
18
17
|
import { pendingTasksPlugin } from './angular-pending-tasks.plugin.js';
|
|
18
|
+
import { liveReloadPlugin } from './live-reload-plugin.js';
|
|
19
|
+
import { nxFolderPlugin } from './nx-folder-plugin.js';
|
|
19
20
|
/**
|
|
20
21
|
* TypeScript file extension regex
|
|
21
22
|
* Match .(c or m)ts, .ts extensions with an optional ? for query params
|
|
22
23
|
* Ignore .tsx extensions
|
|
23
24
|
*/
|
|
24
25
|
const TS_EXT_REGEX = /\.[cm]?(ts|analog|ag)[^x]?\??/;
|
|
25
|
-
const ANGULAR_COMPONENT_PREFIX = '/@ng/component';
|
|
26
26
|
const classNames = new Map();
|
|
27
27
|
export function angular(options) {
|
|
28
28
|
/**
|
|
@@ -30,10 +30,7 @@ export function angular(options) {
|
|
|
30
30
|
* are used for values not provided.
|
|
31
31
|
*/
|
|
32
32
|
const pluginOptions = {
|
|
33
|
-
tsconfig: options?.tsconfig
|
|
34
|
-
(process.env['NODE_ENV'] === 'test'
|
|
35
|
-
? './tsconfig.spec.json'
|
|
36
|
-
: './tsconfig.app.json'),
|
|
33
|
+
tsconfig: options?.tsconfig || '',
|
|
37
34
|
workspaceRoot: options?.workspaceRoot ?? process.cwd(),
|
|
38
35
|
inlineStylesExtension: options?.inlineStylesExtension ?? 'css',
|
|
39
36
|
advanced: {
|
|
@@ -44,29 +41,22 @@ export function angular(options) {
|
|
|
44
41
|
},
|
|
45
42
|
},
|
|
46
43
|
supportedBrowsers: options?.supportedBrowsers ?? ['safari 15'],
|
|
47
|
-
jit: options?.
|
|
48
|
-
supportAnalogFormat: options?.experimental?.supportAnalogFormat ?? false,
|
|
49
|
-
markdownTemplateTransforms: options?.experimental
|
|
50
|
-
?.markdownTemplateTransforms?.length
|
|
51
|
-
? options.experimental.markdownTemplateTransforms
|
|
52
|
-
: defaultMarkdownTemplateTransforms,
|
|
44
|
+
jit: options?.jit,
|
|
53
45
|
include: options?.include ?? [],
|
|
54
46
|
additionalContentDirs: options?.additionalContentDirs ?? [],
|
|
55
47
|
liveReload: options?.liveReload ?? false,
|
|
48
|
+
disableTypeChecking: options?.disableTypeChecking ?? true,
|
|
56
49
|
};
|
|
57
|
-
// The file emitter created during `onStart` that will be used during the build in `onLoad` callbacks for TS files
|
|
58
|
-
let fileEmitter;
|
|
59
|
-
let compilerOptions = {};
|
|
60
|
-
const ts = require('typescript');
|
|
61
50
|
let resolvedConfig;
|
|
62
|
-
let rootNames;
|
|
63
|
-
let host;
|
|
64
51
|
let nextProgram;
|
|
65
52
|
let builderProgram;
|
|
66
53
|
let watchMode = false;
|
|
67
|
-
let testWatchMode =
|
|
54
|
+
let testWatchMode = isTestWatchMode();
|
|
55
|
+
let inlineComponentStyles;
|
|
56
|
+
let externalComponentStyles;
|
|
68
57
|
const sourceFileCache = new SourceFileCache();
|
|
69
58
|
const isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'];
|
|
59
|
+
const isVitestVscode = !!process.env['VITEST_VSCODE'];
|
|
70
60
|
const isStackBlitz = !!process.versions['webcontainer'];
|
|
71
61
|
const isAstroIntegration = process.env['ANALOG_ASTRO'] === 'true';
|
|
72
62
|
const isStorybook = process.env['npm_lifecycle_script']?.includes('storybook') ||
|
|
@@ -75,9 +65,16 @@ export function angular(options) {
|
|
|
75
65
|
process.env['ANALOG_STORYBOOK'] === 'true';
|
|
76
66
|
const jit = typeof pluginOptions?.jit !== 'undefined' ? pluginOptions.jit : isTest;
|
|
77
67
|
let viteServer;
|
|
78
|
-
let styleTransform;
|
|
79
68
|
const styleUrlsResolver = new StyleUrlsResolver();
|
|
80
69
|
const templateUrlsResolver = new TemplateUrlsResolver();
|
|
70
|
+
let outputFile;
|
|
71
|
+
const outputFiles = new Map();
|
|
72
|
+
const fileEmitter = (file) => {
|
|
73
|
+
outputFile?.(file);
|
|
74
|
+
return outputFiles.get(normalizePath(file));
|
|
75
|
+
};
|
|
76
|
+
let initialCompilation = false;
|
|
77
|
+
const declarationFiles = [];
|
|
81
78
|
function angularPlugin() {
|
|
82
79
|
let isProd = false;
|
|
83
80
|
if (angularMajor < 19 || isTest) {
|
|
@@ -85,21 +82,12 @@ export function angular(options) {
|
|
|
85
82
|
}
|
|
86
83
|
return {
|
|
87
84
|
name: '@analogjs/vite-plugin-angular',
|
|
88
|
-
async watchChange() {
|
|
89
|
-
if (isTest) {
|
|
90
|
-
await buildAndAnalyze();
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
85
|
async config(config, { command }) {
|
|
94
86
|
watchMode = command === 'serve';
|
|
95
87
|
isProd =
|
|
96
88
|
config.mode === 'production' ||
|
|
97
89
|
process.env['NODE_ENV'] === 'production';
|
|
98
|
-
pluginOptions.tsconfig =
|
|
99
|
-
options?.tsconfig ??
|
|
100
|
-
resolve(config.root || '.', process.env['NODE_ENV'] === 'test'
|
|
101
|
-
? './tsconfig.spec.json'
|
|
102
|
-
: './tsconfig.app.json');
|
|
90
|
+
pluginOptions.tsconfig = getTsConfigPath(config.root || '.', pluginOptions, isProd, isTest, !!config?.build?.lib);
|
|
103
91
|
return {
|
|
104
92
|
esbuild: config.esbuild ?? false,
|
|
105
93
|
optimizeDeps: {
|
|
@@ -123,80 +111,60 @@ export function angular(options) {
|
|
|
123
111
|
},
|
|
124
112
|
},
|
|
125
113
|
resolve: {
|
|
126
|
-
conditions: ['style'],
|
|
114
|
+
conditions: ['style', ...defaultClientConditions],
|
|
127
115
|
},
|
|
128
116
|
};
|
|
129
117
|
},
|
|
130
118
|
configResolved(config) {
|
|
131
119
|
resolvedConfig = config;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
120
|
+
if (isTest) {
|
|
121
|
+
// set test watch mode
|
|
122
|
+
// - vite override from vitest-angular
|
|
123
|
+
// - @nx/vite executor set server.watch explicitly to undefined (watch)/null (watch=false)
|
|
124
|
+
// - vite config for test.watch variable
|
|
125
|
+
// - vitest watch mode detected from the command line
|
|
126
|
+
testWatchMode =
|
|
127
|
+
!(config.server.watch === null) ||
|
|
128
|
+
config.test?.watch === true ||
|
|
129
|
+
testWatchMode;
|
|
130
|
+
}
|
|
139
131
|
},
|
|
140
132
|
configureServer(server) {
|
|
141
133
|
viteServer = server;
|
|
142
134
|
server.watcher.on('add', async () => {
|
|
143
|
-
|
|
144
|
-
await buildAndAnalyze();
|
|
135
|
+
await performCompilation(resolvedConfig);
|
|
145
136
|
});
|
|
146
137
|
server.watcher.on('unlink', async () => {
|
|
147
|
-
|
|
148
|
-
await buildAndAnalyze();
|
|
138
|
+
await performCompilation(resolvedConfig);
|
|
149
139
|
});
|
|
150
|
-
if (pluginOptions.liveReload) {
|
|
151
|
-
const angularComponentMiddleware = async (req, res, next) => {
|
|
152
|
-
if (req.url === undefined || res.writableEnded) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
if (!req.url.startsWith(ANGULAR_COMPONENT_PREFIX)) {
|
|
156
|
-
next();
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const requestUrl = new URL(req.url, 'http://localhost');
|
|
160
|
-
const componentId = requestUrl.searchParams.get('c');
|
|
161
|
-
if (!componentId) {
|
|
162
|
-
res.statusCode = 400;
|
|
163
|
-
res.end();
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const [fileId] = decodeURIComponent(componentId).split('@');
|
|
167
|
-
const result = await fileEmitter?.(resolve(process.cwd(), fileId));
|
|
168
|
-
res.setHeader('Content-Type', 'text/javascript');
|
|
169
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
170
|
-
res.end(`${result?.hmrUpdateCode || ''}`);
|
|
171
|
-
};
|
|
172
|
-
viteServer.middlewares.use(angularComponentMiddleware);
|
|
173
|
-
}
|
|
174
140
|
},
|
|
175
141
|
async buildStart() {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
142
|
+
// Defer the first compilation in test mode
|
|
143
|
+
if (!isVitestVscode) {
|
|
144
|
+
const { host } = await performCompilation(resolvedConfig);
|
|
145
|
+
initialCompilation = true;
|
|
146
|
+
// Only store cache if in watch mode
|
|
147
|
+
if (watchMode) {
|
|
148
|
+
augmentHostWithCaching(host, sourceFileCache);
|
|
149
|
+
}
|
|
180
150
|
}
|
|
181
|
-
await buildAndAnalyze();
|
|
182
151
|
},
|
|
183
152
|
async handleHotUpdate(ctx) {
|
|
184
|
-
// The `handleHotUpdate` hook may be called before the `buildStart`,
|
|
185
|
-
// which sets the compilation. As a result, the `host` may not be available
|
|
186
|
-
// yet for use, leading to build errors such as "cannot read properties of undefined"
|
|
187
|
-
// (because `host` is undefined).
|
|
188
|
-
if (!host) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
153
|
if (TS_EXT_REGEX.test(ctx.file)) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
154
|
+
let [fileId] = ctx.file.split('?');
|
|
155
|
+
await performCompilation(resolvedConfig, [fileId]);
|
|
156
|
+
const result = fileEmitter(fileId);
|
|
157
|
+
if (pluginOptions.liveReload &&
|
|
158
|
+
result?.hmrEligible &&
|
|
159
|
+
classNames.get(fileId)) {
|
|
197
160
|
const relativeFileId = `${relative(process.cwd(), fileId)}@${classNames.get(fileId)}`;
|
|
198
161
|
sendHMRComponentUpdate(ctx.server, relativeFileId);
|
|
199
|
-
return
|
|
162
|
+
return ctx.modules.map((mod) => {
|
|
163
|
+
if (mod.id === ctx.file) {
|
|
164
|
+
return markModuleSelfAccepting(mod);
|
|
165
|
+
}
|
|
166
|
+
return mod;
|
|
167
|
+
});
|
|
200
168
|
}
|
|
201
169
|
}
|
|
202
170
|
if (/\.(html|htm|css|less|sass|scss)$/.test(ctx.file)) {
|
|
@@ -205,7 +173,42 @@ export function angular(options) {
|
|
|
205
173
|
* for an external resource (styles, html).
|
|
206
174
|
*/
|
|
207
175
|
const isDirect = ctx.modules.find((mod) => ctx.file === mod.file && mod.id?.includes('?direct'));
|
|
208
|
-
|
|
176
|
+
const isInline = ctx.modules.find((mod) => ctx.file === mod.file && mod.id?.includes('?inline'));
|
|
177
|
+
if (isDirect || isInline) {
|
|
178
|
+
if (pluginOptions.liveReload && isDirect?.id && isDirect.file) {
|
|
179
|
+
const isComponentStyle = isDirect.type === 'css' && isComponentStyleSheet(isDirect.id);
|
|
180
|
+
if (isComponentStyle) {
|
|
181
|
+
const { encapsulation } = getComponentStyleSheetMeta(isDirect.id);
|
|
182
|
+
// Track if the component uses ShadowDOM encapsulation
|
|
183
|
+
// Shadow DOM components currently require a full reload.
|
|
184
|
+
// Vite's CSS hot replacement does not support shadow root searching.
|
|
185
|
+
if (encapsulation !== 'shadow') {
|
|
186
|
+
ctx.server.ws.send({
|
|
187
|
+
type: 'update',
|
|
188
|
+
updates: [
|
|
189
|
+
{
|
|
190
|
+
type: 'css-update',
|
|
191
|
+
timestamp: Date.now(),
|
|
192
|
+
path: isDirect.url,
|
|
193
|
+
acceptedPath: isDirect.file,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
return ctx.modules
|
|
198
|
+
.filter((mod) => {
|
|
199
|
+
// Component stylesheets will have 2 modules (*.component.scss and *.component.scss?direct&ngcomp=xyz&e=x)
|
|
200
|
+
// We remove the module with the query params to prevent vite double logging the stylesheet name "hmr update *.component.scss, *.component.scss?direct&ngcomp=xyz&e=x"
|
|
201
|
+
return mod.file !== ctx.file || mod.id !== isDirect.id;
|
|
202
|
+
})
|
|
203
|
+
.map((mod) => {
|
|
204
|
+
if (mod.file === ctx.file) {
|
|
205
|
+
return markModuleSelfAccepting(mod);
|
|
206
|
+
}
|
|
207
|
+
return mod;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
209
212
|
return ctx.modules;
|
|
210
213
|
}
|
|
211
214
|
const mods = [];
|
|
@@ -222,16 +225,26 @@ export function angular(options) {
|
|
|
222
225
|
}
|
|
223
226
|
});
|
|
224
227
|
});
|
|
225
|
-
await
|
|
228
|
+
await performCompilation(resolvedConfig, [
|
|
229
|
+
...mods.map((mod) => mod.id),
|
|
230
|
+
...updates,
|
|
231
|
+
]);
|
|
226
232
|
if (updates.length > 0) {
|
|
227
233
|
updates.forEach((updateId) => {
|
|
228
234
|
const impRelativeFileId = `${relative(process.cwd(), updateId)}@${classNames.get(updateId)}`;
|
|
229
235
|
sendHMRComponentUpdate(ctx.server, impRelativeFileId);
|
|
230
236
|
});
|
|
231
|
-
return ctx.modules
|
|
237
|
+
return ctx.modules.map((mod) => {
|
|
238
|
+
if (mod.id === ctx.file) {
|
|
239
|
+
return markModuleSelfAccepting(mod);
|
|
240
|
+
}
|
|
241
|
+
return mod;
|
|
242
|
+
});
|
|
232
243
|
}
|
|
233
244
|
return mods;
|
|
234
245
|
}
|
|
246
|
+
// clear HMR updates with a full reload
|
|
247
|
+
classNames.clear();
|
|
235
248
|
return ctx.modules;
|
|
236
249
|
},
|
|
237
250
|
resolveId(id, importer) {
|
|
@@ -239,19 +252,22 @@ export function angular(options) {
|
|
|
239
252
|
const path = id.split(';')[1];
|
|
240
253
|
return `${normalizePath(resolve(dirname(importer), path))}?raw`;
|
|
241
254
|
}
|
|
255
|
+
// Map angular external styleUrls to the source file
|
|
256
|
+
if (isComponentStyleSheet(id)) {
|
|
257
|
+
const componentStyles = externalComponentStyles?.get(getFilenameFromPath(id));
|
|
258
|
+
if (componentStyles) {
|
|
259
|
+
return componentStyles + new URL(id, 'http://localhost').search;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
242
262
|
return undefined;
|
|
243
263
|
},
|
|
244
|
-
async load(id
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
id
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (!componentId) {
|
|
251
|
-
return;
|
|
264
|
+
async load(id) {
|
|
265
|
+
// Map angular inline styles to the source text
|
|
266
|
+
if (isComponentStyleSheet(id)) {
|
|
267
|
+
const componentStyles = inlineComponentStyles?.get(getFilenameFromPath(id));
|
|
268
|
+
if (componentStyles) {
|
|
269
|
+
return componentStyles;
|
|
252
270
|
}
|
|
253
|
-
const result = await fileEmitter?.(resolve(process.cwd(), decodeURIComponent(componentId).split('@')[0]));
|
|
254
|
-
return result?.hmrUpdateCode || '';
|
|
255
271
|
}
|
|
256
272
|
return;
|
|
257
273
|
},
|
|
@@ -284,6 +300,19 @@ export function angular(options) {
|
|
|
284
300
|
if (id.includes('analog-content-')) {
|
|
285
301
|
return;
|
|
286
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Encapsulate component stylesheets that use emulated encapsulation
|
|
305
|
+
*/
|
|
306
|
+
if (pluginOptions.liveReload && isComponentStyleSheet(id)) {
|
|
307
|
+
const { encapsulation, componentId } = getComponentStyleSheetMeta(id);
|
|
308
|
+
if (encapsulation === 'emulated' && componentId) {
|
|
309
|
+
const encapsulated = ngCompiler.encapsulateStyle(code, componentId);
|
|
310
|
+
return {
|
|
311
|
+
code: encapsulated,
|
|
312
|
+
map: null,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
287
316
|
if (TS_EXT_REGEX.test(id)) {
|
|
288
317
|
if (id.includes('.ts?')) {
|
|
289
318
|
// Strip the query string off the ID
|
|
@@ -295,11 +324,17 @@ export function angular(options) {
|
|
|
295
324
|
* for test(Vitest)
|
|
296
325
|
*/
|
|
297
326
|
if (isTest) {
|
|
327
|
+
if (isVitestVscode && !initialCompilation) {
|
|
328
|
+
// Do full initial compilation
|
|
329
|
+
await performCompilation(resolvedConfig);
|
|
330
|
+
initialCompilation = true;
|
|
331
|
+
}
|
|
298
332
|
const tsMod = viteServer?.moduleGraph.getModuleById(id);
|
|
299
333
|
if (tsMod) {
|
|
300
|
-
|
|
301
|
-
if (testWatchMode) {
|
|
302
|
-
|
|
334
|
+
const invalidated = tsMod.lastInvalidationTimestamp;
|
|
335
|
+
if (testWatchMode && invalidated) {
|
|
336
|
+
sourceFileCache.invalidate([id]);
|
|
337
|
+
await performCompilation(resolvedConfig, [id]);
|
|
303
338
|
}
|
|
304
339
|
}
|
|
305
340
|
}
|
|
@@ -314,7 +349,7 @@ export function angular(options) {
|
|
|
314
349
|
this.addWatchFile(absoluteFileUrl);
|
|
315
350
|
}
|
|
316
351
|
}
|
|
317
|
-
const typescriptResult =
|
|
352
|
+
const typescriptResult = fileEmitter(id);
|
|
318
353
|
if (typescriptResult?.warnings &&
|
|
319
354
|
typescriptResult?.warnings.length > 0) {
|
|
320
355
|
this.warn(`${typescriptResult.warnings.join('\n')}`);
|
|
@@ -335,25 +370,6 @@ export function angular(options) {
|
|
|
335
370
|
data = data.replace(`angular:jit:style:file;${styleFile}`, `${resolvedStyleUrl}?inline`);
|
|
336
371
|
});
|
|
337
372
|
}
|
|
338
|
-
if (jit) {
|
|
339
|
-
return {
|
|
340
|
-
code: data,
|
|
341
|
-
map: null,
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
if ((id.endsWith('.analog') ||
|
|
345
|
-
id.endsWith('.agx') ||
|
|
346
|
-
id.endsWith('.ag')) &&
|
|
347
|
-
pluginOptions.supportAnalogFormat &&
|
|
348
|
-
fileEmitter) {
|
|
349
|
-
sourceFileCache.invalidate([`${id}.ts`]);
|
|
350
|
-
const ngFileResult = await fileEmitter(`${id}.ts`);
|
|
351
|
-
data = ngFileResult?.content || '';
|
|
352
|
-
if (id.includes('.agx')) {
|
|
353
|
-
const metadata = await getFrontmatterMetadata(code, id, pluginOptions.markdownTemplateTransforms || []);
|
|
354
|
-
data += metadata;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
373
|
return {
|
|
358
374
|
code: data,
|
|
359
375
|
map: null,
|
|
@@ -361,10 +377,17 @@ export function angular(options) {
|
|
|
361
377
|
}
|
|
362
378
|
return undefined;
|
|
363
379
|
},
|
|
380
|
+
closeBundle() {
|
|
381
|
+
declarationFiles.forEach(({ declarationFileDir, declarationPath, data }) => {
|
|
382
|
+
mkdirSync(declarationFileDir, { recursive: true });
|
|
383
|
+
writeFileSync(declarationPath, data, 'utf-8');
|
|
384
|
+
});
|
|
385
|
+
},
|
|
364
386
|
};
|
|
365
387
|
}
|
|
366
388
|
return [
|
|
367
389
|
angularPlugin(),
|
|
390
|
+
pluginOptions.liveReload && liveReloadPlugin({ classNames, fileEmitter }),
|
|
368
391
|
...(isTest && !isStackBlitz ? angularVitestPlugins() : []),
|
|
369
392
|
(jit &&
|
|
370
393
|
jitPlugin({
|
|
@@ -374,36 +397,12 @@ export function angular(options) {
|
|
|
374
397
|
supportedBrowsers: pluginOptions.supportedBrowsers,
|
|
375
398
|
jit,
|
|
376
399
|
}),
|
|
377
|
-
(isStorybook &&
|
|
400
|
+
(isStorybook &&
|
|
401
|
+
angularStorybookPlugin(pluginOptions.workspaceRoot)),
|
|
378
402
|
routerPlugin(),
|
|
379
403
|
pendingTasksPlugin(),
|
|
404
|
+
nxFolderPlugin(),
|
|
380
405
|
].filter(Boolean);
|
|
381
|
-
function findAnalogFiles(config) {
|
|
382
|
-
const analogConfig = pluginOptions.supportAnalogFormat;
|
|
383
|
-
if (!analogConfig) {
|
|
384
|
-
return [];
|
|
385
|
-
}
|
|
386
|
-
let extraGlobs = [];
|
|
387
|
-
if (typeof analogConfig === 'object') {
|
|
388
|
-
if (analogConfig.include) {
|
|
389
|
-
extraGlobs = analogConfig.include;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
const fg = require('fast-glob');
|
|
393
|
-
const appRoot = normalizePath(resolve(pluginOptions.workspaceRoot, config.root || '.'));
|
|
394
|
-
const workspaceRoot = normalizePath(resolve(pluginOptions.workspaceRoot));
|
|
395
|
-
const globs = [
|
|
396
|
-
`${appRoot}/**/*.{analog,agx,ag}`,
|
|
397
|
-
...extraGlobs.map((glob) => `${workspaceRoot}${glob}.{analog,agx,ag}`),
|
|
398
|
-
...(pluginOptions.additionalContentDirs || [])?.map((glob) => `${workspaceRoot}${glob}/**/*.agx`),
|
|
399
|
-
...pluginOptions.include.map((glob) => `${workspaceRoot}${glob}`.replace(/\.ts$/, '.analog')),
|
|
400
|
-
];
|
|
401
|
-
return fg
|
|
402
|
-
.sync(globs, {
|
|
403
|
-
dot: true,
|
|
404
|
-
})
|
|
405
|
-
.map((file) => `${file}.ts`);
|
|
406
|
-
}
|
|
407
406
|
function findIncludes() {
|
|
408
407
|
const fg = require('fast-glob');
|
|
409
408
|
const workspaceRoot = normalizePath(resolve(pluginOptions.workspaceRoot));
|
|
@@ -414,11 +413,28 @@ export function angular(options) {
|
|
|
414
413
|
dot: true,
|
|
415
414
|
});
|
|
416
415
|
}
|
|
417
|
-
function
|
|
416
|
+
function getTsConfigPath(root, options, isProd, isTest, isLib) {
|
|
417
|
+
if (options.tsconfig && isAbsolute(options.tsconfig)) {
|
|
418
|
+
return options.tsconfig;
|
|
419
|
+
}
|
|
420
|
+
let tsconfigFilePath = './tsconfig.app.json';
|
|
421
|
+
if (isLib) {
|
|
422
|
+
tsconfigFilePath = isProd
|
|
423
|
+
? './tsconfig.lib.prod.json'
|
|
424
|
+
: './tsconfig.lib.json';
|
|
425
|
+
}
|
|
426
|
+
if (isTest) {
|
|
427
|
+
tsconfigFilePath = './tsconfig.spec.json';
|
|
428
|
+
}
|
|
429
|
+
if (options.tsconfig) {
|
|
430
|
+
tsconfigFilePath = options.tsconfig;
|
|
431
|
+
}
|
|
432
|
+
return resolve(root, tsconfigFilePath);
|
|
433
|
+
}
|
|
434
|
+
async function performCompilation(config, ids) {
|
|
418
435
|
const isProd = config.mode === 'production';
|
|
419
|
-
const analogFiles = findAnalogFiles(config);
|
|
420
436
|
const includeFiles = findIncludes();
|
|
421
|
-
|
|
437
|
+
let { options: tsCompilerOptions, rootNames } = compilerCli.readConfiguration(pluginOptions.tsconfig, {
|
|
422
438
|
suppressOutputPathCheck: true,
|
|
423
439
|
outDir: undefined,
|
|
424
440
|
sourceMap: false,
|
|
@@ -435,73 +451,149 @@ export function angular(options) {
|
|
|
435
451
|
supportTestBed: false,
|
|
436
452
|
supportJitMode: false,
|
|
437
453
|
});
|
|
438
|
-
if (pluginOptions.
|
|
439
|
-
// Experimental Local Compilation is necessary
|
|
440
|
-
// for the Angular compiler to work with
|
|
441
|
-
// AOT and virtually compiled .analog files.
|
|
442
|
-
tsCompilerOptions.compilationMode = 'experimental-local';
|
|
443
|
-
}
|
|
444
|
-
if (pluginOptions.liveReload) {
|
|
454
|
+
if (pluginOptions.liveReload && watchMode) {
|
|
445
455
|
tsCompilerOptions['_enableHmr'] = true;
|
|
456
|
+
tsCompilerOptions['externalRuntimeStyles'] = true;
|
|
457
|
+
// Workaround for https://github.com/angular/angular/issues/59310
|
|
458
|
+
// Force extra instructions to be generated for HMR w/defer
|
|
459
|
+
tsCompilerOptions['supportTestBed'] = true;
|
|
460
|
+
}
|
|
461
|
+
if (tsCompilerOptions.compilationMode === 'partial') {
|
|
462
|
+
// These options can't be false in partial mode
|
|
463
|
+
tsCompilerOptions['supportTestBed'] = true;
|
|
464
|
+
tsCompilerOptions['supportJitMode'] = true;
|
|
465
|
+
}
|
|
466
|
+
if (!isTest && config.build?.lib) {
|
|
467
|
+
tsCompilerOptions['declaration'] = true;
|
|
468
|
+
tsCompilerOptions['declarationMap'] = watchMode;
|
|
469
|
+
tsCompilerOptions['inlineSources'] = true;
|
|
446
470
|
}
|
|
447
|
-
rootNames =
|
|
448
|
-
|
|
449
|
-
host = ts.createIncrementalCompilerHost(
|
|
450
|
-
styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
471
|
+
rootNames = rootNames.concat(includeFiles);
|
|
472
|
+
const ts = require('typescript');
|
|
473
|
+
const host = ts.createIncrementalCompilerHost(tsCompilerOptions);
|
|
451
474
|
if (!jit) {
|
|
475
|
+
const styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
476
|
+
inlineComponentStyles = tsCompilerOptions['externalRuntimeStyles']
|
|
477
|
+
? new Map()
|
|
478
|
+
: undefined;
|
|
479
|
+
externalComponentStyles = tsCompilerOptions['externalRuntimeStyles']
|
|
480
|
+
? new Map()
|
|
481
|
+
: undefined;
|
|
452
482
|
augmentHostWithResources(host, styleTransform, {
|
|
453
483
|
inlineStylesExtension: pluginOptions.inlineStylesExtension,
|
|
454
|
-
supportAnalogFormat: pluginOptions.supportAnalogFormat,
|
|
455
484
|
isProd,
|
|
456
|
-
|
|
485
|
+
inlineComponentStyles,
|
|
486
|
+
externalComponentStyles,
|
|
457
487
|
});
|
|
458
488
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
*/
|
|
465
|
-
async function buildAndAnalyze() {
|
|
489
|
+
/**
|
|
490
|
+
* Creates a new NgtscProgram to analyze/re-analyze
|
|
491
|
+
* the source files and create a file emitter.
|
|
492
|
+
* This is shared between an initial build and a hot update.
|
|
493
|
+
*/
|
|
466
494
|
let builder;
|
|
467
495
|
let typeScriptProgram;
|
|
468
496
|
let angularCompiler;
|
|
469
497
|
if (!jit) {
|
|
470
498
|
// Create the Angular specific program that contains the Angular compiler
|
|
471
|
-
const angularProgram = new compilerCli.NgtscProgram(rootNames,
|
|
499
|
+
const angularProgram = new compilerCli.NgtscProgram(rootNames, tsCompilerOptions, host, nextProgram);
|
|
472
500
|
angularCompiler = angularProgram.compiler;
|
|
473
501
|
typeScriptProgram = angularProgram.getTsProgram();
|
|
474
502
|
augmentProgramWithVersioning(typeScriptProgram);
|
|
475
|
-
builder = builderProgram
|
|
476
|
-
ts.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, builderProgram);
|
|
503
|
+
builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(typeScriptProgram, host, builderProgram);
|
|
477
504
|
await angularCompiler.analyzeAsync();
|
|
478
505
|
nextProgram = angularProgram;
|
|
506
|
+
builderProgram =
|
|
507
|
+
builder;
|
|
479
508
|
}
|
|
480
509
|
else {
|
|
481
|
-
builder =
|
|
482
|
-
ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, compilerOptions, host, nextProgram);
|
|
510
|
+
builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, tsCompilerOptions, host, nextProgram);
|
|
483
511
|
typeScriptProgram = builder.getProgram();
|
|
484
|
-
nextProgram = builderProgram;
|
|
485
512
|
}
|
|
486
513
|
if (!watchMode) {
|
|
487
514
|
// When not in watch mode, the startup cost of the incremental analysis can be avoided by
|
|
488
515
|
// using an abstract builder that only wraps a TypeScript program.
|
|
489
516
|
builder = ts.createAbstractBuilder(typeScriptProgram, host);
|
|
490
517
|
}
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
518
|
+
const beforeTransformers = jit
|
|
519
|
+
? [
|
|
520
|
+
compilerCli.constructorParametersDownlevelTransform(builder.getProgram()),
|
|
521
|
+
createJitResourceTransformer(() => builder.getProgram().getTypeChecker()),
|
|
522
|
+
]
|
|
523
|
+
: [];
|
|
524
|
+
const transformers = mergeTransformers({ before: beforeTransformers }, jit ? {} : angularCompiler.prepareEmit().transformers);
|
|
525
|
+
const fileMetadata = getFileMetadata(builder, angularCompiler, pluginOptions.liveReload, pluginOptions.disableTypeChecking);
|
|
526
|
+
const writeFileCallback = (_filename, content, _a, _b, sourceFiles) => {
|
|
527
|
+
if (!sourceFiles?.length) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const filename = normalizePath(sourceFiles[0].fileName);
|
|
531
|
+
if (filename.includes('ngtypecheck.ts') || filename.includes('.d.')) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const metadata = watchMode ? fileMetadata(filename) : {};
|
|
535
|
+
outputFiles.set(filename, {
|
|
536
|
+
content,
|
|
537
|
+
dependencies: [],
|
|
538
|
+
errors: metadata.errors,
|
|
539
|
+
warnings: metadata.warnings,
|
|
540
|
+
hmrUpdateCode: metadata.hmrUpdateCode,
|
|
541
|
+
hmrEligible: metadata.hmrEligible,
|
|
542
|
+
});
|
|
543
|
+
};
|
|
544
|
+
const writeOutputFile = (id) => {
|
|
545
|
+
const sourceFile = builder.getSourceFile(id);
|
|
546
|
+
if (!sourceFile) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
let content = '';
|
|
550
|
+
builder.emit(sourceFile, (filename, data) => {
|
|
551
|
+
if (/\.[cm]?js$/.test(filename)) {
|
|
552
|
+
content = data;
|
|
553
|
+
}
|
|
554
|
+
if (!watchMode &&
|
|
555
|
+
!isTest &&
|
|
556
|
+
/\.d\.ts/.test(filename) &&
|
|
557
|
+
!filename.includes('.ngtypecheck.')) {
|
|
558
|
+
// output to library root instead /src
|
|
559
|
+
const declarationPath = resolve(config.root, config.build.outDir, relative(config.root, filename)).replace('/src/', '/');
|
|
560
|
+
const declarationFileDir = declarationPath
|
|
561
|
+
.replace(basename(filename), '')
|
|
562
|
+
.replace('/src/', '/');
|
|
563
|
+
declarationFiles.push({
|
|
564
|
+
declarationFileDir,
|
|
565
|
+
declarationPath,
|
|
566
|
+
data,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
}, undefined /* cancellationToken */, undefined /* emitOnlyDtsFiles */, transformers);
|
|
570
|
+
writeFileCallback(id, content, false, undefined, [sourceFile]);
|
|
571
|
+
};
|
|
572
|
+
if (watchMode) {
|
|
573
|
+
if (ids && ids.length > 0) {
|
|
574
|
+
ids.forEach((id) => writeOutputFile(id));
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
/**
|
|
578
|
+
* Only block the server from starting up
|
|
579
|
+
* during testing.
|
|
580
|
+
*/
|
|
581
|
+
if (isTest) {
|
|
582
|
+
// TypeScript will loop until there are no more affected files in the program
|
|
583
|
+
while (builder.emitNextAffectedFile(writeFileCallback, undefined, undefined, transformers)) {
|
|
584
|
+
/* empty */
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (!isTest) {
|
|
590
|
+
/**
|
|
591
|
+
* Perf: Output files on demand so the dev server
|
|
592
|
+
* isn't blocked when emitting files.
|
|
593
|
+
*/
|
|
594
|
+
outputFile = writeOutputFile;
|
|
595
|
+
}
|
|
596
|
+
return { host };
|
|
505
597
|
}
|
|
506
598
|
}
|
|
507
599
|
function sendHMRComponentUpdate(server, id) {
|
|
@@ -511,38 +603,114 @@ function sendHMRComponentUpdate(server, id) {
|
|
|
511
603
|
});
|
|
512
604
|
classNames.delete(id);
|
|
513
605
|
}
|
|
514
|
-
export function
|
|
515
|
-
|
|
606
|
+
export function getFileMetadata(program, angularCompiler, liveReload, disableTypeChecking) {
|
|
607
|
+
const ts = require('typescript');
|
|
608
|
+
return (file) => {
|
|
516
609
|
const sourceFile = program.getSourceFile(file);
|
|
517
610
|
if (!sourceFile) {
|
|
518
|
-
return
|
|
611
|
+
return {};
|
|
519
612
|
}
|
|
520
|
-
const diagnostics = angularCompiler
|
|
521
|
-
? angularCompiler.getDiagnosticsForFile(sourceFile, 1)
|
|
522
|
-
: [];
|
|
613
|
+
const diagnostics = getDiagnosticsForSourceFile(sourceFile, !!disableTypeChecking, program, angularCompiler);
|
|
523
614
|
const errors = diagnostics
|
|
524
615
|
.filter((d) => d.category === ts.DiagnosticCategory?.Error)
|
|
525
|
-
.map((d) => d.messageText
|
|
616
|
+
.map((d) => typeof d.messageText === 'object'
|
|
617
|
+
? d.messageText.messageText
|
|
618
|
+
: d.messageText);
|
|
526
619
|
const warnings = diagnostics
|
|
527
620
|
.filter((d) => d.category === ts.DiagnosticCategory?.Warning)
|
|
528
621
|
.map((d) => d.messageText);
|
|
529
622
|
let hmrUpdateCode = undefined;
|
|
623
|
+
let hmrEligible = false;
|
|
530
624
|
if (liveReload) {
|
|
531
625
|
for (const node of sourceFile.statements) {
|
|
532
626
|
if (ts.isClassDeclaration(node) && node.name != null) {
|
|
533
627
|
hmrUpdateCode = angularCompiler?.emitHmrUpdateModule(node);
|
|
534
|
-
|
|
628
|
+
if (!!hmrUpdateCode) {
|
|
629
|
+
classNames.set(file, node.name.getText());
|
|
630
|
+
hmrEligible = true;
|
|
631
|
+
}
|
|
535
632
|
}
|
|
536
633
|
}
|
|
537
634
|
}
|
|
538
|
-
|
|
539
|
-
program.emit(sourceFile, (filename, data) => {
|
|
540
|
-
if (/\.[cm]?js$/.test(filename)) {
|
|
541
|
-
content = data;
|
|
542
|
-
}
|
|
543
|
-
}, undefined /* cancellationToken */, undefined /* emitOnlyDtsFiles */, transformers);
|
|
544
|
-
onAfterEmit?.(sourceFile);
|
|
545
|
-
return { content, dependencies: [], errors, warnings, hmrUpdateCode };
|
|
635
|
+
return { errors, warnings, hmrUpdateCode, hmrEligible };
|
|
546
636
|
};
|
|
547
637
|
}
|
|
638
|
+
function getDiagnosticsForSourceFile(sourceFile, disableTypeChecking, program, angularCompiler) {
|
|
639
|
+
const syntacticDiagnostics = program.getSyntacticDiagnostics(sourceFile);
|
|
640
|
+
if (disableTypeChecking) {
|
|
641
|
+
// Syntax errors are cheap to compute and the app will not run if there are any
|
|
642
|
+
// So always show these types of errors regardless if type checking is disabled
|
|
643
|
+
return syntacticDiagnostics;
|
|
644
|
+
}
|
|
645
|
+
const semanticDiagnostics = program.getSemanticDiagnostics(sourceFile);
|
|
646
|
+
const angularDiagnostics = angularCompiler
|
|
647
|
+
? angularCompiler.getDiagnosticsForFile(sourceFile, 1)
|
|
648
|
+
: [];
|
|
649
|
+
return [
|
|
650
|
+
...syntacticDiagnostics,
|
|
651
|
+
...semanticDiagnostics,
|
|
652
|
+
...angularDiagnostics,
|
|
653
|
+
];
|
|
654
|
+
}
|
|
655
|
+
function markModuleSelfAccepting(mod) {
|
|
656
|
+
// support Vite 6
|
|
657
|
+
if ('_clientModule' in mod) {
|
|
658
|
+
mod['_clientModule'].isSelfAccepting = true;
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
...mod,
|
|
662
|
+
isSelfAccepting: true,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function isComponentStyleSheet(id) {
|
|
666
|
+
return id.includes('ngcomp=');
|
|
667
|
+
}
|
|
668
|
+
function getComponentStyleSheetMeta(id) {
|
|
669
|
+
const params = new URL(id, 'http://localhost').searchParams;
|
|
670
|
+
const encapsulationMapping = {
|
|
671
|
+
'0': 'emulated',
|
|
672
|
+
'2': 'none',
|
|
673
|
+
'3': 'shadow',
|
|
674
|
+
};
|
|
675
|
+
return {
|
|
676
|
+
componentId: params.get('ngcomp'),
|
|
677
|
+
encapsulation: encapsulationMapping[params.get('e')],
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Removes leading / and query string from a url path
|
|
682
|
+
* e.g. /foo.scss?direct&ngcomp=ng-c3153525609&e=0 returns foo.scss
|
|
683
|
+
* @param id
|
|
684
|
+
*/
|
|
685
|
+
function getFilenameFromPath(id) {
|
|
686
|
+
return new URL(id, 'http://localhost').pathname.replace(/^\//, '');
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Checks for vitest run from the command line
|
|
690
|
+
* @returns boolean
|
|
691
|
+
*/
|
|
692
|
+
export function isTestWatchMode(args = process.argv) {
|
|
693
|
+
// vitest --run
|
|
694
|
+
const hasRun = args.find((arg) => arg.includes('--run'));
|
|
695
|
+
if (hasRun) {
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
// vitest --no-run
|
|
699
|
+
const hasNoRun = args.find((arg) => arg.includes('--no-run'));
|
|
700
|
+
if (hasNoRun) {
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
// check for --watch=false or --no-watch
|
|
704
|
+
const hasWatch = args.find((arg) => arg.includes('watch'));
|
|
705
|
+
if (hasWatch && ['false', 'no'].some((neg) => hasWatch.includes(neg))) {
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
// check for --watch false
|
|
709
|
+
const watchIndex = args.findIndex((arg) => arg.includes('watch'));
|
|
710
|
+
const watchArg = args[watchIndex + 1];
|
|
711
|
+
if (watchArg && watchArg === 'false') {
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
548
716
|
//# sourceMappingURL=angular-vite-plugin.js.map
|