knip 6.22.0 → 6.24.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 (69) hide show
  1. package/LICENSE +1 -1
  2. package/dist/ConfigurationChief.d.ts +6 -0
  3. package/dist/ProjectPrincipal.js +3 -5
  4. package/dist/WorkspaceWorker.d.ts +3 -1
  5. package/dist/WorkspaceWorker.js +5 -2
  6. package/dist/binaries/resolvers/index.d.ts +2 -0
  7. package/dist/binaries/resolvers/index.js +3 -0
  8. package/dist/binaries/resolvers/nub.d.ts +2 -0
  9. package/dist/binaries/resolvers/nub.js +46 -0
  10. package/dist/binaries/resolvers/yarn.js +4 -3
  11. package/dist/compilers/compilers.d.ts +2 -0
  12. package/dist/compilers/compilers.js +15 -4
  13. package/dist/compilers/index.d.ts +11 -1
  14. package/dist/compilers/index.js +25 -10
  15. package/dist/compilers/less.d.ts +7 -0
  16. package/dist/compilers/less.js +37 -0
  17. package/dist/compilers/mdx.d.ts +1 -2
  18. package/dist/compilers/mdx.js +14 -8
  19. package/dist/compilers/scss.d.ts +3 -2
  20. package/dist/compilers/scss.js +17 -14
  21. package/dist/compilers/shared.d.ts +6 -0
  22. package/dist/compilers/shared.js +9 -0
  23. package/dist/compilers/style-preprocessors.d.ts +2 -0
  24. package/dist/compilers/style-preprocessors.js +41 -0
  25. package/dist/compilers/stylus.d.ts +7 -0
  26. package/dist/compilers/stylus.js +36 -0
  27. package/dist/constants.js +4 -0
  28. package/dist/graph/build.js +14 -1
  29. package/dist/plugins/astro/compiler-mdx.js +11 -2
  30. package/dist/plugins/astro/compiler.js +8 -4
  31. package/dist/plugins/astro-markdoc/index.d.ts +3 -0
  32. package/dist/plugins/astro-markdoc/index.js +34 -0
  33. package/dist/plugins/astro-markdoc/types.d.ts +12 -0
  34. package/dist/plugins/astro-markdoc/types.js +1 -0
  35. package/dist/plugins/github-actions/index.js +3 -2
  36. package/dist/plugins/index.d.ts +1 -0
  37. package/dist/plugins/index.js +2 -0
  38. package/dist/plugins/node/index.js +1 -1
  39. package/dist/plugins/nuxt/index.js +4 -2
  40. package/dist/plugins/prisma/compiler.js +3 -0
  41. package/dist/plugins/starlight/index.js +14 -1
  42. package/dist/plugins/stencil/index.js +59 -1
  43. package/dist/plugins/svelte/compiler.d.ts +2 -1
  44. package/dist/plugins/svelte/compiler.js +8 -1
  45. package/dist/plugins/tailwind/compiler.js +3 -0
  46. package/dist/plugins/tailwind/index.js +5 -1
  47. package/dist/plugins/vite/index.js +1 -1
  48. package/dist/plugins/vitest/index.js +3 -3
  49. package/dist/plugins/vue/compiler.d.ts +2 -1
  50. package/dist/plugins/vue/compiler.js +8 -1
  51. package/dist/reporters/compact.js +1 -2
  52. package/dist/reporters/symbols.js +1 -2
  53. package/dist/schema/configuration.d.ts +15 -0
  54. package/dist/schema/plugins.d.ts +5 -0
  55. package/dist/schema/plugins.js +1 -0
  56. package/dist/types/PluginNames.d.ts +2 -2
  57. package/dist/types/PluginNames.js +1 -0
  58. package/dist/types/config.d.ts +1 -0
  59. package/dist/types.d.ts +1 -1
  60. package/dist/typescript/SourceFileManager.js +3 -2
  61. package/dist/typescript/ast-nodes.d.ts +1 -0
  62. package/dist/typescript/ast-nodes.js +51 -1
  63. package/dist/typescript/comments.js +22 -3
  64. package/dist/typescript/visitors/walk.js +7 -1
  65. package/dist/util/create-options.d.ts +10 -0
  66. package/dist/version.d.ts +1 -1
  67. package/dist/version.js +1 -1
  68. package/package.json +1 -1
  69. package/schema.json +4 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  ISC License (ISC)
2
2
 
