@vizejs/vite-plugin 0.88.0 → 0.90.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.
Files changed (2) hide show
  1. package/dist/index.mjs +144 -66
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -352,11 +352,8 @@ function parseCustomMedia(css, map) {
352
352
  }
353
353
  function resolveCssPath(importPath, importer, aliasRules) {
354
354
  for (const rule of aliasRules) {
355
- const suffix = matchedAliasSuffix(importPath, rule.find);
356
- if (suffix !== null) {
357
- const resolved = path.join(rule.replacement, suffix);
358
- return path.resolve(resolved);
359
- }
355
+ const resolved = resolveAliasPath(importPath, rule);
356
+ if (resolved !== null) return path.resolve(resolved);
360
357
  }
361
358
  if (importPath.startsWith(".")) {
362
359
  const dir = path.dirname(importer);
@@ -365,6 +362,18 @@ function resolveCssPath(importPath, importer, aliasRules) {
365
362
  if (path.isAbsolute(importPath)) return importPath;
366
363
  return null;
367
364
  }
365
+ function resolveAliasPath(importPath, rule) {
366
+ if (typeof rule.find !== "string") {
367
+ const pattern = stableAliasPattern$1(rule.find);
368
+ return pattern.test(importPath) ? importPath.replace(pattern, rule.replacement) : null;
369
+ }
370
+ const suffix = matchedAliasSuffix(importPath, rule.find);
371
+ if (suffix !== null) return path.join(rule.replacement, suffix);
372
+ return null;
373
+ }
374
+ function stableAliasPattern$1(pattern) {
375
+ return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
376
+ }
368
377
  function matchedAliasSuffix(importPath, find) {
369
378
  if (importPath === find) return "";
370
379
  const prefix = find.endsWith("/") ? find : `${find}/`;
@@ -642,15 +651,14 @@ function createLogger(debug) {
642
651
  const vizeConfigStore = /* @__PURE__ */ new Map();
643
652
  //#endregion
644
653
  //#region src/compile-options.ts
645
- function buildCompileFileOptions(filePath, source, options) {
646
- const scopeId = /<style[^>]*\bscoped\b/.test(source) ? `data-v-${generateScopeId(filePath)}` : void 0;
654
+ function buildCompileFileOptions(filePath, options) {
647
655
  return {
648
656
  filename: filePath,
649
657
  sourceMap: options.sourceMap,
650
658
  ssr: options.ssr,
651
659
  vapor: options.vapor,
652
660
  customRenderer: options.customRenderer ?? false,
653
- scopeId
661
+ scopeId: `data-v-${generateScopeId(filePath)}`
654
662
  };
655
663
  }
656
664
  function buildCompileBatchOptions(options) {
@@ -663,38 +671,20 @@ function buildCompileBatchOptions(options) {
663
671
  //#endregion
664
672
  //#region src/compiler.ts
665
673
  const { compileSfc, compileSfcBatchWithResults } = native;
666
- /**
667
- * Extract style block metadata from a Vue SFC source string.
668
- * Parses `<style>` tags to determine lang, scoped, and module attributes.
669
- */
670
- function extractStyleBlocks(source) {
671
- const blocks = [];
672
- const styleRegex = /<style([^>]*)>([\s\S]*?)<\/style>/gi;
673
- let match;
674
- let index = 0;
675
- while ((match = styleRegex.exec(source)) !== null) {
676
- const attrs = match[1];
677
- const content = match[2];
678
- const lang = attrs.match(/\blang=["']([^"']+)["']/)?.[1] ?? null;
679
- const scoped = /\bscoped\b/.test(attrs);
680
- const moduleMatch = attrs.match(/\bmodule(?:=["']([^"']+)["'])?/);
681
- const isModule = moduleMatch ? moduleMatch[1] || true : false;
682
- blocks.push({
683
- content,
684
- lang,
685
- scoped,
686
- module: isModule,
687
- index
688
- });
689
- index++;
690
- }
691
- return blocks;
674
+ function normalizeStyleBlocks(styles) {
675
+ if (!styles) return [];
676
+ return styles.map((block) => ({
677
+ content: block.content,
678
+ lang: block.lang ?? null,
679
+ scoped: block.scoped,
680
+ module: block.module ? block.moduleName ?? true : false,
681
+ index: block.index
682
+ }));
692
683
  }
693
684
  function compileFile(filePath, cache, options, source) {
694
685
  const content = source ?? fs.readFileSync(filePath, "utf-8");
695
686
  const scopeId = generateScopeId(filePath);
696
- const hasScoped = /<style[^>]*\bscoped\b/.test(content);
697
- const result = compileSfc(content, buildCompileFileOptions(filePath, content, options));
687
+ const result = compileSfc(content, buildCompileFileOptions(filePath, options));
698
688
  if (result.errors.length > 0) {
699
689
  const errorMsg = result.errors.join("\n");
700
690
  console.error(`[vize] Compilation error in ${filePath}:\n${errorMsg}`);
@@ -702,17 +692,16 @@ function compileFile(filePath, cache, options, source) {
702
692
  if (result.warnings.length > 0) result.warnings.forEach((warning) => {
703
693
  console.warn(`[vize] Warning in ${filePath}: ${warning}`);
704
694
  });
705
- const styles = extractStyleBlocks(content);
706
695
  const compiled = {
707
696
  code: result.code,
708
697
  css: result.css,
709
698
  scopeId,
710
- hasScoped,
699
+ hasScoped: result.hasScoped,
711
700
  templateHash: result.templateHash,
712
701
  styleHash: result.styleHash,
713
702
  scriptHash: result.scriptHash,
714
703
  macroArtifacts: result.macroArtifacts ?? [],
715
- styles
704
+ styles: normalizeStyleBlocks(result.styles)
716
705
  };
717
706
  cache.set(filePath, compiled);
718
707
  return compiled;
@@ -726,24 +715,18 @@ function compileBatch(files, cache, options) {
726
715
  path: f.path,
727
716
  source: f.source
728
717
  })), buildCompileBatchOptions(options));
729
- const sourceMap = /* @__PURE__ */ new Map();
730
- for (const f of files) sourceMap.set(f.path, f.source);
731
718
  for (const fileResult of result.results) {
732
- if (fileResult.errors.length === 0) {
733
- const source = sourceMap.get(fileResult.path);
734
- const styles = source ? extractStyleBlocks(source) : void 0;
735
- cache.set(fileResult.path, {
736
- code: fileResult.code,
737
- css: fileResult.css,
738
- scopeId: fileResult.scopeId,
739
- hasScoped: fileResult.hasScoped,
740
- templateHash: fileResult.templateHash,
741
- styleHash: fileResult.styleHash,
742
- scriptHash: fileResult.scriptHash,
743
- macroArtifacts: fileResult.macroArtifacts ?? [],
744
- styles
745
- });
746
- }
719
+ if (fileResult.errors.length === 0) cache.set(fileResult.path, {
720
+ code: fileResult.code,
721
+ css: fileResult.css,
722
+ scopeId: fileResult.scopeId,
723
+ hasScoped: fileResult.hasScoped,
724
+ templateHash: fileResult.templateHash,
725
+ styleHash: fileResult.styleHash,
726
+ scriptHash: fileResult.scriptHash,
727
+ macroArtifacts: fileResult.macroArtifacts ?? [],
728
+ styles: normalizeStyleBlocks(fileResult.styles)
729
+ });
747
730
  if (fileResult.errors.length > 0) console.error(`[vize] Compilation error in ${fileResult.path}:\n${fileResult.errors.join("\n")}`);
748
731
  if (fileResult.warnings.length > 0) fileResult.warnings.forEach((warning) => {
749
732
  console.warn(`[vize] Warning in ${fileResult.path}: ${warning}`);
@@ -921,10 +904,51 @@ function normalizeRequireBase(importer) {
921
904
  else if (isMacroVirtualId(normalized)) normalized = normalized.slice(1).split("?")[0] ?? "";
922
905
  return normalized.split("?")[0] ?? null;
923
906
  }
907
+ function splitIdQuery(id) {
908
+ const queryStart = id.indexOf("?");
909
+ if (queryStart === -1) return [id, ""];
910
+ return [id.slice(0, queryStart), id.slice(queryStart)];
911
+ }
912
+ function isBareSpecifier(id) {
913
+ const [request] = splitIdQuery(id);
914
+ return request !== "" && !request.startsWith("./") && !request.startsWith("../") && !request.startsWith("/") && !request.startsWith("\0") && !request.includes(":");
915
+ }
916
+ function resolveAliasRequest(state, id) {
917
+ const [request, querySuffix] = splitIdQuery(id);
918
+ for (const rule of state.cssAliasRules) {
919
+ if (rule.find instanceof RegExp) {
920
+ const pattern = stableAliasPattern(rule.find);
921
+ if (pattern.test(request)) return request.replace(pattern, rule.replacement) + querySuffix;
922
+ continue;
923
+ }
924
+ if (request === rule.find) return rule.replacement + querySuffix;
925
+ const findPrefix = rule.find.endsWith("/") ? rule.find : rule.find + "/";
926
+ if (request.startsWith(findPrefix)) return (rule.replacement.endsWith("/") ? rule.replacement : rule.replacement + "/") + request.slice(findPrefix.length) + querySuffix;
927
+ }
928
+ return null;
929
+ }
930
+ function stableAliasPattern(pattern) {
931
+ return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
932
+ }
933
+ function pushPnpmHoistBases(candidates, start, isDirectory) {
934
+ if (!start) return;
935
+ let dir = isDirectory ? start : path.dirname(start);
936
+ for (;;) {
937
+ const pnpmHoist = path.join(dir, "node_modules", ".pnpm", "node_modules");
938
+ if (fs.existsSync(pnpmHoist)) {
939
+ candidates.push(path.join(pnpmHoist, "package.json"));
940
+ break;
941
+ }
942
+ const parent = path.dirname(dir);
943
+ if (parent === dir) break;
944
+ dir = parent;
945
+ }
946
+ }
924
947
  function resolveBareImportWithNode(state, id, importer) {
925
- const [request, queryPart] = id.split("?");
926
- const querySuffix = queryPart ? `?${queryPart}` : "";
948
+ const [request, querySuffix] = splitIdQuery(id);
927
949
  const candidates = [normalizeRequireBase(importer), path.join(state.root, "package.json")].filter((candidate) => candidate != null);
950
+ pushPnpmHoistBases(candidates, importer ?? null, false);
951
+ pushPnpmHoistBases(candidates, state.root, true);
928
952
  const seen = /* @__PURE__ */ new Set();
929
953
  for (const candidate of candidates) {
930
954
  if (seen.has(candidate)) continue;
@@ -935,8 +959,23 @@ function resolveBareImportWithNode(state, id, importer) {
935
959
  }
936
960
  return null;
937
961
  }
962
+ function resolveBareImportCandidatesWithNode(state, id, importer, resolvedId) {
963
+ const candidates = [
964
+ resolvedId,
965
+ resolveAliasRequest(state, id),
966
+ id
967
+ ].filter((candidate) => candidate != null && isBareSpecifier(candidate));
968
+ const seen = /* @__PURE__ */ new Set();
969
+ for (const candidate of candidates) {
970
+ if (seen.has(candidate)) continue;
971
+ seen.add(candidate);
972
+ const resolved = resolveBareImportWithNode(state, candidate, importer);
973
+ if (resolved) return resolved;
974
+ }
975
+ return null;
976
+ }
938
977
  function normalizeResolvedVuePath(id) {
939
- const pathPart = id.split("?")[0];
978
+ const [pathPart] = splitIdQuery(id);
940
979
  if (!pathPart?.endsWith(".vue")) return null;
941
980
  return pathPart.startsWith("/@fs/") ? pathPart.slice(4) : pathPart;
942
981
  }
@@ -1023,21 +1062,57 @@ async function resolveIdHook(ctx, state, id, importer, options) {
1023
1062
  }
1024
1063
  if (!id.endsWith(".vue")) {
1025
1064
  if (!id.startsWith("./") && !id.startsWith("../") && !id.startsWith("/")) {
1026
- if (!state.cssAliasRules.some((rule) => id === rule.find || id.startsWith(rule.find + "/"))) {
1065
+ const aliasRequest = resolveAliasRequest(state, id);
1066
+ if (aliasRequest && isBareSpecifier(aliasRequest)) {
1067
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
1068
+ if (nodeResolved) {
1069
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
1070
+ return nodeResolved;
1071
+ }
1072
+ }
1073
+ try {
1074
+ const resolved = await ctx.resolve(id, cleanImporter, { skipSelf: true });
1075
+ if (resolved) {
1076
+ state.logger.log(`resolveId: resolved bare ${id} to ${resolved.id} via Vite resolver`);
1077
+ if (isBuild && resolved.id.startsWith("/@fs/")) return {
1078
+ ...resolved,
1079
+ id: normalizeFsIdForBuild(resolved.id)
1080
+ };
1081
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
1082
+ if (nodeResolved) {
1083
+ state.logger.log(`resolveId: normalized bare ${id} to ${nodeResolved} via Node fallback`);
1084
+ return nodeResolved;
1085
+ }
1086
+ if (isBareSpecifier(resolved.id)) return null;
1087
+ return resolved;
1088
+ }
1089
+ } catch {}
1090
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
1091
+ if (nodeResolved) {
1092
+ state.logger.log(`resolveId: resolved bare ${id} to ${nodeResolved} via Node fallback`);
1093
+ return nodeResolved;
1094
+ }
1095
+ if (aliasRequest && aliasRequest !== id && !isBareSpecifier(aliasRequest)) {
1027
1096
  try {
1028
- const resolved = await ctx.resolve(id, cleanImporter, { skipSelf: true });
1097
+ const resolved = await ctx.resolve(aliasRequest, cleanImporter, { skipSelf: true });
1029
1098
  if (resolved) {
1030
- state.logger.log(`resolveId: resolved bare ${id} to ${resolved.id} via Vite resolver`);
1099
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${resolved.id} via Vite resolver`);
1031
1100
  if (isBuild && resolved.id.startsWith("/@fs/")) return {
1032
1101
  ...resolved,
1033
1102
  id: normalizeFsIdForBuild(resolved.id)
1034
1103
  };
1104
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
1105
+ if (nodeResolved) {
1106
+ state.logger.log(`resolveId: normalized aliased bare ${id} to ${nodeResolved} via Node fallback`);
1107
+ return nodeResolved;
1108
+ }
1109
+ if (isBareSpecifier(resolved.id)) return null;
1035
1110
  return resolved;
1036
1111
  }
1037
1112
  } catch {}
1038
- const nodeResolved = resolveBareImportWithNode(state, id, cleanImporter);
1113
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, aliasRequest, cleanImporter);
1039
1114
  if (nodeResolved) {
1040
- state.logger.log(`resolveId: resolved bare ${id} to ${nodeResolved} via Node fallback`);
1115
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
1041
1116
  return nodeResolved;
1042
1117
  }
1043
1118
  }
@@ -1515,6 +1590,9 @@ function patchUnoCssBridge(plugins) {
1515
1590
  }
1516
1591
  //#endregion
1517
1592
  //#region src/plugin/index.ts
1593
+ function aliasSortKey(find) {
1594
+ return typeof find === "string" ? find.length : find.source.length;
1595
+ }
1518
1596
  function vize(options = {}) {
1519
1597
  const state = {
1520
1598
  cache: /* @__PURE__ */ new Map(),
@@ -1632,13 +1710,13 @@ function vize(options = {}) {
1632
1710
  state.dynamicImportAliasRules.sort((a, b) => b.fromPrefix.length - a.fromPrefix.length);
1633
1711
  state.cssAliasRules = [];
1634
1712
  for (const alias of resolvedConfig.resolve.alias) {
1635
- if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
1713
+ if (!(typeof alias.find === "string" || alias.find instanceof RegExp) || typeof alias.replacement !== "string") continue;
1636
1714
  state.cssAliasRules.push({
1637
1715
  find: alias.find,
1638
1716
  replacement: alias.replacement
1639
1717
  });
1640
1718
  }
1641
- state.cssAliasRules.sort((a, b) => b.find.length - a.find.length);
1719
+ state.cssAliasRules.sort((a, b) => aliasSortKey(b.find) - aliasSortKey(a.find));
1642
1720
  state.filter = createFilter(state.mergedOptions.include, state.mergedOptions.exclude);
1643
1721
  state.scanPatterns = state.mergedOptions.scanPatterns ?? ["**/*.vue"];
1644
1722
  state.precompileBatchSize = normalizePrecompileBatchSize(state.mergedOptions.precompileBatchSize);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizejs/vite-plugin",
3
- "version": "0.88.0",
3
+ "version": "0.90.0",
4
4
  "description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
5
5
  "keywords": [
6
6
  "compiler",
@@ -33,9 +33,9 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@vizejs/native": "0.88.0",
36
+ "@vizejs/native": "0.90.0",
37
37
  "tinyglobby": "0.2.16",
38
- "vize": "0.88.0"
38
+ "vize": "0.90.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "25.7.0",