auklet 0.0.1 → 0.0.3

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 (42) hide show
  1. package/README.md +207 -0
  2. package/bin/entry.cjs +136 -0
  3. package/dist/build/runTsdown.d.ts +8 -0
  4. package/dist/build/runTsdown.js +36 -0
  5. package/dist/build/tsdownConfig.d.ts +12 -0
  6. package/dist/build/tsdownConfig.js +223 -0
  7. package/dist/config.d.ts +8 -0
  8. package/dist/config.js +14 -0
  9. package/dist/configLoader.d.ts +8 -0
  10. package/dist/configLoader.js +85 -0
  11. package/dist/css/core/config.d.ts +2 -0
  12. package/dist/css/core/config.js +11 -0
  13. package/dist/css/core/constants.d.ts +3 -0
  14. package/dist/css/core/constants.js +3 -0
  15. package/dist/css/core/moduleCssGraph.d.ts +51 -0
  16. package/dist/css/core/moduleCssGraph.js +416 -0
  17. package/dist/css/core/moduleStyleImportCollector.d.ts +29 -0
  18. package/dist/css/core/moduleStyleImportCollector.js +285 -0
  19. package/dist/css/core/path.d.ts +4 -0
  20. package/dist/css/core/path.js +26 -0
  21. package/dist/css/core/styleEntry.d.ts +45 -0
  22. package/dist/css/core/styleEntry.js +108 -0
  23. package/dist/css/core/styleProcessor.d.ts +16 -0
  24. package/dist/css/core/styleProcessor.js +123 -0
  25. package/dist/css/core/workspaceStyleResolver.d.ts +18 -0
  26. package/dist/css/core/workspaceStyleResolver.js +100 -0
  27. package/dist/css/production/moduleCssBuilder.d.ts +33 -0
  28. package/dist/css/production/moduleCssBuilder.js +445 -0
  29. package/dist/css/vite/hmr.d.ts +15 -0
  30. package/dist/css/vite/hmr.js +153 -0
  31. package/dist/css/vite/vitePlugin.d.ts +24 -0
  32. package/dist/css/vite/vitePlugin.js +140 -0
  33. package/dist/css/watch/moduleCssWatcher.d.ts +19 -0
  34. package/dist/css/watch/moduleCssWatcher.js +106 -0
  35. package/dist/index.d.ts +26 -0
  36. package/dist/index.js +12 -0
  37. package/dist/types.d.ts +58 -0
  38. package/dist/types.js +0 -0
  39. package/dist/utils.d.ts +20 -0
  40. package/dist/utils.js +59 -0
  41. package/package.json +80 -8
  42. package/index.js +0 -1
