@knighted/css 1.0.0-rc.0 → 1.0.0-rc.10

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 (51) hide show
  1. package/bin/generate-types.js +31 -0
  2. package/dist/cjs/css.cjs +107 -25
  3. package/dist/cjs/css.d.cts +10 -6
  4. package/dist/cjs/generateTypes.cjs +636 -0
  5. package/dist/cjs/generateTypes.d.cts +104 -0
  6. package/dist/cjs/loader.cjs +128 -56
  7. package/dist/cjs/loader.d.cts +5 -0
  8. package/dist/cjs/loaderInternals.cjs +108 -0
  9. package/dist/cjs/loaderInternals.d.cts +23 -0
  10. package/dist/cjs/moduleGraph.cjs +431 -0
  11. package/dist/cjs/moduleGraph.d.cts +15 -0
  12. package/dist/cjs/moduleInfo.cjs +62 -0
  13. package/dist/cjs/moduleInfo.d.cts +10 -0
  14. package/dist/cjs/sassInternals.cjs +135 -0
  15. package/dist/cjs/sassInternals.d.cts +25 -0
  16. package/dist/cjs/stableNamespace.cjs +12 -0
  17. package/dist/cjs/stableNamespace.d.cts +3 -0
  18. package/dist/cjs/stableSelectors.cjs +44 -0
  19. package/dist/cjs/stableSelectors.d.cts +13 -0
  20. package/dist/cjs/stableSelectorsLiteral.cjs +104 -0
  21. package/dist/cjs/stableSelectorsLiteral.d.cts +19 -0
  22. package/dist/cjs/types.cjs +2 -0
  23. package/dist/cjs/types.d.cts +4 -0
  24. package/dist/css.d.ts +10 -6
  25. package/dist/css.js +107 -26
  26. package/dist/generateTypes.d.ts +104 -0
  27. package/dist/generateTypes.js +628 -0
  28. package/dist/loader.d.ts +5 -0
  29. package/dist/loader.js +127 -55
  30. package/dist/loaderInternals.d.ts +23 -0
  31. package/dist/loaderInternals.js +96 -0
  32. package/dist/moduleGraph.d.ts +15 -0
  33. package/dist/moduleGraph.js +425 -0
  34. package/dist/moduleInfo.d.ts +10 -0
  35. package/dist/moduleInfo.js +55 -0
  36. package/dist/sassInternals.d.ts +25 -0
  37. package/dist/sassInternals.js +124 -0
  38. package/dist/stableNamespace.d.ts +3 -0
  39. package/dist/stableNamespace.js +8 -0
  40. package/dist/stableSelectors.d.ts +13 -0
  41. package/dist/stableSelectors.js +36 -0
  42. package/dist/stableSelectorsLiteral.d.ts +19 -0
  43. package/dist/stableSelectorsLiteral.js +98 -0
  44. package/dist/types.d.ts +4 -0
  45. package/dist/types.js +1 -0
  46. package/loader-queries.d.ts +61 -0
  47. package/package.json +58 -8
  48. package/stable/_index.scss +57 -0
  49. package/stable/stable.css +15 -0
  50. package/types-stub/index.d.ts +5 -0
  51. package/types.d.ts +4 -0
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'node:path'
4
+ import { fileURLToPath, pathToFileURL } from 'node:url'
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+ const distPath = path.resolve(__dirname, '../dist/generateTypes.js')
8
+
9
+ async function main() {
10
+ try {
11
+ const mod = await import(pathToFileURL(distPath).href)
12
+ const runner =
13
+ typeof mod.runGenerateTypesCli === 'function'
14
+ ? mod.runGenerateTypesCli
15
+ : typeof mod.default === 'function'
16
+ ? mod.default
17
+ : undefined
18
+ if (typeof runner !== 'function') {
19
+ console.error('[knighted-css] Unable to load generateTypes CLI entry point.')
20
+ process.exitCode = 1
21
+ return
22
+ }
23
+ await runner(process.argv.slice(2))
24
+ } catch (error) {
25
+ console.error('[knighted-css] Failed to run generateTypes CLI.')
26
+ console.error(error)
27
+ process.exitCode = 1
28
+ }
29
+ }
30
+
31
+ void main()
package/dist/cjs/css.cjs CHANGED
@@ -6,11 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DEFAULT_EXTENSIONS = void 0;
7
7
  exports.css = css;