3
- Copyright 2022-2025 Lars Kappert
3
+ Copyright 2022-2026 Lars Kappert
4
4
 
5
5
  Permission to use, copy, modify, and/or distribute this software for any purpose
6
6
  with or without fee is hereby granted, provided that the above copyright notice
@@ -72,6 +72,11 @@ export declare class ConfigurationChief {
72
72
  entry?: string | string[] | undefined;
73
73
  project?: string | string[] | undefined;
74
74
  } | undefined;
75
+ 'astro-markdoc'?: string | boolean | string[] | {
76
+ config?: string | string[] | undefined;
77
+ entry?: string | string[] | undefined;
78
+ project?: string | string[] | undefined;
79
+ } | undefined;
75
80
  'astro-og-canvas'?: string | boolean | string[] | {
76
81
  config?: string | string[] | undefined;
77
82
  entry?: string | string[] | undefined;
@@ -867,6 +872,7 @@ export declare class ConfigurationChief {
867
872
  angular?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
868
873
  astro?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
869
874
  "astro-db"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
875
+ "astro-markdoc"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
870
876
  "astro-og-canvas"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
871
877
  ava?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
872
878
  babel?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -130,11 +130,9 @@ export class ProjectPrincipal {
130
130
  }
131
131
  async runAsyncCompilers() {
132
132
  const add = timerify(this.fileManager.compileAndAddSourceFile.bind(this.fileManager));
133
- const extensions = Array.from(this.asyncCompilers.keys());
134
- const files = Array.from(this.projectPaths).filter(filePath => extensions.includes(extname(filePath)));
135
- for (const filePath of files) {
136
- await add(filePath);
137
- }
133
+ for (const filePath of this.projectPaths)
134
+ if (this.asyncCompilers.has(extname(filePath)))
135
+ await add(filePath);
138
136
  }
139
137
  walkAndAnalyze(analyzeFile) {
140
138
  this.resolvedFiles.clear();
@@ -17,6 +17,7 @@ type WorkspaceManagerOptions = {
17
17
  rootManifest: Manifest | undefined;
18
18
  handleInput: HandleInput;
19
19
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
20
+ getManifest: (dir: string) => Manifest | undefined;
20
21
  readFile: (filePath: string) => string;
21
22
  negatedWorkspacePatterns: string[];
22
23
  ignoredWorkspacePatterns: string[];
@@ -38,6 +39,7 @@ export declare class WorkspaceWorker {
38
39
  dependencies: DependencySet;
39
40
  handleInput: HandleInput;
40
41
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
42
+ getManifest: (dir: string) => Manifest | undefined;
41
43
  readFile: (filePath: string) => string;
42
44
  negatedWorkspacePatterns: string[];
43
45
  ignoredWorkspacePatterns: string[];
@@ -47,7 +49,7 @@ export declare class WorkspaceWorker {
47
49
  enabledPluginsInAncestors: string[];
48
50
  cache: CacheConsultant<CacheItem>;
49
51
  configFilesMap: Map<string, Map<PluginName, Set<string>>>;
50
- constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, readFile, configFilesMap, options, }: WorkspaceManagerOptions);
52
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readFile, configFilesMap, options, }: WorkspaceManagerOptions);
51
53
  init(): Promise<void>;
52
54
  private determineEnabledPlugins;
53
55
  private getConfigForPlugin;
@@ -32,6 +32,7 @@ export class WorkspaceWorker {
32
32
  dependencies;
33
33
  handleInput;
34
34
  findWorkspaceByFilePath;
35
+ getManifest;
35
36
  readFile;
36
37
  negatedWorkspacePatterns = [];
37
38
  ignoredWorkspacePatterns = [];
@@ -41,7 +42,7 @@ export class WorkspaceWorker {
41
42
  enabledPluginsInAncestors;
42
43
  cache;
43
44
  configFilesMap;
44
- constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, readFile, configFilesMap, options, }) {
45
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readFile, configFilesMap, options, }) {
45
46
  this.name = name;
46
47
  this.dir = dir;
47
48
  this.config = config;
@@ -54,6 +55,7 @@ export class WorkspaceWorker {
54
55
  this.configFilesMap = configFilesMap;
55
56
  this.handleInput = handleInput;
56
57
  this.findWorkspaceByFilePath = findWorkspaceByFilePath;
58
+ this.getManifest = getManifest;
57
59
  this.readFile = readFile;
58
60
  this.options = options;
59
61
  this.cache = new CacheConsultant(`plugins-${name}`, options);
@@ -211,7 +213,8 @@ export class WorkspaceWorker {
211
213
  const isProduction = this.options.isProduction;
212
214
  const knownBinsOnly = false;
213
215
  const rootManifest = this.rootManifest;
214
- const baseOptions = { manifest, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly };
216
+ const getManifest = this.getManifest;
217
+ const baseOptions = { manifest, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly, getManifest };
215
218
  const baseScriptOptions = { ...baseOptions, isProduction, enabledPlugins: this.enabledPlugins };
216
219
  const [productionScripts, developmentScripts] = getFilteredScripts(manifest.scripts ?? {});
217
220
  const inputsFromManifest = _getInputsFromScripts(Object.values(developmentScripts), baseOptions);
@@ -1,6 +1,8 @@
1
1
  declare const _default: {
2
2
  bun: import("../../types/config.ts").BinaryResolver;
3
3
  bunx: import("../../types/config.ts").BinaryResolver;
4
+ nub: import("../../types/config.ts").BinaryResolver;
5
+ nubx: import("../../types/config.ts").BinaryResolver;
4
6
  find: import("../../types/config.ts").BinaryResolver;
5
7
  npm: import("../../types/config.ts").BinaryResolver;
6
8
  npx: import("../../types/config.ts").BinaryResolver;
@@ -3,12 +3,15 @@ import * as bunx from './bunx.js';
3
3
  import * as find from './find.js';
4
4
  import * as npm from './npm.js';
5
5
  import * as npx from './npx.js';
6
+ import * as nub from './nub.js';
6
7
  import * as pnpm from './pnpm.js';
7
8
  import * as pnpx from './pnpx.js';
8
9
  import * as yarn from './yarn.js';
9
10
  export default {
10
11
  bun: bun.resolve,
11
12
  bunx: bunx.resolve,
13
+ nub: nub.resolve,
14
+ nubx: bunx.resolve,
12
15
  find: find.resolve,
13
16
  npm: npm.resolve,
14
17
  npx: npx.resolve,
@@ -0,0 +1,2 @@
1
+ import type { BinaryResolver } from '../../types/config.ts';
2
+ export declare const resolve: BinaryResolver;
@@ -0,0 +1,46 @@
1
+ import parseArgs from '../../util/parse-args.js';
2
+ import { toBinary, toEntry } from '../../util/input.js';
3
+ import { isAbsolute, join } from '../../util/path.js';
4
+ import { _resolveSync } from '../../util/resolve.js';
5
+ import { resolveX } from './bunx.js';
6
+ const runtimes = new Set(['x', 'dlx', 'exec']);
7
+ const runners = new Set(['run', 'watch']);
8
+ const commands = new Set([
9
+ 'add',
10
+ 'approve-builds',
11
+ 'audit',
12
+ 'ci',
13
+ 'create',
14
+ 'init',
15
+ 'install',
16
+ 'link',
17
+ 'node',
18
+ 'outdated',
19
+ 'pm',
20
+ 'publish',
21
+ 'remove',
22
+ 'unlink',
23
+ 'update',
24
+ 'why',
25
+ ]);
26
+ export const resolve = (_binary, args, options) => {
27
+ const binary = toBinary(_binary);
28
+ const { manifest, cwd, fromArgs } = options;
29
+ const parsed = parseArgs(args, { string: ['filter'], boolean: ['recursive'], alias: { recursive: 'r' } });
30
+ const [command, script] = parsed._;
31
+ if (runtimes.has(command)) {
32
+ const rest = args.filter(arg => arg !== command);
33
+ return [binary, ...resolveX(rest, options)];
34
+ }
35
+ if (parsed.recursive || parsed.filter)
36
+ return [binary];
37
+ if (runners.has(command)) {
38
+ if (!script || manifest.scriptNames.has(script))
39
+ return [binary];
40
+ const resolved = _resolveSync(isAbsolute(script) ? script : join(cwd, script), cwd);
41
+ return resolved ? [binary, toEntry(resolved)] : [binary];
42
+ }
43
+ if (command && (commands.has(command) || manifest.scriptNames.has(command)))
44
+ return [binary];
45
+ return [binary, ...fromArgs(['node', ...args])];
46
+ };
@@ -49,15 +49,16 @@ const resolveDlx = (args, options) => {
49
49
  return [...packages.map(id => toDependency(id)), ...command].map(id => isDependency(id) || isBinary(id) ? Object.assign(id, { optional: true }) : id);
50
50
  };
51
51
  export const resolve = (_binary, args, options) => {
52
- const { manifest, fromArgs, cwd, rootCwd } = options;
52
+ const { manifest, fromArgs, cwd, rootCwd, getManifest } = options;
53
53
  const parsed = parseArgs(args, { boolean: ['top-level'], string: ['cwd'], '--': true });
54
54
  const dir = parsed['top-level'] ? rootCwd : parsed.cwd ? join(cwd, parsed.cwd) : undefined;
55
55
  const [command, binary] = parsed._;
56
56
  if (!command && !binary)
57
57
  return [];
58
+ const dirManifest = (dir && getManifest(dir)) || manifest;
58
59
  const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--'], { knownBinsOnly: true }) : [];
59
60
  if (command === 'run') {
60
- if (manifest.scriptNames.has(binary))
61
+ if (dirManifest.scriptNames.has(binary))
61
62
  return _childArgs;
62
63
  const bin = toBinary(binary, { optional: true });
63
64
  if (dir)
@@ -70,7 +71,7 @@ export const resolve = (_binary, args, options) => {
70
71
  const argsForDlx = args.filter(arg => arg !== 'dlx');
71
72
  return resolveDlx(argsForDlx, options);
72
73
  }
73
- if ((!dir && manifest.scriptNames.has(command)) || commands.includes(command))
74
+ if (dirManifest.scriptNames.has(command) || commands.includes(command))
74
75
  return _childArgs;
75
76
  const opts = dir ? { cwd: dir } : {};
76
77
  return fromArgs(argsFrom(args, command === 'exec' ? binary : command), opts);
@@ -2,10 +2,12 @@ import type { CompilerSync } from './types.ts';
2
2
  export declare const fencedCodeBlockMatcher: RegExp;
3
3
  export declare const inlineCodeMatcher: RegExp;
4
4
  export declare const scriptExtractor: RegExp;
5
+ export declare const styleExtractor: RegExp;
5
6
  export declare const blockCommentMatcher: RegExp;
6
7
  export declare const lineCommentMatcher: RegExp;
7
8
  export declare const importMatcher: RegExp;
8
9
  export declare const importsWithinScripts: CompilerSync;
9
10
  export declare const scriptBodies: CompilerSync;
11
+ export declare const getStyleLang: (attrs: string) => string | undefined;
10
12
  export declare const frontmatterMatcher: RegExp;
11
13
  export declare const importsWithinFrontmatter: (text: string, keys?: string[]) => string;
@@ -1,26 +1,37 @@
1
1
  export const fencedCodeBlockMatcher = /```[\s\S]*?```/g;
2
2
  export const inlineCodeMatcher = /`[^`]+`/g;
3
3
  export const scriptExtractor = /<script\b((?:[^>"']|"[^"]*"|'[^']*')*)>([\s\S]*?)<\/script>/gi;
4
+ export const styleExtractor = /<style\b((?:[^>"']|"[^"]*"|'[^']*')*)>([\s\S]*?)<\/style>/gi;
5
+ const langAttrMatcher = /\blang\s*=\s*["']([^"']+)["']/i;
4
6
  export const blockCommentMatcher = /\/\*[\s\S]*?\*\//g;
5
7
  export const lineCommentMatcher = /^[ \t]*\/\/.*$/gm;
6
8
  export const importMatcher = /import(?:\s*\(\s*['"][^'"]+['"][^)]*\)|(?!\s*\()[^'"]+['"][^'"]+['"])/g;
7
9
  export const importsWithinScripts = (text) => {
8
10
  const scripts = [];
9
- for (const [, , scriptBody] of text.matchAll(scriptExtractor)) {
11
+ scriptExtractor.lastIndex = 0;
12
+ let scriptMatch;
13
+ while ((scriptMatch = scriptExtractor.exec(text))) {
14
+ const scriptBody = scriptMatch[2];
10
15
  const body = scriptBody.replace(blockCommentMatcher, '').replace(lineCommentMatcher, '');
11
- for (const importMatch of body.matchAll(importMatcher))
12
- scripts.push(importMatch);
16
+ let importMatch;
17
+ importMatcher.lastIndex = 0;
18
+ while ((importMatch = importMatcher.exec(body)))
19
+ scripts.push(importMatch[0]);
13
20
  }
14
21
  return scripts.join(';\n');
15
22
  };
16
23
  export const scriptBodies = (text) => {
17
24
  const scripts = [];
18
- for (const [, , body] of text.matchAll(scriptExtractor)) {
25
+ scriptExtractor.lastIndex = 0;
26
+ let match;
27
+ while ((match = scriptExtractor.exec(text))) {
28
+ const body = match[2];
19
29
  if (body)
20
30
  scripts.push(body);
21
31
  }
22
32
  return scripts.join(';\n');
23
33
  };
34
+ export const getStyleLang = (attrs) => attrs.match(langAttrMatcher)?.[1]?.toLowerCase();
24
35
  export const frontmatterMatcher = /^---\r?\n([\s\S]*?)\r?\n---/;
25
36
  export const importsWithinFrontmatter = (text, keys = []) => {
26
37
  const frontmatter = text.match(frontmatterMatcher)?.[1];
@@ -18,6 +18,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
18
18
  entry?: string | string[] | undefined;
19
19
  project?: string | string[] | undefined;
20
20
  } | undefined;
21
+ 'astro-markdoc'?: string | boolean | string[] | {
22
+ config?: string | string[] | undefined;
23
+ entry?: string | string[] | undefined;
24
+ project?: string | string[] | undefined;
25
+ } | undefined;
21
26
  'astro-og-canvas'?: string | boolean | string[] | {
22
27
  config?: string | string[] | undefined;
23
28
  entry?: string | string[] | undefined;
@@ -820,6 +825,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
820
825
  entry?: string | string[] | undefined;
821
826
  project?: string | string[] | undefined;
822
827
  } | undefined;
828
+ 'astro-markdoc'?: string | boolean | string[] | {
829
+ config?: string | string[] | undefined;
830
+ entry?: string | string[] | undefined;
831
+ project?: string | string[] | undefined;
832
+ } | undefined;
823
833
  'astro-og-canvas'?: string | boolean | string[] | {
824
834
  config?: string | string[] | undefined;
825
835
  entry?: string | string[] | undefined;
@@ -1601,5 +1611,5 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
1601
1611
  syncCompilers: Record<string, true | CompilerSync>;
1602
1612
  asyncCompilers: Record<string, CompilerAsync>;
1603
1613
  };
1604
- export declare const getIncludedCompilers: (syncCompilers: RawSyncCompilers, asyncCompilers: AsyncCompilers, dependencies: DependencySet) => Compilers;
1614
+ export declare const getIncludedCompilers: (syncCompilers: RawSyncCompilers, asyncCompilers: AsyncCompilers, dependencies: DependencySet, onReferencedDependency?: (packageName: string) => void) => Compilers;
1605
1615
  export declare const getCompilerExtensions: (compilers: [SyncCompilers, AsyncCompilers]) => string[];
@@ -1,5 +1,7 @@
1
+ import LESS from './less.js';
1
2
  import MDX from './mdx.js';
2
3
  import SCSS from './scss.js';
4
+ import STYLUS from './stylus.js';
3
5
  const isAsyncCompiler = (fn) => (fn ? fn.constructor.name === 'AsyncFunction' : false);
4
6
  export const normalizeCompilerExtension = (ext) => ext.replace(/^\.*/, '.');
5
7
  export const partitionCompilers = (rawLocalConfig) => {
@@ -26,16 +28,29 @@ export const partitionCompilers = (rawLocalConfig) => {
26
28
  }
27
29
  return { ...rawLocalConfig, syncCompilers, asyncCompilers };
28
30
  };
29
- const compilers = new Map([
30
- ['.mdx', MDX],
31
- ['.sass', SCSS],
32
- ['.scss', SCSS],
33
- ]);
34
- export const getIncludedCompilers = (syncCompilers, asyncCompilers, dependencies) => {
35
- const hasDependency = (packageName) => dependencies.has(packageName);
36
- for (const [extension, { condition, compiler }] of compilers) {
37
- if ((!syncCompilers.has(extension) && condition(hasDependency)) || syncCompilers.get(extension) === true) {
38
- syncCompilers.set(extension, compiler);
31
+ const compilers = [
32
+ { extensions: ['.mdx'], ...MDX },
33
+ { extensions: ['.sass', '.scss'], ...SCSS },
34
+ { extensions: ['.less'], ...LESS },
35
+ { extensions: ['.styl', '.stylus'], ...STYLUS },
36
+ ];
37
+ export const getIncludedCompilers = (syncCompilers, asyncCompilers, dependencies, onReferencedDependency) => {
38
+ for (const { extensions, dependencies: compilerDependencies, compiler } of compilers) {
39
+ let hasCompilerDependency = false;
40
+ for (const dependency of compilerDependencies) {
41
+ if (dependencies.has(dependency)) {
42
+ hasCompilerDependency = true;
43
+ if (onReferencedDependency)
44
+ onReferencedDependency(dependency);
45
+ else
46
+ break;
47
+ }
48
+ }
49
+ for (const extension of extensions) {
50
+ const existingCompiler = syncCompilers.get(extension);
51
+ if (existingCompiler === true || (existingCompiler === undefined && hasCompilerDependency)) {
52
+ syncCompilers.set(extension, compiler);
53
+ }
39
54
  }
40
55
  }
41
56
  return [syncCompilers, asyncCompilers];
@@ -0,0 +1,7 @@
1
+ import type { CompilerSync } from './types.ts';
2
+ export declare const compiler: CompilerSync;
3
+ declare const _default: {
4
+ dependencies: string[];
5
+ compiler: CompilerSync;
6
+ };
7
+ export default _default;
@@ -0,0 +1,37 @@
1
+ import { isScopedPackage, isTildePackage, splitSpec } from './shared.js';
2
+ const dependencies = ['less'];
3
+ const importMatcher = /@import\s+(?:\([^)]*\)\s+)?(?:url\(\s*['"]?([^'")\s]+)['"]?\s*\)|['"]([^'"]+)['"])/g;
4
+ const isExternalUrl = (s) => s.startsWith('//') || s.startsWith('http://') || s.startsWith('https://');
5
+ const candidates = (specifier) => {
6
+ const { dir, name } = splitSpec(specifier);
7
+ if (name.endsWith('.less') || name.endsWith('.css'))
8
+ return [`${dir}/${name}`];
9
+ return [`${dir}/${name}.less`];
10
+ };
11
+ export const compiler = text => {
12
+ if (!text.includes('@import'))
13
+ return '';
14
+ const out = [];
15
+ let i = 0;
16
+ let match;
17
+ importMatcher.lastIndex = 0;
18
+ while ((match = importMatcher.exec(text))) {
19
+ let spec = match[1] ?? match[2];
20
+ if (!spec || isExternalUrl(spec))
21
+ continue;
22
+ let isBare = isScopedPackage(spec);
23
+ if (isTildePackage(spec)) {
24
+ spec = spec.slice(1);
25
+ isBare = true;
26
+ }
27
+ if (isBare) {
28
+ out.push(`import _$${i++} from '${spec}';`);
29
+ }
30
+ else {
31
+ for (const s of candidates(spec))
32
+ out.push(`import _$${i++} from '${s}';`);
33
+ }
34
+ }
35
+ return out.join('\n');
36
+ };
37
+ export default { dependencies, compiler };
@@ -1,6 +1,5 @@
1
- import type { HasDependency } from './types.ts';
2
1
  declare const _default: {
3
- condition: (hasDependency: HasDependency) => boolean;
2
+ dependencies: string[];
4
3
  compiler: (text: string) => string;
5
4
  };
6
5
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import { fencedCodeBlockMatcher, frontmatterMatcher, inlineCodeMatcher } from './compilers.js';
2
- const mdxDependencies = [
2
+ const dependencies = [
3
3
  '@mdx-js/esbuild',
4
4
  '@mdx-js/loader',
5
5
  '@mdx-js/mdx',
@@ -10,13 +10,19 @@ const mdxDependencies = [
10
10
  '@mdx-js/vue',
11
11
  'remark-mdx',
12
12
  ];
13
- const condition = (hasDependency) => mdxDependencies.some(hasDependency);
14
13
  const mdxImportMatcher = /^import[^'"]+['"][^'"]+['"]/gm;
15
- const compiler = (text) => [
16
- ...text
14
+ const compiler = (text) => {
15
+ if (!text.includes('import'))
16
+ return '';
17
+ const imports = [];
18
+ const source = text
17
19
  .replace(frontmatterMatcher, '')
18
20
  .replace(fencedCodeBlockMatcher, '')
19
- .replace(inlineCodeMatcher, '')
20
- .matchAll(mdxImportMatcher),
21
- ].join('\n');
22
- export default { condition, compiler };
21
+ .replace(inlineCodeMatcher, '');
22
+ let match;
23
+ mdxImportMatcher.lastIndex = 0;
24
+ while ((match = mdxImportMatcher.exec(source)))
25
+ imports.push(match[0]);
26
+ return imports.join('\n');
27
+ };
28
+ export default { dependencies, compiler };
@@ -1,6 +1,7 @@
1
- import type { CompilerSync, HasDependency } from './types.ts';
1
+ import type { CompilerSync } from './types.ts';
2
+ export declare const compiler: CompilerSync;
2
3
  declare const _default: {
3
- condition: (hasDependency: HasDependency) => boolean;
4
+ dependencies: string[];
4
5
  compiler: CompilerSync;
5
6
  };
6
7
  export default _default;
@@ -1,13 +1,8 @@
1
- import { basename, dirname } from '../util/path.js';
2
- const condition = (hasDependency) => hasDependency('sass') || hasDependency('sass-embedded') || hasDependency('node-sass');
1
+ import { isScopedPackage, isTildePackage, splitSpec } from './shared.js';
2
+ const dependencies = ['sass', 'sass-embedded', 'node-sass'];
3
3
  const importMatcher = /@(?:use|import|forward)\s+['"](pkg:)?([^'"]+)['"]/g;
4
- const isAlias = (s) => (s.charCodeAt(0) === 64 && s.charCodeAt(1) === 47) || s.charCodeAt(0) === 126 || s.charCodeAt(0) === 35;
5
- const isScopedPackage = (s) => s.charCodeAt(0) === 64 && s.charCodeAt(1) !== 47;
6
- const isTildePackage = (s) => s.charCodeAt(0) === 126 && s.charCodeAt(1) !== 47;
7
4
  const candidates = (specifier) => {
8
- const spec = specifier.startsWith('.') || isAlias(specifier) ? specifier : `./${specifier}`;
9
- const name = basename(spec);
10
- const dir = dirname(spec);
5
+ const { dir, name } = splitSpec(specifier);
11
6
  const hasExt = name.endsWith('.scss') || name.endsWith('.sass');
12
7
  const bases = hasExt ? [name] : [`${name}.scss`, `${name}.sass`];
13
8
  const out = [];
@@ -18,10 +13,14 @@ const candidates = (specifier) => {
18
13
  }
19
14
  return out;
20
15
  };
21
- const compiler = text => {
16
+ export const compiler = text => {
17
+ if (!text.includes('@use') && !text.includes('@import') && !text.includes('@forward'))
18
+ return '';
22
19
  const out = [];
23
20
  let i = 0;
24
- for (const match of text.matchAll(importMatcher)) {
21
+ let match;
22
+ importMatcher.lastIndex = 0;
23
+ while ((match = importMatcher.exec(text))) {
25
24
  let spec = match[2];
26
25
  if (!spec || spec.startsWith('sass:'))
27
26
  continue;
@@ -30,10 +29,14 @@ const compiler = text => {
30
29
  spec = spec.slice(1);
31
30
  isBare = true;
32
31
  }
33
- const specs = isBare ? [spec] : candidates(spec);
34
- for (const s of specs)
35
- out.push(`import _$${i++} from '${s}';`);
32
+ if (isBare) {
33
+ out.push(`import _$${i++} from '${spec}';`);
34
+ }
35
+ else {
36
+ for (const s of candidates(spec))
37
+ out.push(`import _$${i++} from '${s}';`);
38
+ }
36
39
  }
37
40
  return out.join('\n');
38
41
  };
39
- export default { condition, compiler };
42
+ export default { dependencies, compiler };
@@ -0,0 +1,6 @@
1
+ export declare const isScopedPackage: (s: string) => boolean;
2
+ export declare const isTildePackage: (s: string) => boolean;
3
+ export declare const splitSpec: (specifier: string) => {
4
+ dir: string;
5
+ name: string;
6
+ };
@@ -0,0 +1,9 @@
1
+ import { basename, dirname } from '../util/path.js';
2
+ const isAlias = (s) => (s.charCodeAt(0) === 64 && s.charCodeAt(1) === 47) || s.charCodeAt(0) === 126 || s.charCodeAt(0) === 35;
3
+ export const isScopedPackage = (s) => s.charCodeAt(0) === 64 && s.charCodeAt(1) !== 47;
4
+ export const isTildePackage = (s) => s.charCodeAt(0) === 126 && s.charCodeAt(1) !== 47;
5
+ const ensureRelative = (spec) => (spec.startsWith('.') || isAlias(spec) ? spec : `./${spec}`);
6
+ export const splitSpec = (specifier) => {
7
+ const spec = ensureRelative(specifier);
8
+ return { dir: dirname(spec), name: basename(spec) };
9
+ };
@@ -0,0 +1,2 @@
1
+ import type { CompilerSync } from './types.ts';
2
+ export declare const stylePreprocessorImports: CompilerSync;
@@ -0,0 +1,41 @@
1
+ import { getStyleLang, styleExtractor } from './compilers.js';
2
+ import { compiler as lessCompiler } from './less.js';
3
+ import { compiler as scssCompiler } from './scss.js';
4
+ import { compiler as stylusCompiler } from './stylus.js';
5
+ export const stylePreprocessorImports = (text, path) => {
6
+ let scss = '';
7
+ let less = '';
8
+ let stylus = '';
9
+ styleExtractor.lastIndex = 0;
10
+ let match;
11
+ while ((match = styleExtractor.exec(text))) {
12
+ const attrs = match[1];
13
+ const body = match[2];
14
+ if (!body)
15
+ continue;
16
+ switch (getStyleLang(attrs)) {
17
+ case 'scss':
18
+ case 'sass':
19
+ scss = scss ? `${scss}\n${body}` : body;
20
+ break;
21
+ case 'less':
22
+ less = less ? `${less}\n${body}` : body;
23
+ break;
24
+ case 'styl':
25
+ case 'stylus':
26
+ stylus = stylus ? `${stylus}\n${body}` : body;
27
+ }
28
+ }
29
+ let out = scss ? scssCompiler(scss, path) : '';
30
+ if (less) {
31
+ const imports = lessCompiler(less, path);
32
+ if (imports)
33
+ out = out ? `${out}\n${imports}` : imports;
34
+ }
35
+ if (stylus) {
36
+ const imports = stylusCompiler(stylus, path);
37
+ if (imports)
38
+ out = out ? `${out}\n${imports}` : imports;
39
+ }
40
+ return out;
41
+ };
@@ -0,0 +1,7 @@
1
+ import type { CompilerSync } from './types.ts';
2
+ export declare const compiler: CompilerSync;
3
+ declare const _default: {
4
+ dependencies: string[];
5
+ compiler: CompilerSync;
6
+ };
7
+ export default _default;
@@ -0,0 +1,36 @@
1
+ import { isScopedPackage, isTildePackage, splitSpec } from './shared.js';
2
+ const dependencies = ['stylus'];
3
+ const importMatcher = /@(?:import|require)\s+['"]([^'"]+)['"]/g;
4
+ const candidates = (specifier) => {
5
+ const { dir, name } = splitSpec(specifier);
6
+ if (name.endsWith('.styl') || name.endsWith('.stylus') || name.endsWith('.css'))
7
+ return [`${dir}/${name}`];
8
+ return [`${dir}/${name}.styl`, `${dir}/${name}/index.styl`];
9
+ };
10
+ export const compiler = text => {
11
+ if (!text.includes('@import') && !text.includes('@require'))
12
+ return '';
13
+ const out = [];
14
+ let i = 0;
15
+ let match;
16
+ importMatcher.lastIndex = 0;
17
+ while ((match = importMatcher.exec(text))) {
18
+ let spec = match[1];
19
+ if (!spec || spec.includes('*'))
20
+ continue;
21
+ let isBare = isScopedPackage(spec);
22
+ if (isTildePackage(spec)) {
23
+ spec = spec.slice(1);
24
+ isBare = true;
25
+ }
26
+ if (isBare) {
27
+ out.push(`import _$${i++} from '${spec}';`);
28
+ }
29
+ else {
30
+ for (const s of candidates(spec))
31
+ out.push(`import _$${i++} from '${s}';`);
32
+ }
33
+ }
34
+ return out.join('\n');
35
+ };
36
+ export default { dependencies, compiler };
package/dist/constants.js CHANGED
@@ -84,6 +84,8 @@ export const IGNORED_GLOBAL_BINARIES = new Set([
84
84
  'npm',
85
85
  'nproc',
86
86
  'npx',
87
+ 'nub',
88
+ 'nubx',
87
89
  'paste',
88
90
  'pnpm',
89
91
  'pnpx',
@@ -153,6 +155,8 @@ export const FOREIGN_FILE_EXTENSIONS = new Set([
153
155
  '.sass',
154
156
  '.scss',
155
157
  '.sh',
158
+ '.styl',
159
+ '.stylus',
156
160
  '.svg',
157
161
  '.ttf',
158
162
  '.webp',