@@ -0,0 +1,285 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import ts from 'typescript';
4
+ import { isArray } from 'aidly';
5
+ import {
6
+ appendUniqueMapValue,
7
+ getSourceModuleDir,
8
+ SOURCE_DECLARATION_RE,
9
+ POSIX_SEPARATOR,
10
+ SOURCE_MODULE_RE,
11
+ } from '#auklet/utils';
12
+ const GLOBSTAR_TOKEN = '**';
13
+ export class ModuleStyleImportCollector {
14
+ constructor(srcRoot, packageRoot, resolver, styleExtensions = ['.css']) {
15
+ this.srcRoot = srcRoot;
16
+ this.packageRoot = packageRoot;
17
+ this.resolver = resolver;
18
+ this.styleExtensions = styleExtensions;
19
+ this.sourceImportAliasRules = this.createSourceImportAliasRules();
20
+ }
21
+ collect(files, cssOptions) {
22
+ const entries = new Map();
23
+ const rules = this.createAutoImportRules(cssOptions);
24
+ for (const file of files) {
25
+ if (!SOURCE_MODULE_RE.test(file) || SOURCE_DECLARATION_RE.test(file)) {
26
+ continue;
27
+ }
28
+ const sourceRelative = path.relative(this.srcRoot, file);
29
+ const sourceDir = path.dirname(sourceRelative);
30
+ const sourceModuleDir = getSourceModuleDir(sourceRelative);
31
+ const code = fs.readFileSync(file, 'utf8');
32
+ const imports = this.getImportDeclarations(file, code);
33
+ for (const item of imports) {
34
+ this.collectSourceImportStyle(
35
+ entries,
36
+ sourceDir,
37
+ sourceModuleDir,
38
+ item,
39
+ );
40
+ const importPath = item.importPath;
41
+ const ruleMatches = this.matchAutoImportRules(rules, importPath);
42
+ if (!ruleMatches.length) continue;
43
+ const directSpecifiers = ruleMatches
44
+ .map((ruleMatch) =>
45
+ this.createDirectStyleSpecifier(ruleMatch.rule, importPath),
46
+ )
47
+ .filter((specifier) => Boolean(specifier));
48
+ if (directSpecifiers.length) {
49
+ for (const specifier of directSpecifiers) {
50
+ const cssFile = this.resolver.resolveStyleDependency(specifier);
51
+ if (fs.existsSync(cssFile)) {
52
+ appendUniqueMapValue(entries, sourceModuleDir, specifier);
53
+ }
54
+ }
55
+ continue;
56
+ }
57
+ for (const ruleMatch of ruleMatches) {
58
+ const importedNames = this.getImportedNames(file, item);
59
+ for (const importedName of importedNames) {
60
+ const specifier = this.createStyleSpecifier(
61
+ ruleMatch.rule,
62
+ ruleMatch.values,
63
+ importedName,
64
+ );
65
+ const cssFile = this.resolver.resolveStyleDependency(specifier);
66
+ if (!fs.existsSync(cssFile)) {
67
+ continue;
68
+ }
69
+ appendUniqueMapValue(entries, sourceModuleDir, specifier);
70
+ }
71
+ }
72
+ }
73
+ }
74
+ return entries;
75
+ }
76
+ getImportDeclarations(file, code) {
77
+ const imports = [];
78
+ const sourceFile = ts.createSourceFile(
79
+ file,
80
+ code,
81
+ ts.ScriptTarget.Latest,
82
+ false,
83
+ file.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
84
+ );
85
+ sourceFile.forEachChild((node) => {
86
+ if (
87
+ !ts.isImportDeclaration(node) ||
88
+ !ts.isStringLiteral(node.moduleSpecifier)
89
+ ) {
90
+ return;
91
+ }
92
+ imports.push({
93
+ importPath: node.moduleSpecifier.text,
94
+ importClause: node.importClause,
95
+ });
96
+ });
97
+ return imports;
98
+ }
99
+ collectSourceImportStyle(entries, sourceDir, sourceModuleDir, item) {
100
+ var _a;
101
+ if (
102
+ (_a = item.importClause) === null || _a === void 0
103
+ ? void 0
104
+ : _a.isTypeOnly
105
+ )
106
+ return;
107
+ const importedStyleEntry = this.resolveSourceImportStyleEntry(
108
+ sourceDir,
109
+ item.importPath,
110
+ );
111
+ if (!importedStyleEntry) return;
112
+ const sourceStyleDir = path.join(this.srcRoot, sourceModuleDir, 'style');
113
+ appendUniqueMapValue(
114
+ entries,
115
+ sourceModuleDir,
116
+ this.toRelativeSpecifier(sourceStyleDir, importedStyleEntry),
117
+ );
118
+ }
119
+ resolveSourceImportStyleEntry(sourceDir, importPath) {
120
+ const sourceRelativePath = this.resolveSourceImportPath(
121
+ sourceDir,
122
+ importPath,
123
+ );
124
+ if (!sourceRelativePath) return null;
125
+ const sourceBase = path.join(this.srcRoot, sourceRelativePath);
126
+ const directoryStyleEntry = path.join(sourceBase, 'style', 'index.css');
127
+ for (const extension of this.styleExtensions) {
128
+ const directorySourceStyle = path.join(sourceBase, `index${extension}`);
129
+ if (fs.existsSync(directorySourceStyle)) return directoryStyleEntry;
130
+ }
131
+ const hasFileSourceStyle = this.styleExtensions.some((extension) =>
132
+ fs.existsSync(`${sourceBase}${extension}`),
133
+ );
134
+ if (!hasFileSourceStyle) return null;
135
+ return path.join(sourceBase, 'style', 'index.css');
136
+ }
137
+ resolveSourceImportPath(sourceDir, importPath) {
138
+ if (importPath.startsWith('.')) {
139
+ return path.normalize(path.join(sourceDir, importPath));
140
+ }
141
+ for (const rule of this.sourceImportAliasRules) {
142
+ if (!importPath.startsWith(rule.prefix)) continue;
143
+ return importPath.slice(rule.prefix.length);
144
+ }
145
+ return null;
146
+ }
147
+ createSourceImportAliasRules() {
148
+ var _a;
149
+ const packageJsonPath = path.join(this.packageRoot, 'package.json');
150
+ if (!fs.existsSync(packageJsonPath)) return [];
151
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
152
+ const rules = [];
153
+ for (const [name, target] of Object.entries(
154
+ (_a = packageJson.imports) !== null && _a !== void 0 ? _a : {},
155
+ )) {
156
+ if (
157
+ !name.endsWith(`${POSIX_SEPARATOR}*`) ||
158
+ typeof target !== 'string' ||
159
+ !target.includes('*')
160
+ ) {
161
+ continue;
162
+ }
163
+ rules.push({
164
+ prefix: name.slice(0, -1),
165
+ });
166
+ }
167
+ return rules;
168
+ }
169
+ toRelativeSpecifier(fromDir, file) {
170
+ const relative = path.relative(fromDir, file).split(path.sep).join('/');
171
+ return relative.startsWith('.') ? relative : `./${relative}`;
172
+ }
173
+ createAutoImportRules(cssOptions) {
174
+ var _a;
175
+ const rules = [];
176
+ for (const [packageName, dependency] of Object.entries(
177
+ (_a = cssOptions.cssDependencies) !== null && _a !== void 0 ? _a : {},
178
+ )) {
179
+ const dependencyPaths = isArray(dependency.component)
180
+ ? dependency.component
181
+ : [dependency.component].filter((value) => Boolean(value));
182
+ for (const dependencyPath of dependencyPaths) {
183
+ rules.push({
184
+ packageName,
185
+ outputPattern: this.joinDependencySpecifier(
186
+ packageName,
187
+ dependencyPath,
188
+ ),
189
+ });
190
+ }
191
+ }
192
+ return rules;
193
+ }
194
+ matchAutoImportRules(rules, importPath) {
195
+ const matches = [];
196
+ for (const rule of rules) {
197
+ if (
198
+ importPath !== rule.packageName &&
199
+ !importPath.startsWith(`${rule.packageName}${POSIX_SEPARATOR}`)
200
+ ) {
201
+ continue;
202
+ }
203
+ matches.push({
204
+ rule,
205
+ values: this.getImportPathValues(rule.packageName, importPath),
206
+ });
207
+ }
208
+ return matches;
209
+ }
210
+ getImportPathValues(packageName, importPath) {
211
+ return importPath
212
+ .slice(packageName.length)
213
+ .replace(new RegExp(`^${POSIX_SEPARATOR}`), '')
214
+ .split(POSIX_SEPARATOR)
215
+ .filter(Boolean);
216
+ }
217
+ createStyleSpecifier(rule, values, importedName) {
218
+ const pathValues = [...values];
219
+ return rule.outputPattern.replace(/\*\*|\*/g, (token) => {
220
+ const matchedValue = pathValues.shift();
221
+ if (matchedValue) return matchedValue;
222
+ if (token === GLOBSTAR_TOKEN) return importedName;
223
+ return matchedValue !== null && matchedValue !== void 0
224
+ ? matchedValue
225
+ : importedName;
226
+ });
227
+ }
228
+ createDirectStyleSpecifier(rule, importPath) {
229
+ const wildcardIndex = rule.outputPattern.indexOf('*');
230
+ if (wildcardIndex < 0) {
231
+ return null;
232
+ }
233
+ const wildcardLength = rule.outputPattern.startsWith(
234
+ GLOBSTAR_TOKEN,
235
+ wildcardIndex,
236
+ )
237
+ ? GLOBSTAR_TOKEN.length
238
+ : 1;
239
+ const prefix = rule.outputPattern.slice(0, wildcardIndex);
240
+ const suffix = rule.outputPattern.slice(wildcardIndex + wildcardLength);
241
+ if (!importPath.startsWith(prefix)) {
242
+ return null;
243
+ }
244
+ return `${importPath}${suffix}`;
245
+ }
246
+ joinDependencySpecifier(packageName, dependencyPath) {
247
+ if (!dependencyPath) return packageName;
248
+ if (dependencyPath.startsWith(POSIX_SEPARATOR)) {
249
+ return `${packageName}${dependencyPath}`;
250
+ }
251
+ return `${packageName}${POSIX_SEPARATOR}${dependencyPath}`;
252
+ }
253
+ getImportedNames(file, item) {
254
+ var _a;
255
+ const importClause = item.importClause;
256
+ if (!importClause || importClause.isTypeOnly) {
257
+ return [];
258
+ }
259
+ const names = [];
260
+ if (importClause.name) {
261
+ names.push(importClause.name.text);
262
+ }
263
+ const namedBindings = importClause.namedBindings;
264
+ if (!namedBindings) {
265
+ return names;
266
+ }
267
+ if (ts.isNamespaceImport(namedBindings)) {
268
+ throw new Error(
269
+ `Namespace import is not supported for CSS auto import: ${item.importPath}\n` +
270
+ `Use named imports instead, for example: import { Component } from '${item.importPath}'.\n` +
271
+ `File: ${file}`,
272
+ );
273
+ }
274
+ for (const element of namedBindings.elements) {
275
+ if (element.isTypeOnly) continue;
276
+ names.push(
277
+ ((_a = element.propertyName) !== null && _a !== void 0
278
+ ? _a
279
+ : element.name
280
+ ).text,
281
+ );
282
+ }
283
+ return names;
284
+ }
285
+ }
@@ -0,0 +1,4 @@
1
+ export declare function isWindowsAbsolutePath(file: string): boolean;
2
+ export declare function normalizeCssFileKey(file: string): string;
3
+ export declare function toCssFsSpecifier(file: string): string;
4
+ export declare function toCssWatchPath(...parts: Array<string>): string;
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { toPosixPath } from '#auklet/utils';
4
+ const WINDOWS_ABSOLUTE_PATH_RE = /^[a-zA-Z]:[\\/]/;
5
+ export function isWindowsAbsolutePath(file) {
6
+ return WINDOWS_ABSOLUTE_PATH_RE.test(file);
7
+ }
8
+ export function normalizeCssFileKey(file) {
9
+ if (process.platform !== 'win32' && isWindowsAbsolutePath(file)) {
10
+ return toPosixPath(file);
11
+ }
12
+ const resolved = path.resolve(file);
13
+ const realpath = fs.existsSync(resolved)
14
+ ? fs.realpathSync.native(resolved)
15
+ : resolved;
16
+ return toPosixPath(realpath);
17
+ }
18
+ export function toCssFsSpecifier(file) {
19
+ return path.posix.join('/@fs', normalizeCssFileKey(file));
20
+ }
21
+ export function toCssWatchPath(...parts) {
22
+ if (parts[0] && isWindowsAbsolutePath(parts[0])) {
23
+ return toPosixPath(path.win32.join(...parts));
24
+ }
25
+ return toPosixPath(path.join(...parts));
26
+ }
@@ -0,0 +1,45 @@
1
+ import type { CssOptions } from '#auklet/types';
2
+ export declare const STYLE_ENTRY = 'style.css';
3
+ export declare const EXTERNAL_ENTRY = 'external.css';
4
+ export declare const MODULE_ENTRY = 'module.css';
5
+ export declare const THEMES_DIR = 'themes';
6
+ export declare const THEMES_ENTRY_PREFIX = 'themes/';
7
+ export type PackageStyleSpecifier = {
8
+ packageName: string;
9
+ stylePath: string;
10
+ };
11
+ export declare function groupStyleFilesByDir(
12
+ sourceRoot: string,
13
+ styleFiles: Array<string>,
14
+ ): Map<string, string[]>;
15
+ export declare function getGlobalStyleDependencies(
16
+ cssOptions: CssOptions,
17
+ ): string[];
18
+ export declare function getExternalStyleDependencies(
19
+ cssOptions: CssOptions,
20
+ ): string[];
21
+ export declare function getThemeStyleDependencies(
22
+ cssOptions: CssOptions,
23
+ themeName: string,
24
+ ): string[];
25
+ export declare function getThemeStyleEntries(cssOptions: CssOptions): {
26
+ themeName: string;
27
+ file: string;
28
+ }[];
29
+ export declare function resolveThemeStyleFiles(
30
+ cssOptions: CssOptions,
31
+ packageRoot: string,
32
+ ): Map<string, string>;
33
+ export declare function createStyleFileKeySet(
34
+ styleFiles: Iterable<string>,
35
+ ): Set<string>;
36
+ export declare function createStyleFileKey(styleFile: string): string;
37
+ export declare function parsePackageStyleSpecifier(
38
+ specifier: string,
39
+ ): PackageStyleSpecifier | null;
40
+ export declare function joinDependencySpecifier(
41
+ packageName: string,
42
+ dependencyPath: string,
43
+ ): string;
44
+ export declare function createImportCode(specifiers: Array<string>): string;
45
+ export declare function removeCssExtension(cssPath: string): string;
@@ -0,0 +1,108 @@
1
+ import path from 'node:path';
2
+ import { isArray } from 'aidly';
3
+ import { getSourceModuleDir } from '#auklet/utils';
4
+ import { normalizeCssFileKey } from '#auklet/css/core/path';
5
+ export const STYLE_ENTRY = 'style.css';
6
+ export const EXTERNAL_ENTRY = 'external.css';
7
+ export const MODULE_ENTRY = 'module.css';
8
+ export const THEMES_DIR = 'themes';
9
+ export const THEMES_ENTRY_PREFIX = 'themes/';
10
+ export function groupStyleFilesByDir(sourceRoot, styleFiles) {
11
+ var _a;
12
+ const styleFilesByDir = new Map();
13
+ for (const styleFile of styleFiles) {
14
+ const sourceRelative = path.relative(sourceRoot, styleFile);
15
+ const sourceDir = getSourceModuleDir(sourceRelative);
16
+ const values =
17
+ (_a = styleFilesByDir.get(sourceDir)) !== null && _a !== void 0 ? _a : [];
18
+ values.push(styleFile);
19
+ styleFilesByDir.set(sourceDir, values);
20
+ }
21
+ return styleFilesByDir;
22
+ }
23
+ export function getGlobalStyleDependencies(cssOptions) {
24
+ var _a;
25
+ const dependencies = [];
26
+ for (const [packageName, dependency] of Object.entries(
27
+ (_a = cssOptions.cssDependencies) !== null && _a !== void 0 ? _a : {},
28
+ )) {
29
+ const globalDependencies = isArray(dependency.global)
30
+ ? dependency.global
31
+ : [dependency.global].filter((value) => Boolean(value));
32
+ for (const globalDependency of globalDependencies) {
33
+ dependencies.push(joinDependencySpecifier(packageName, globalDependency));
34
+ }
35
+ }
36
+ return dependencies;
37
+ }
38
+ export function getExternalStyleDependencies(cssOptions) {
39
+ return getGlobalStyleDependencies(cssOptions);
40
+ }
41
+ export function getThemeStyleDependencies(cssOptions, themeName) {
42
+ var _a, _b;
43
+ const dependencies = [];
44
+ for (const [packageName, dependency] of Object.entries(
45
+ (_a = cssOptions.cssDependencies) !== null && _a !== void 0 ? _a : {},
46
+ )) {
47
+ const themeDependency =
48
+ (_b = dependency.themes) === null || _b === void 0
49
+ ? void 0
50
+ : _b[themeName];
51
+ if (!themeDependency) continue;
52
+ dependencies.push(joinDependencySpecifier(packageName, themeDependency));
53
+ }
54
+ return dependencies;
55
+ }
56
+ export function getThemeStyleEntries(cssOptions) {
57
+ var _a;
58
+ return Object.entries(
59
+ (_a = cssOptions.themes) !== null && _a !== void 0 ? _a : {},
60
+ ).map(([themeName, file]) => ({
61
+ themeName,
62
+ file,
63
+ }));
64
+ }
65
+ export function resolveThemeStyleFiles(cssOptions, packageRoot) {
66
+ const themeFiles = new Map();
67
+ for (const { themeName, file } of getThemeStyleEntries(cssOptions)) {
68
+ themeFiles.set(themeName, path.resolve(packageRoot, file));
69
+ }
70
+ return themeFiles;
71
+ }
72
+ export function createStyleFileKeySet(styleFiles) {
73
+ return new Set(Array.from(styleFiles, normalizeCssFileKey));
74
+ }
75
+ export function createStyleFileKey(styleFile) {
76
+ return normalizeCssFileKey(styleFile);
77
+ }
78
+ export function parsePackageStyleSpecifier(specifier) {
79
+ var _a, _b, _c;
80
+ if (specifier.startsWith('.')) return null;
81
+ const parts = specifier.split('/');
82
+ const packageName = specifier.startsWith('@')
83
+ ? `${(_a = parts.shift()) !== null && _a !== void 0 ? _a : ''}/${
84
+ (_b = parts.shift()) !== null && _b !== void 0 ? _b : ''
85
+ }`
86
+ : (_c = parts.shift()) !== null && _c !== void 0
87
+ ? _c
88
+ : '';
89
+ if (!packageName) return null;
90
+ return {
91
+ packageName,
92
+ stylePath: parts.join('/'),
93
+ };
94
+ }
95
+ export function joinDependencySpecifier(packageName, dependencyPath) {
96
+ if (!dependencyPath) return packageName;
97
+ return dependencyPath.startsWith('/')
98
+ ? `${packageName}${dependencyPath}`
99
+ : `${packageName}/${dependencyPath}`;
100
+ }
101
+ export function createImportCode(specifiers) {
102
+ return Array.from(new Set(specifiers))
103
+ .map((specifier) => `@import "${specifier}";`)
104
+ .join('\n');
105
+ }
106
+ export function removeCssExtension(cssPath) {
107
+ return cssPath.slice(0, -path.extname(cssPath).length);
108
+ }
@@ -0,0 +1,16 @@
1
+ import postcss, { type Root } from 'postcss';
2
+ import type { ModuleCssBuildConfig } from '#auklet/types';
3
+ import type { WorkspaceStyleResolver } from '#auklet/css/core/workspaceStyleResolver';
4
+ export declare class StyleProcessor {
5
+ private readonly config;
6
+ private readonly resolver;
7
+ constructor(config: ModuleCssBuildConfig, resolver: WorkspaceStyleResolver);
8
+ createRoot(): postcss.Root;
9
+ appendImportRule(root: Root, specifier: string): void;
10
+ stringify(root: Root): string;
11
+ appendStyleContent(target: Root, content: string, from: string): void;
12
+ readStyleFile(cssPath: string, seen?: Set<string>): string;
13
+ collectImportedStyleFiles(styleFiles: Array<string>): Set<string>;
14
+ private parse;
15
+ private parseImportSpecifier;
16
+ }
@@ -0,0 +1,123 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import postcss from 'postcss';
4
+ import {
5
+ IMPORT_AT_RULE,
6
+ LINE_SEPARATOR,
7
+ RELATIVE_IMPORT_PREFIX,
8
+ } from '#auklet/css/core/constants';
9
+ export class StyleProcessor {
10
+ constructor(config, resolver) {
11
+ this.config = config;
12
+ this.resolver = resolver;
13
+ }
14
+ createRoot() {
15
+ return postcss.root();
16
+ }
17
+ appendImportRule(root, specifier) {
18
+ var _a;
19
+ const rule = postcss.atRule({
20
+ name: IMPORT_AT_RULE,
21
+ params: `"${specifier}"`,
22
+ });
23
+ if ((_a = root.nodes) === null || _a === void 0 ? void 0 : _a.length)
24
+ rule.raws.before = LINE_SEPARATOR;
25
+ root.append(rule);
26
+ root.raws.semicolon = true;
27
+ }
28
+ stringify(root) {
29
+ root.raws.semicolon = true;
30
+ return `${root}${LINE_SEPARATOR}`;
31
+ }
32
+ appendStyleContent(target, content, from) {
33
+ var _a, _b, _c;
34
+ const root = this.parse(content, from);
35
+ if (
36
+ ((_a = target.nodes) === null || _a === void 0 ? void 0 : _a.length) &&
37
+ ((_b = root.nodes) === null || _b === void 0 ? void 0 : _b[0])
38
+ ) {
39
+ root.nodes[0].raws.before = LINE_SEPARATOR;
40
+ }
41
+ target.append(...((_c = root.nodes) !== null && _c !== void 0 ? _c : []));
42
+ }
43
+ readStyleFile(cssPath, seen = new Set()) {
44
+ var _a;
45
+ if (!fs.existsSync(cssPath)) {
46
+ return '';
47
+ }
48
+ const normalizedPath = path.resolve(cssPath);
49
+ if (seen.has(normalizedPath)) return '';
50
+ seen.add(normalizedPath);
51
+ const css = fs.readFileSync(cssPath, 'utf8');
52
+ const root = this.parse(css, cssPath);
53
+ const imports = [];
54
+ root.walkAtRules(IMPORT_AT_RULE, (rule) => {
55
+ const specifier = this.parseImportSpecifier(rule.params);
56
+ if (specifier) imports.push({ rule, specifier });
57
+ });
58
+ for (const { rule, specifier } of imports) {
59
+ const importedPath = this.resolver.resolveStyleDependency(
60
+ specifier,
61
+ path.dirname(cssPath),
62
+ );
63
+ if (!importedPath) continue;
64
+ const content = this.readStyleFile(importedPath, seen);
65
+ if (!content.trim()) {
66
+ rule.remove();
67
+ continue;
68
+ }
69
+ rule.replaceWith(
70
+ ...((_a = this.parse(content, importedPath).nodes) !== null &&
71
+ _a !== void 0
72
+ ? _a
73
+ : []),
74
+ );
75
+ }
76
+ return root.toString();
77
+ }
78
+ collectImportedStyleFiles(styleFiles) {
79
+ const imported = new Set();
80
+ for (const styleFile of styleFiles) {
81
+ const css = fs.readFileSync(styleFile, 'utf8');
82
+ const root = this.parse(css, styleFile);
83
+ root.walkAtRules(IMPORT_AT_RULE, (rule) => {
84
+ const specifier = this.parseImportSpecifier(rule.params);
85
+ if (
86
+ !(specifier === null || specifier === void 0
87
+ ? void 0
88
+ : specifier.startsWith(RELATIVE_IMPORT_PREFIX)) ||
89
+ !this.config.styleExtensions.includes(path.extname(specifier))
90
+ ) {
91
+ return;
92
+ }
93
+ imported.add(path.resolve(path.dirname(styleFile), specifier));
94
+ });
95
+ }
96
+ return imported;
97
+ }
98
+ parse(code, from) {
99
+ // Keep parsing behind one method so future style languages can transform
100
+ // to CSS before PostCSS reads the final stylesheet.
101
+ return postcss.parse(code, { from });
102
+ }
103
+ parseImportSpecifier(params) {
104
+ const value = params.trim();
105
+ const first = value[0];
106
+ if (first === '"' || first === "'") {
107
+ const end = value.indexOf(first, 1);
108
+ return end > 0 ? value.slice(1, end) : null;
109
+ }
110
+ if (!value.startsWith('url(')) {
111
+ return null;
112
+ }
113
+ const end = value.indexOf(')', 4);
114
+ if (end < 0) return null;
115
+ const url = value.slice(4, end).trim();
116
+ const quote = url[0];
117
+ if (quote === '"' || quote === "'") {
118
+ const quoteEnd = url.indexOf(quote, 1);
119
+ return quoteEnd > 0 ? url.slice(1, quoteEnd) : null;
120
+ }
121
+ return url || null;
122
+ }
123
+ }
@@ -0,0 +1,18 @@
1
+ import type {
2
+ ModuleCssBuildConfig,
3
+ ResolvedModuleCssBuildContext,
4
+ } from '#auklet/types';
5
+ export declare class WorkspaceStyleResolver {
6
+ private readonly config;
7
+ private readonly context;
8
+ private readonly require;
9
+ constructor(
10
+ config: ModuleCssBuildConfig,
11
+ context: ResolvedModuleCssBuildContext,
12
+ );
13
+ resolveStyleDependency(specifier: string, fromDir?: string): string;
14
+ toOutputStyleSpecifier(specifier: string, outRoot: string): string;
15
+ toExternalStyleSpecifier(specifier: string, outRoot: string): string;
16
+ private getStylePathOutputFormat;
17
+ private parsePackageStyleSpecifier;
18
+ }