8
8
  exports.cssWithMeta = cssWithMeta;
9
+ exports.compileVanillaModule = compileVanillaModule;
9
10
  const node_path_1 = __importDefault(require("node:path"));
10
11
  const node_fs_1 = require("node:fs");
11
- const dependency_tree_1 = __importDefault(require("dependency-tree"));
12
12
  const lightningcss_1 = require("lightningcss");
13
13
  const helpers_js_1 = require("./helpers.cjs");
14
+ const moduleGraph_js_1 = require("./moduleGraph.cjs");
15
+ const sassInternals_js_1 = require("./sassInternals.cjs");
14
16
  exports.DEFAULT_EXTENSIONS = ['.css', '.scss', '.sass', '.less', '.css.ts'];
15
17
  async function css(entry, options = {}) {
16
18
  const { css: output } = await cssWithMeta(entry, options);
@@ -20,11 +22,12 @@ async function cssWithMeta(entry, options = {}) {
20
22
  const cwd = options.cwd ? node_path_1.default.resolve(options.cwd) : process.cwd();
21
23
  const entryPath = await resolveEntry(entry, cwd, options.resolver);
22
24
  const extensions = (options.extensions ?? exports.DEFAULT_EXTENSIONS).map(ext => ext.toLowerCase());
23
- const files = collectStyleDependencies(entryPath, {
25
+ const files = await collectStyleDependencies(entryPath, {
24
26
  cwd,
25
27
  extensions,
26
28
  filter: options.filter,
27
- dependencyTreeOptions: options.dependencyTree,
29
+ graphOptions: options.moduleGraph,
30
+ resolver: options.resolver,
28
31
  });
29
32
  if (files.length === 0) {
30
33
  return { css: '', files: [] };
@@ -34,6 +37,7 @@ async function cssWithMeta(entry, options = {}) {
34
37
  const chunk = await compileStyleModule(file, {
35
38
  cwd,
36
39
  peerResolver: options.peerResolver,
40
+ resolver: options.resolver,
37
41
  });
38
42
  if (chunk) {
39
43
  chunks.push(chunk);
@@ -73,30 +77,33 @@ async function resolveEntry(entry, cwd, resolver) {
73
77
  }
74
78
  return node_path_1.default.resolve(cwd, entry);
75
79
  }
76
- function collectStyleDependencies(entryPath, { cwd, extensions, filter, dependencyTreeOptions, }) {
80
+ async function collectStyleDependencies(entryPath, { cwd, extensions, filter, graphOptions, resolver, }) {
77
81
  const seen = new Set();
78
82
  const order = [];
79
83
  const shouldInclude = typeof filter === 'function'
80
84
  ? filter
81
85
  : (filePath) => !filePath.includes('node_modules');
82
86
  const entryIsStyle = Boolean(matchExtension(entryPath, extensions));
83
- let treeList = [];
87
+ let discoveredStyles = [];
84
88
  if (!entryIsStyle) {
85
- const dependencyConfig = {
86
- ...dependencyTreeOptions,
87
- filename: entryPath,
88
- directory: cwd,
89
+ discoveredStyles = await (0, moduleGraph_js_1.collectStyleImports)(entryPath, {
90
+ cwd,
91
+ styleExtensions: extensions,
89
92
  filter: shouldInclude,
90
- };
91
- treeList = dependency_tree_1.default.toList(dependencyConfig);
93
+ resolver,
94
+ graphOptions,
95
+ });
92
96
  }
93
- const candidates = entryIsStyle ? [entryPath] : [entryPath, ...treeList];
97
+ const candidates = entryIsStyle ? [entryPath] : [entryPath, ...discoveredStyles];
94
98
  for (const candidate of candidates) {
95
99
  const match = matchExtension(candidate, extensions);
96
- if (!match || seen.has(candidate))
100
+ if (!match)
101
+ continue;
102
+ const resolvedCandidate = node_path_1.default.resolve(candidate);
103
+ if (seen.has(resolvedCandidate))
97
104
  continue;
98
- seen.add(candidate);
99
- order.push({ path: node_path_1.default.resolve(candidate), ext: match });
105
+ seen.add(resolvedCandidate);
106
+ order.push({ path: resolvedCandidate, ext: match });
100
107
  }
101
108
  return order;
102
109
  }
@@ -104,28 +111,79 @@ function matchExtension(filePath, extensions) {
104
111
  const lower = filePath.toLowerCase();
105
112
  return extensions.find(ext => lower.endsWith(ext));
106
113
  }
107
- async function compileStyleModule(file, { cwd, peerResolver }) {
114
+ async function compileStyleModule(file, { cwd, peerResolver, resolver, }) {
108
115
  switch (file.ext) {
109
116
  case '.css':
110
117
  return node_fs_1.promises.readFile(file.path, 'utf8');
111
118
  case '.scss':
112
119
  case '.sass':
113
- return compileSass(file.path, file.ext === '.sass', peerResolver);
120
+ return compileSass(file.path, file.ext === '.sass', {
121
+ cwd,
122
+ peerResolver,
123
+ resolver,
124
+ });
114
125
  case '.less':
115
126
  return compileLess(file.path, peerResolver);
116
127
  case '.css.ts':
117
- return compileVanillaExtract(file.path, cwd, peerResolver);
128
+ return (await compileVanillaModule(file.path, cwd, peerResolver)).css;
118
129
  default:
119
130
  return '';
120
131
  }
121
132
  }
122
- async function compileSass(filePath, indented, peerResolver) {
133
+ async function compileSass(filePath, indented, { cwd, peerResolver, resolver, }) {
123
134
  const sassModule = await optionalPeer('sass', 'Sass', peerResolver);
124
- const sass = sassModule;
125
- const result = sass.compile(filePath, {
126
- style: 'expanded',
135
+ const sass = resolveSassNamespace(sassModule);
136
+ const importer = (0, sassInternals_js_1.createSassImporter)({ cwd, resolver });
137
+ const loadPaths = buildSassLoadPaths(filePath);
138
+ if (typeof sass.compileAsync === 'function') {
139
+ const result = await sass.compileAsync(filePath, {
140
+ style: 'expanded',
141
+ loadPaths,
142
+ importers: importer ? [importer] : undefined,
143
+ });
144
+ return result.css;
145
+ }
146
+ if (typeof sass.render === 'function') {
147
+ return renderLegacySass(sass, filePath, indented, loadPaths);
148
+ }
149
+ throw new Error('@knighted/css: Installed "sass" package does not expose compileAsync or render APIs. Please update "sass" to a supported version.');
150
+ }
151
+ function renderLegacySass(sass, filePath, indented, loadPaths) {
152
+ return new Promise((resolve, reject) => {
153
+ sass.render({
154
+ file: filePath,
155
+ indentedSyntax: indented,
156
+ outputStyle: 'expanded',
157
+ includePaths: loadPaths,
158
+ }, (error, result) => {
159
+ if (error) {
160
+ reject(error);
161
+ return;
162
+ }
163
+ if (!result || typeof result.css === 'undefined') {
164
+ resolve('');
165
+ return;
166
+ }
167
+ resolve(result.css.toString());
168
+ });
127
169
  });
128
- return result.css;
170
+ }
171
+ // Ensure Sass can resolve bare module specifiers by walking node_modules folders.
172
+ function buildSassLoadPaths(filePath) {
173
+ const loadPaths = new Set();
174
+ let cursor = node_path_1.default.dirname(filePath);
175
+ const root = node_path_1.default.parse(cursor).root;
176
+ while (true) {
177
+ loadPaths.add(cursor);
178
+ loadPaths.add(node_path_1.default.join(cursor, 'node_modules'));
179
+ if (cursor === root)
180
+ break;
181
+ cursor = node_path_1.default.dirname(cursor);
182
+ }
183
+ const cwd = process.cwd();
184
+ loadPaths.add(cwd);
185
+ loadPaths.add(node_path_1.default.join(cwd, 'node_modules'));
186
+ return Array.from(loadPaths).filter(dir => dir && (0, node_fs_1.existsSync)(dir));
129
187
  }
130
188
  async function compileLess(filePath, peerResolver) {
131
189
  const mod = await optionalPeer('less', 'Less', peerResolver);
@@ -134,7 +192,7 @@ async function compileLess(filePath, peerResolver) {
134
192
  const result = await less.render(source, { filename: filePath });
135
193
  return result.css;
136
194
  }
137
- async function compileVanillaExtract(filePath, cwd, peerResolver) {
195
+ async function compileVanillaModule(filePath, cwd, peerResolver) {
138
196
  const mod = await optionalPeer('@vanilla-extract/integration', 'Vanilla Extract', peerResolver);
139
197
  const namespace = unwrapModuleNamespace(mod);
140
198
  const compileFn = namespace.compile;
@@ -174,7 +232,10 @@ async function compileVanillaExtract(filePath, cwd, peerResolver) {
174
232
  imports.push(virtualFile.source);
175
233
  }
176
234
  }
177
- return imports.join('\n');
235
+ return {
236
+ source,
237
+ css: imports.join('\n'),
238
+ };
178
239
  }
179
240
  const defaultPeerLoader = name => import(name);
180
241
  async function optionalPeer(name, label, loader) {
@@ -193,6 +254,27 @@ async function optionalPeer(name, label, loader) {
193
254
  throw error;
194
255
  }
195
256
  }
257
+ function resolveSassNamespace(mod) {
258
+ if (isSassNamespace(mod)) {
259
+ return mod;
260
+ }
261
+ if (typeof mod === 'object' &&
262
+ mod !== null &&
263
+ 'default' in mod) {
264
+ const candidate = mod.default;
265
+ if (isSassNamespace(candidate)) {
266
+ return candidate;
267
+ }
268
+ }
269
+ return mod;
270
+ }
271
+ function isSassNamespace(candidate) {
272
+ if (typeof candidate !== 'object' || !candidate) {
273
+ return false;
274
+ }
275
+ const namespace = candidate;
276
+ return typeof namespace.compile === 'function' || typeof namespace.render === 'function';
277
+ }
196
278
  function unwrapModuleNamespace(mod) {
197
279
  if (typeof mod === 'object' &&
198
280
  mod !== null &&
@@ -1,11 +1,11 @@
1
- import type { Options as DependencyTreeOpts } from 'dependency-tree';
2
1
  import { type TransformOptions as LightningTransformOptions } from 'lightningcss';
3
2
  import { type SpecificitySelector, type SpecificityStrategy } from './helpers.cjs';
3
+ import type { ModuleGraphOptions } from './moduleGraph.cjs';
4
+ import type { CssResolver } from './types.cjs';
5
+ export type { CssResolver } from './types.cjs';
6
+ export type { ModuleGraphOptions } from './moduleGraph.cjs';
4
7
  export declare const DEFAULT_EXTENSIONS: string[];
5
8
  type LightningCssConfig = boolean | Partial<Omit<LightningTransformOptions<never>, 'code'>>;
6
- export type CssResolver = (specifier: string, ctx: {
7
- cwd: string;
8
- }) => string | Promise<string | undefined>;
9
9
  type PeerLoader = (name: string) => Promise<unknown>;
10
10
  export interface CssOptions {
11
11
  extensions?: string[];
@@ -17,10 +17,14 @@ export interface CssOptions {
17
17
  strategy?: SpecificityStrategy;
18
18
  match?: SpecificitySelector[];
19
19
  };
20
- dependencyTree?: Partial<Omit<DependencyTreeOpts, 'filename' | 'directory'>>;
20
+ moduleGraph?: ModuleGraphOptions;
21
21
  resolver?: CssResolver;
22
22
  peerResolver?: PeerLoader;
23
23
  }
24
+ export interface VanillaCompileResult {
25
+ source: string;
26
+ css: string;
27
+ }
24
28
  /**
25
29
  * Extract and compile all CSS-like dependencies for a given module.
26
30
  */
@@ -30,4 +34,4 @@ export interface CssResult {
30
34
  }
31
35
  export declare function css(entry: string, options?: CssOptions): Promise<string>;
32
36
  export declare function cssWithMeta(entry: string, options?: CssOptions): Promise<CssResult>;
33
- export {};
37
+ export declare function compileVanillaModule(filePath: string, cwd: string, peerResolver?: PeerLoader): Promise<VanillaCompileResult>;