@analogjs/vite-plugin-angular 3.0.0-alpha.44 → 3.0.0-alpha.45

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 CHANGED
@@ -1,5 +1,7 @@
1
1
  # @analogjs/vite-plugin-angular
2
2
 
3
+ [![Vite Plugin Registry](https://img.shields.io/badge/vite-plugin--registry-blue?logo=vite)](https://registry.vite.dev/plugin/@analogjs/vite-plugin-angular)
4
+
3
5
  A Vite plugin for building Angular applications
4
6
 
5
7
  ## Install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/vite-plugin-angular",
3
- "version": "3.0.0-alpha.44",
3
+ "version": "3.0.0-alpha.45",
4
4
  "description": "Vite Plugin for Angular",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -33,8 +33,24 @@
33
33
  },
34
34
  "@angular/build": {
35
35
  "optional": true
36
+ },
37
+ "vite": {
38
+ "optional": true
36
39
  }
37
40
  },
41
+ "compatiblePackages": {
42
+ "vite": [
43
+ "^6.0.0",
44
+ "^7.0.0",
45
+ "^8.0.0"
46
+ ],
47
+ "rollup": [
48
+ "^4.0.0"
49
+ ],
50
+ "rolldown": [
51
+ "^1.0.0"
52
+ ]
53
+ },
38
54
  "dependencies": {
39
55
  "es-toolkit": "^1.45.1",
40
56
  "magic-string": "^0.30.21",
@@ -1,6 +1,5 @@
1
1
  import { debugStyles } from "./utils/debug.js";
2
2
  import { isTailwindReferenceError } from "./utils/tailwind-reference.js";
3
- import { shouldPreprocessTestCss } from "./utils/virtual-resources.js";
4
3
  import { preprocessCSS } from "vite";
5
4
  import { createHash } from "node:crypto";
6
5
  //#region packages/vite-plugin-angular/src/lib/angular-jit-plugin.ts
@@ -20,8 +19,6 @@ function jitPlugin({ inlineStylesExtension }) {
20
19
  const styleIdHash = createHash("sha256").update(styleId).digest("hex").slice(0, 16);
21
20
  const decodedStyles = Buffer.from(decodeURIComponent(styleId), "base64").toString();
22
21
  let styles = "";
23
- const inlineStyleId = `${styleIdHash}.${inlineStylesExtension}`;
24
- if (!shouldPreprocessTestCss(config, inlineStyleId)) return `export default \`\``;
25
22
  try {
26
23
  styles = (await preprocessCSS(decodedStyles, `${styleIdHash}.${inlineStylesExtension}?direct`, config))?.code;
27
24
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"angular-jit-plugin.js","names":[],"sources":["../../../src/lib/angular-jit-plugin.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { Plugin, ResolvedConfig, preprocessCSS } from 'vite';\nimport { debugStyles } from './utils/debug.js';\nimport { isTailwindReferenceError } from './utils/tailwind-reference.js';\n\nimport { shouldPreprocessTestCss } from './utils/virtual-resources.js';\n\nexport function jitPlugin({\n inlineStylesExtension,\n}: {\n inlineStylesExtension: string;\n}): Plugin {\n let config: ResolvedConfig;\n\n return {\n name: '@analogjs/vite-plugin-angular-jit',\n configResolved(_config) {\n config = _config;\n },\n resolveId(id: string) {\n if (id.startsWith('virtual:angular')) {\n return `\\0${id}`;\n }\n\n return;\n },\n async load(id: string) {\n if (id.includes('virtual:angular:jit:style:inline;')) {\n const styleId = id.split('style:inline;')[1];\n // styleId may exceed 255 bytes of base64-encoded content, limit to 16\n const styleIdHash = createHash('sha256')\n .update(styleId)\n .digest('hex')\n .slice(0, 16);\n\n const decodedStyles = Buffer.from(\n decodeURIComponent(styleId),\n 'base64',\n ).toString();\n\n let styles: string | undefined = '';\n\n // In tests, mirror Vitest's `test.css` rules — defaults to no\n // preprocessing (matches Vite's CSS pipeline behavior). Inline\n // component styles have no real file path to match include/exclude\n // patterns against, so only `test.css: true` opts them in. (#2297)\n const inlineStyleId = `${styleIdHash}.${inlineStylesExtension}`;\n if (!shouldPreprocessTestCss(config, inlineStyleId)) {\n return `export default \\`\\``;\n }\n\n try {\n const compiled = await preprocessCSS(\n decodedStyles,\n `${styleIdHash}.${inlineStylesExtension}?direct`,\n config,\n );\n styles = compiled?.code;\n } catch (e) {\n if (isTailwindReferenceError(e)) {\n throw e;\n }\n const errorMessage = e instanceof Error ? e.message : String(e);\n debugStyles('jit css compilation error', {\n styleIdHash,\n error: errorMessage,\n });\n console.warn(\n '[@analogjs/vite-plugin-angular]: Failed to preprocess inline JIT stylesheet %s. Returning an empty stylesheet instead. %s',\n styleIdHash,\n errorMessage,\n );\n }\n\n return `export default \\`${styles}\\``;\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;;;AAOA,SAAgB,UAAU,EACxB,yBAGS;CACT,IAAI;AAEJ,QAAO;EACL,MAAM;EACN,eAAe,SAAS;AACtB,YAAS;;EAEX,UAAU,IAAY;AACpB,OAAI,GAAG,WAAW,kBAAkB,CAClC,QAAO,KAAK;;EAKhB,MAAM,KAAK,IAAY;AACrB,OAAI,GAAG,SAAS,oCAAoC,EAAE;IACpD,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC;IAE1C,MAAM,cAAc,WAAW,SAAS,CACrC,OAAO,QAAQ,CACf,OAAO,MAAM,CACb,MAAM,GAAG,GAAG;IAEf,MAAM,gBAAgB,OAAO,KAC3B,mBAAmB,QAAQ,EAC3B,SACD,CAAC,UAAU;IAEZ,IAAI,SAA6B;IAMjC,MAAM,gBAAgB,GAAG,YAAY,GAAG;AACxC,QAAI,CAAC,wBAAwB,QAAQ,cAAc,CACjD,QAAO;AAGT,QAAI;AAMF,eALiB,MAAM,cACrB,eACA,GAAG,YAAY,GAAG,sBAAsB,UACxC,OACD,GACkB;aACZ,GAAG;AACV,SAAI,yBAAyB,EAAE,CAC7B,OAAM;KAER,MAAM,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AAC/D,iBAAY,6BAA6B;MACvC;MACA,OAAO;MACR,CAAC;AACF,aAAQ,KACN,6HACA,aACA,aACD;;AAGH,WAAO,oBAAoB,OAAO;;;EAKvC"}
1
+ {"version":3,"file":"angular-jit-plugin.js","names":[],"sources":["../../../src/lib/angular-jit-plugin.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { Plugin, ResolvedConfig, preprocessCSS } from 'vite';\nimport { debugStyles } from './utils/debug.js';\nimport { isTailwindReferenceError } from './utils/tailwind-reference.js';\n\nexport function jitPlugin({\n inlineStylesExtension,\n}: {\n inlineStylesExtension: string;\n}): Plugin {\n let config: ResolvedConfig;\n\n return {\n name: '@analogjs/vite-plugin-angular-jit',\n configResolved(_config) {\n config = _config;\n },\n resolveId(id: string) {\n if (id.startsWith('virtual:angular')) {\n return `\\0${id}`;\n }\n\n return;\n },\n async load(id: string) {\n if (id.includes('virtual:angular:jit:style:inline;')) {\n const styleId = id.split('style:inline;')[1];\n // styleId may exceed 255 bytes of base64-encoded content, limit to 16\n const styleIdHash = createHash('sha256')\n .update(styleId)\n .digest('hex')\n .slice(0, 16);\n\n const decodedStyles = Buffer.from(\n decodeURIComponent(styleId),\n 'base64',\n ).toString();\n\n let styles: string | undefined = '';\n\n try {\n const compiled = await preprocessCSS(\n decodedStyles,\n `${styleIdHash}.${inlineStylesExtension}?direct`,\n config,\n );\n styles = compiled?.code;\n } catch (e) {\n if (isTailwindReferenceError(e)) {\n throw e;\n }\n const errorMessage = e instanceof Error ? e.message : String(e);\n debugStyles('jit css compilation error', {\n styleIdHash,\n error: errorMessage,\n });\n console.warn(\n '[@analogjs/vite-plugin-angular]: Failed to preprocess inline JIT stylesheet %s. Returning an empty stylesheet instead. %s',\n styleIdHash,\n errorMessage,\n );\n }\n\n return `export default \\`${styles}\\``;\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;;AAKA,SAAgB,UAAU,EACxB,yBAGS;CACT,IAAI;AAEJ,QAAO;EACL,MAAM;EACN,eAAe,SAAS;AACtB,YAAS;;EAEX,UAAU,IAAY;AACpB,OAAI,GAAG,WAAW,kBAAkB,CAClC,QAAO,KAAK;;EAKhB,MAAM,KAAK,IAAY;AACrB,OAAI,GAAG,SAAS,oCAAoC,EAAE;IACpD,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC;IAE1C,MAAM,cAAc,WAAW,SAAS,CACrC,OAAO,QAAQ,CACf,OAAO,MAAM,CACb,MAAM,GAAG,GAAG;IAEf,MAAM,gBAAgB,OAAO,KAC3B,mBAAmB,QAAQ,EAC3B,SACD,CAAC,UAAU;IAEZ,IAAI,SAA6B;AAEjC,QAAI;AAMF,eALiB,MAAM,cACrB,eACA,GAAG,YAAY,GAAG,sBAAsB,UACxC,OACD,GACkB;aACZ,GAAG;AACV,SAAI,yBAAyB,EAAE,CAC7B,OAAM;KAER,MAAM,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AAC/D,iBAAY,6BAA6B;MACvC;MACA,OAAO;MACR,CAAC;AACF,aAAQ,KACN,6HACA,aACA,aACD;;AAGH,WAAO,oBAAoB,OAAO;;;EAKvC"}
@@ -2,7 +2,6 @@ import { angularFullVersion, cjt, sourceFileCache } from "./utils/devkit.js";
2
2
  import { getJsTransformConfigKey, isRolldown } from "./utils/rolldown.js";
3
3
  import { buildOptimizerPlugin } from "./angular-build-optimizer-plugin.js";
4
4
  import { activateDeferredDebug, applyDebugOption, debugCompiler, debugCompilerV, debugEmit, debugEmitV, debugHmr, debugHmrV, debugStyles, debugStylesV } from "./utils/debug.js";
5
- import { toVirtualRawId, toVirtualStyleId } from "./utils/virtual-ids.js";
6
5
  import { jitPlugin } from "./angular-jit-plugin.js";
7
6
  import { createCompilerPlugin, createRolldownCompilerPlugin } from "./compiler-plugin.js";
8
7
  import { StyleUrlsResolver, TemplateUrlsResolver, getAngularComponentMetadata } from "./component-resolvers.js";
@@ -11,9 +10,12 @@ import { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVer
11
10
  import { TS_EXT_REGEX, createTsConfigGetter, getTsConfigPath } from "./utils/plugin-config.js";
12
11
  import { TsconfigResolver } from "./utils/tsconfig-resolver.js";
13
12
  import { configureStylePipelineRegistry } from "./style-pipeline.js";
14
- import { describeStylesheetContent, injectViteIgnoreForHmrMetadata, isIgnoredHmrFile, isTestWatchMode, refreshStylesheetRegistryForFile } from "./utils/compilation-shared.js";
13
+ import { describeStylesheetContent, injectViteIgnoreForHmrMetadata, isIgnoredHmrFile, isTestWatchMode } from "./utils/compilation-shared.js";
15
14
  import { compilationAPIPlugin } from "./compilation-api/compilation-api-plugin.js";
16
15
  import "./compilation-api/index.js";
16
+ import { toVirtualRawId } from "./utils/virtual-ids.js";
17
+ import { loadVirtualRawModule, rewriteHtmlRawImport } from "./utils/virtual-resources.js";
18
+ import { markStylePathSafe } from "./utils/safe-module-paths.js";
17
19
  import { fastCompilePlugin } from "./fast-compile-plugin.js";
18
20
  import { removeActiveGraphMetadata, removeStyleOwnerMetadata, templateClassBindingGuardPlugin } from "./template-class-binding-guard-plugin.js";
19
21
  import { buildStylePreprocessor, tailwindReferencePlugin, validateTailwindConfig } from "./tailwind-plugin.js";
@@ -26,8 +28,8 @@ import { nxFolderPlugin } from "./nx-folder-plugin.js";
26
28
  import { replaceFiles } from "./plugins/file-replacements.plugin.js";
27
29
  import { routerPlugin } from "./router-plugin.js";
28
30
  import { union } from "es-toolkit";
29
- import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
30
- import { basename, dirname, join, relative, resolve } from "node:path";
31
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
32
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
31
33
  import * as compilerCli from "@angular/compiler-cli";
32
34
  import { createRequire } from "node:module";
33
35
  import { defaultClientConditions, normalizePath, preprocessCSS } from "vite";
@@ -351,32 +353,6 @@ function angular(options) {
351
353
  if (/\.(html|htm|css|less|sass|scss)$/.test(ctx.file)) {
352
354
  debugHmr("resource file changed", { file: ctx.file });
353
355
  fileTransformMap.delete(ctx.file.split("?")[0]);
354
- if (/\.(css|less|sass|scss)$/.test(ctx.file)) refreshStylesheetRegistryForFile(ctx.file, stylesheetRegistry, pluginOptions.stylePreprocessor);
355
- if (/\.(css|less|sass|scss)$/.test(ctx.file) && existsSync(ctx.file)) try {
356
- const rawResource = readFileSync(ctx.file, "utf-8");
357
- debugHmrV("resource source snapshot", {
358
- file: ctx.file,
359
- mtimeMs: safeStatMtimeMs(ctx.file),
360
- ...describeStylesheetContent(rawResource)
361
- });
362
- } catch (error) {
363
- debugHmrV("resource source snapshot failed", {
364
- file: ctx.file,
365
- error: String(error)
366
- });
367
- }
368
- const fileModules = await getModulesForChangedFile(ctx.server, ctx.file, ctx.modules, stylesheetRegistry);
369
- debugHmrV("resource modules resolved", {
370
- file: ctx.file,
371
- eventModuleCount: ctx.modules.length,
372
- fileModuleCount: fileModules.length,
373
- modules: fileModules.map((mod) => ({
374
- id: mod.id,
375
- file: mod.file,
376
- type: mod.type,
377
- url: mod.url
378
- }))
379
- });
380
356
  /**
381
357
  * Check to see if this was a direct request
382
358
  * for an external resource (styles, html).
@@ -591,7 +567,24 @@ function angular(options) {
591
567
  classNames.clear();
592
568
  return ctx.modules;
593
569
  },
594
- resolveId(id) {
570
+ resolveId(id, importer) {
571
+ if (id.startsWith("virtual:@analogjs/vite-plugin-angular:raw:")) return `\0${id}`;
572
+ if (jit && id.startsWith("angular:jit:")) {
573
+ const filePath = normalizePath(resolve(dirname(importer), id.split(";")[1]));
574
+ if (id.includes(":style")) {
575
+ markStylePathSafe(resolvedConfig, filePath);
576
+ return filePath + "?inline";
577
+ }
578
+ return toVirtualRawId(filePath);
579
+ }
580
+ const rawRewrite = rewriteHtmlRawImport(id, importer);
581
+ if (rawRewrite) return rawRewrite;
582
+ if (/\.(css|scss|sass|less)\?inline$/.test(id) && importer) {
583
+ const filePath = id.split("?")[0];
584
+ const resolved = isAbsolute(filePath) ? normalizePath(filePath) : normalizePath(resolve(dirname(importer), filePath));
585
+ markStylePathSafe(resolvedConfig, resolved);
586
+ return resolved + "?inline";
587
+ }
595
588
  if (isComponentStyleSheet(id)) {
596
589
  const filename = getFilenameFromPath(id);
597
590
  if (stylesheetRegistry?.hasServed(filename)) {
@@ -614,6 +607,9 @@ function angular(options) {
614
607
  }
615
608
  },
616
609
  async load(id) {
610
+ const rawModule = await loadVirtualRawModule(this, id);
611
+ if (rawModule !== void 0) return rawModule;
612
+ if (/\.(css|scss|sass|less)\?inline$/.test(id)) markStylePathSafe(resolvedConfig, id.split("?")[0]);
617
613
  if (isComponentStyleSheet(id)) {
618
614
  const filename = getFilenameFromPath(id);
619
615
  const componentStyles = stylesheetRegistry?.getServedContent(filename);
@@ -718,7 +714,8 @@ function angular(options) {
718
714
  });
719
715
  styleUrls.forEach((styleUrlSet) => {
720
716
  const [styleFile, resolvedStyleUrl] = styleUrlSet.split("|");
721
- data = data.replace(`angular:jit:style:file;${styleFile}`, toVirtualStyleId(resolvedStyleUrl));
717
+ markStylePathSafe(resolvedConfig, resolvedStyleUrl);
718
+ data = data.replace(`angular:jit:style:file;${styleFile}`, resolvedStyleUrl + "?inline");
722
719
  });
723
720
  }
724
721
  if (data.includes("HmrLoad")) {
@@ -972,48 +969,6 @@ function createFsWatcherCacheInvalidator(invalidateFsCaches, invalidateTsconfigC
972
969
  await performCompilation();
973
970
  };
974
971
  }
975
- /**
976
- * Returns every live Vite module that can legitimately represent a changed
977
- * Angular resource file.
978
- *
979
- * For normal files, `getModulesByFile()` is enough. For Angular component
980
- * stylesheets, it is not: the browser often holds virtual hashed requests
981
- * (`/abc123.css?direct&ngcomp=...` and `/abc123.css?ngcomp=...`) that are no
982
- * longer discoverable from the original source path alone. We therefore merge:
983
- * - watcher event modules
984
- * - module-graph modules by source file
985
- * - registry-tracked live request ids resolved back through the module graph
986
- */
987
- async function getModulesForChangedFile(server, file, eventModules = [], stylesheetRegistry) {
988
- const normalizedFile = normalizePath(file.split("?")[0]);
989
- const modules = /* @__PURE__ */ new Map();
990
- for (const mod of eventModules) if (mod.id) modules.set(mod.id, mod);
991
- server.moduleGraph.getModulesByFile(normalizedFile)?.forEach((mod) => {
992
- if (mod.id) modules.set(mod.id, mod);
993
- });
994
- const stylesheetRequestIds = stylesheetRegistry?.getRequestIdsForSource(normalizedFile) ?? [];
995
- const requestIdHits = [];
996
- for (const requestId of stylesheetRequestIds) {
997
- const candidates = [requestId, requestId.startsWith("/") ? requestId : `/${requestId}`];
998
- for (const candidate of candidates) {
999
- const mod = await server.moduleGraph.getModuleByUrl(candidate) ?? server.moduleGraph.getModuleById(candidate);
1000
- requestIdHits.push({
1001
- requestId,
1002
- candidate,
1003
- via: mod?.url === candidate ? "url" : "id",
1004
- moduleId: mod?.id
1005
- });
1006
- if (mod?.id) modules.set(mod.id, mod);
1007
- }
1008
- }
1009
- debugHmrV("getModulesForChangedFile registry lookup", {
1010
- file: normalizedFile,
1011
- stylesheetRequestIds,
1012
- requestIdHits,
1013
- resolvedModuleIds: [...modules.keys()]
1014
- });
1015
- return [...modules.values()];
1016
- }
1017
972
  function isModuleForChangedResource(mod, changedFile, stylesheetRegistry) {
1018
973
  const normalizedChangedFile = normalizePath(changedFile.split("?")[0]);
1019
974
  if (normalizePath((mod.file ?? "").split("?")[0]) === normalizedChangedFile) return true;
@@ -1021,13 +976,6 @@ function isModuleForChangedResource(mod, changedFile, stylesheetRegistry) {
1021
976
  const requestPath = getFilenameFromPath(mod.id);
1022
977
  return normalizePath((stylesheetRegistry?.resolveExternalSource(requestPath) ?? stylesheetRegistry?.resolveExternalSource(requestPath.replace(/^\//, "")) ?? "").split("?")[0]) === normalizedChangedFile;
1023
978
  }
1024
- function safeStatMtimeMs(file) {
1025
- try {
1026
- return statSync(file).mtimeMs;
1027
- } catch {
1028
- return;
1029
- }
1030
- }
1031
979
  function diagnoseComponentStylesheetPipeline(changedFile, directModule, stylesheetRegistry, wrapperModules, stylePreprocessor) {
1032
980
  const normalizedFile = normalizePath(changedFile.split("?")[0]);
1033
981
  const sourceExists = existsSync(normalizedFile);