auklet 0.2.2 → 0.2.4

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.
@@ -9,6 +9,10 @@ export declare class ModuleStyleImportCollector {
9
9
  collect(files: Array<string>, config: NormalizedAukletConfig): Map<string, string[]>;
10
10
  private collectSourceImportStyle;
11
11
  private resolveSourceImportStyleEntry;
12
+ private appendResolvedSourceImportStyles;
13
+ private addAcceptedSourceImportEdge;
14
+ private hasSourceImportPath;
15
+ private hasSourceModule;
12
16
  private isInsideSourceRoot;
13
17
  private resolveSourceImportPaths;
14
18
  private toSourceBase;
@@ -7,6 +7,7 @@ import { resolveRelativeSourceImport } from '#auklet/css/core/resolvers/relative
7
7
  import { resolvePackageImportsSourceImport } from '#auklet/css/core/resolvers/packageImports';
8
8
  import { resolveTsconfigPathsSourceImport } from '#auklet/css/core/resolvers/tsconfigPaths';
9
9
  import { matchStyleAutoImportRules, createStyleAutoImportRules, createStyleAutoImportSpecifier, createDirectStyleAutoImportSpecifier, } from '#auklet/css/core/styleImports/autoImportRules';
10
+ const SOURCE_MODULE_EXTENSION = '.tsx';
10
11
  const SOURCE_EXTENSION_RE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
11
12
  const SOURCE_INDEX_RE = new RegExp(`[/\\\\]index${SOURCE_EXTENSION_RE.source}`);
12
13
  export class ModuleStyleImportCollector {
@@ -22,6 +23,8 @@ export class ModuleStyleImportCollector {
22
23
  }
23
24
  collect(files, config) {
24
25
  const entries = new Map();
26
+ const sourceImportEdges = new Map();
27
+ const acceptedSourceImportEdges = new Map();
25
28
  const rules = createStyleAutoImportRules(config);
26
29
  for (const file of files) {
27
30
  if (!SOURCE_MODULE_RE.test(file)) {
@@ -33,7 +36,7 @@ export class ModuleStyleImportCollector {
33
36
  const code = fs.readFileSync(file, 'utf8');
34
37
  const imports = collectModuleImportReferences(file, code);
35
38
  for (const item of imports) {
36
- this.collectSourceImportStyle(entries, sourceDir, sourceModuleDir, item);
39
+ this.collectSourceImportStyle(entries, sourceImportEdges, acceptedSourceImportEdges, sourceDir, sourceModuleDir, item);
37
40
  if (isTypeOnlyModuleReference(item))
38
41
  continue;
39
42
  const importPath = item.importPath;
@@ -66,16 +69,28 @@ export class ModuleStyleImportCollector {
66
69
  }
67
70
  }
68
71
  }
72
+ this.appendResolvedSourceImportStyles(entries, sourceImportEdges, acceptedSourceImportEdges);
69
73
  return entries;
70
74
  }
71
- collectSourceImportStyle(entries, sourceDir, sourceModuleDir, item) {
75
+ collectSourceImportStyle(entries, sourceImportEdges, acceptedSourceImportEdges, sourceDir, sourceModuleDir, item) {
72
76
  if (isTypeOnlyModuleReference(item))
73
77
  return;
74
78
  const importedStyleEntry = this.resolveSourceImportStyleEntry(sourceDir, item.importPath);
75
79
  if (!importedStyleEntry)
76
80
  return;
77
81
  const sourceStyleDir = path.join(this.srcRoot, sourceModuleDir, 'style');
78
- appendUniqueMapValue(entries, sourceModuleDir, this.toRelativeSpecifier(sourceStyleDir, importedStyleEntry));
82
+ const edge = {
83
+ ...importedStyleEntry,
84
+ specifier: this.toRelativeSpecifier(sourceStyleDir, importedStyleEntry.styleEntry),
85
+ };
86
+ if (importedStyleEntry.hasOwnStyle) {
87
+ if (!this.addAcceptedSourceImportEdge(acceptedSourceImportEdges, sourceModuleDir, edge.sourceDir)) {
88
+ return;
89
+ }
90
+ appendUniqueMapValue(entries, sourceModuleDir, edge.specifier);
91
+ return;
92
+ }
93
+ appendUniqueMapValue(sourceImportEdges, sourceModuleDir, edge);
79
94
  }
80
95
  resolveSourceImportStyleEntry(sourceDir, importPath) {
81
96
  const sourceRelativePaths = this.resolveSourceImportPaths(sourceDir, importPath);
@@ -84,17 +99,75 @@ export class ModuleStyleImportCollector {
84
99
  if (!this.isInsideSourceRoot(sourceBase))
85
100
  continue;
86
101
  const directoryStyleEntry = path.join(sourceBase, 'style', 'index.css');
87
- for (const extension of this.styleExtensions) {
88
- const directorySourceStyle = path.join(sourceBase, `index${extension}`);
89
- if (fs.existsSync(directorySourceStyle))
90
- return directoryStyleEntry;
102
+ const directorySourceStyle = this.styleExtensions.some((extension) => fs.existsSync(path.join(sourceBase, `index${extension}`)));
103
+ const directorySourceModule = this.hasSourceModule(path.join(sourceBase, 'index'));
104
+ if (directorySourceStyle || directorySourceModule) {
105
+ return {
106
+ sourceDir: path.relative(this.srcRoot, sourceBase),
107
+ styleEntry: directoryStyleEntry,
108
+ hasOwnStyle: directorySourceStyle,
109
+ };
91
110
  }
92
111
  const hasFileSourceStyle = this.styleExtensions.some((extension) => fs.existsSync(`${sourceBase}${extension}`));
93
- if (hasFileSourceStyle)
94
- return path.join(sourceBase, 'style', 'index.css');
112
+ const hasFileSourceModule = this.hasSourceModule(sourceBase);
113
+ if (hasFileSourceStyle || hasFileSourceModule)
114
+ return {
115
+ sourceDir: path.relative(this.srcRoot, sourceBase),
116
+ styleEntry: path.join(sourceBase, 'style', 'index.css'),
117
+ hasOwnStyle: hasFileSourceStyle,
118
+ };
95
119
  }
96
120
  return null;
97
121
  }
122
+ appendResolvedSourceImportStyles(entries, sourceImportEdges, acceptedSourceImportEdges) {
123
+ const styledSourceDirs = new Set(entries.keys());
124
+ let changed = true;
125
+ while (changed) {
126
+ changed = false;
127
+ for (const [sourceModuleDir, edges] of sourceImportEdges) {
128
+ for (const edge of edges) {
129
+ if (!edge.hasOwnStyle && !styledSourceDirs.has(edge.sourceDir)) {
130
+ continue;
131
+ }
132
+ if (!this.addAcceptedSourceImportEdge(acceptedSourceImportEdges, sourceModuleDir, edge.sourceDir)) {
133
+ continue;
134
+ }
135
+ const before = entries.get(sourceModuleDir)?.length ?? 0;
136
+ appendUniqueMapValue(entries, sourceModuleDir, edge.specifier);
137
+ const after = entries.get(sourceModuleDir)?.length ?? 0;
138
+ if (after === before)
139
+ continue;
140
+ styledSourceDirs.add(sourceModuleDir);
141
+ changed = true;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ addAcceptedSourceImportEdge(edges, sourceDir, targetDir) {
147
+ if (sourceDir === targetDir)
148
+ return false;
149
+ if (this.hasSourceImportPath(edges, targetDir, sourceDir))
150
+ return false;
151
+ const targets = edges.get(sourceDir) ?? new Set();
152
+ targets.add(targetDir);
153
+ edges.set(sourceDir, targets);
154
+ return true;
155
+ }
156
+ hasSourceImportPath(edges, fromDir, toDir, seen = new Set()) {
157
+ if (fromDir === toDir)
158
+ return true;
159
+ if (seen.has(fromDir))
160
+ return false;
161
+ seen.add(fromDir);
162
+ for (const nextDir of edges.get(fromDir) ?? []) {
163
+ if (this.hasSourceImportPath(edges, nextDir, toDir, seen))
164
+ return true;
165
+ }
166
+ return false;
167
+ }
168
+ hasSourceModule(sourceBase) {
169
+ return fs.existsSync(`${sourceBase}${SOURCE_MODULE_EXTENSION}`);
170
+ }
98
171
  isInsideSourceRoot(file) {
99
172
  const relative = path.relative(this.srcRoot, file);
100
173
  return !relative.startsWith('..') && !path.isAbsolute(relative);
@@ -7,6 +7,7 @@ export declare class AukletStyleHmr {
7
7
  private readonly virtualIdsByDependency;
8
8
  constructor(graph: () => ModuleStyleGraph);
9
9
  trackVirtualStyleDependency(file: string, virtualId: string): void;
10
+ hasTrackedStyleDependency(file: string): boolean;
10
11
  installFullReloadGuard(server: Pick<ViteDevServer, 'ws'>): void;
11
12
  handleStyleHotUpdate(context: HotUpdateOptions): never[] | undefined;
12
13
  handleSourceModuleChange(server: Pick<ViteDevServer, 'moduleGraph' | 'ws'>, file: string): boolean;
@@ -50,6 +50,9 @@ export class AukletStyleHmr {
50
50
  trackVirtualStyleDependency(file, virtualId) {
51
51
  addVirtualStyleDependency(this.virtualIdsByDependency, file, virtualId);
52
52
  }
53
+ hasTrackedStyleDependency(file) {
54
+ return (getDependencyVirtualIds(this.virtualIdsByDependency, file).length > 0);
55
+ }
53
56
  installFullReloadGuard(server) {
54
57
  const send = server.ws.send.bind(server.ws);
55
58
  server.ws.send = ((payload, data) => {
@@ -115,21 +115,24 @@ export function aukletStylePlugin(options = {}) {
115
115
  return;
116
116
  server.ws.send({ type: 'full-reload' });
117
117
  };
118
- const handleSourceAddOrUnlink = (file) => {
119
- if (graph.isStyleFile(file)) {
120
- reloadStyleGraph(file);
121
- return;
122
- }
123
- reloadStyleGraph(file);
124
- };
125
- server.watcher.on('add', handleSourceAddOrUnlink);
126
- server.watcher.on('unlink', handleSourceAddOrUnlink);
118
+ server.watcher.on('add', reloadStyleGraph);
119
+ server.watcher.on('unlink', reloadStyleGraph);
127
120
  server.watcher.on('change', (file) => {
128
121
  if (graph.isStyleConfigFile(file)) {
129
122
  reloadStyleGraph(file);
130
- return;
131
123
  }
132
- if (graph.isSourceModuleFile(file)) {
124
+ else if (graph.isStyleFile(file) &&
125
+ hmr.hasTrackedStyleDependency(file)) {
126
+ hmr.handleStyleHotUpdate({
127
+ file,
128
+ modules: [],
129
+ server,
130
+ timestamp: Date.now(),
131
+ type: 'update',
132
+ read: async () => '',
133
+ });
134
+ }
135
+ else if (graph.isSourceModuleFile(file)) {
133
136
  hmr.handleSourceModuleChange(server, file);
134
137
  }
135
138
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",