Repository: webpro/knip
Pull request #82 (2023-03-12 12:46:11)

fix: parse rc configs with no extension as either yaml or json
rc files can often be written in either yaml or json so knip so try loading them as both.

As yaml is a super type of json. Any valid json can be parsed with the yaml parser - so it's more performant to try this one first. jsonc isn't valid yaml though so we still need to try the json parser if the yaml one fails.


Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..2dab3330
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+  // Use IntelliSense to learn about possible attributes.
+  // Hover to view descriptions of existing attributes.
+  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "type": "node",
+      "request": "launch",
+      "name": "Test Current File",
+      "skipFiles": ["<node_internals>/**"],
+      "runtimeArgs": ["--loader", "tsx", "--test", "${file}"]
+    }
+  ]
+}
diff --git a/README.md b/README.md
index 0d48758f..74c9d222 100644
--- a/README.md
+++ b/README.md
@@ -275,34 +275,35 @@ Knip contains a growing list of plugins:
 - [Capacitor][14]
 - [Changesets][15]
 - [commitlint][16]
-- [Cypress][17]
-- [ESLint][18]
-- [Gatsby][19]
-- [GitHub Actions][20]
-- [husky][21]
-- [Jest][22]
-- [Lefthook][23]
-- [lint-staged][24]
-- [markdownlint][25]
-- [Mocha][26]
-- [Next.js][27]
-- [npm-package-json-lint][28]
-- [Nx][29]
-- [nyc][30]
-- [Playwright][31]
-- [PostCSS][32]
-- [Prettier][33]
-- [Release It][34]
-- [Remark][35]
-- [Remix][36]
-- [Rollup][37]
-- [Sentry][38]
-- [Storybook][39]
-- [Stryker][40]
-- [TypeDoc][41]
-- [TypeScript][42]
-- [Vitest][43]
-- [Webpack][44]
+- [cspell][17]
+- [Cypress][18]
+- [ESLint][19]
+- [Gatsby][20]
+- [GitHub Actions][21]
+- [husky][22]
+- [Jest][23]
+- [Lefthook][24]
+- [lint-staged][25]
+- [markdownlint][26]
+- [Mocha][27]
+- [Next.js][28]
+- [npm-package-json-lint][29]
+- [Nx][30]
+- [nyc][31]
+- [Playwright][32]
+- [PostCSS][33]
+- [Prettier][34]
+- [Release It][35]
+- [Remark][36]
+- [Remix][37]
+- [Rollup][38]
+- [Sentry][39]
+- [Storybook][40]
+- [Stryker][41]
+- [TypeDoc][42]
+- [TypeScript][43]
+- [Vitest][44]
+- [Webpack][45]
 
 Plugins are automatically activated. Each plugin is automatically enabled based on simple heuristics. Most of them check
 whether one or one of a few (dev) dependencies are listed in `package.json`. Once enabled, they add a set of
@@ -310,7 +311,7 @@ configuration and/or entry files for Knip to analyze. These defaults can be over
 
 Most plugins use one or both of the following file types:
 
-- `config` - custom dependency resolvers are applied to the [config files][45]
+- `config` - custom dependency resolvers are applied to the [config files][46]
 - `entry` - files to include with the analysis of the rest of the source code
 
 See each plugin's documentation for its default values.
@@ -336,7 +337,7 @@ Other configuration files use `require` or `import` statements to use dependenci
 rest of the source files. These configuration files are also considered `entry` files.
 
 For plugins related to test files, it's good to know that the following glob patterns are always included by default
-(see [TEST_FILE_PATTERNS in constants.ts][46]):
+(see [TEST_FILE_PATTERNS in constants.ts][47]):
 
 - `**/*.{test,spec}.{js,jsx,ts,tsx,mjs,cjs}`
 - `**/__tests__/**/*.{js,jsx,ts,tsx,mjs,cjs}`
@@ -418,10 +419,10 @@ Each workspace can also have its own `paths` configured. Note that Knip `paths`
 
 Knip provides the following built-in reporters:
 
-- [`codeowners`][47]
-- [`compact`][48]
-- [`json`][49]
-- [`symbol`][50] (default)
+- [`codeowners`][48]
+- [`compact`][49]
+- [`json`][50]
+- [`symbol`][51] (default)
 
 The `compact` reporter shows the sorted files first, and then a list of symbols:
 
@@ -448,7 +449,7 @@ type ReporterOptions = {
 
 The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
 
-Find more details and ideas in [custom reporters][51].
+Find more details and ideas in [custom reporters][52].
 
 ## Libraries and "unused" exports
 
@@ -506,7 +507,7 @@ When unused dependencies are related to dependencies having a Knip [plugin][1],
 for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
 to match the custom location(s).
 
-When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][52].
+When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][53].
 
 #### Too many unused exports
 
@@ -514,7 +515,7 @@ When the project is a library and the exports are meant to be used by consumers
 
 1.  By default, unused exports of `entry` files are not reported. You could re-export from an existing entry file, or
     add the containing file to the `entry` array in the configuration.
-2.  The exported values or types can be marked [using the JSDoc `@public` tag][53].
+2.  The exported values or types can be marked [using the JSDoc `@public` tag][54].
 
 ### How to start using Knip in CI while having too many issues to sort out?
 
@@ -534,7 +535,7 @@ All of this is hiding problems, so please make sure to plan for fixing them and/
 
 This table is an ongoing comparison. Based on their docs (please report any mistakes):
 
-| Feature                            | **knip** | [depcheck][54] | [unimported][55] | [ts-unused-exports][56] | [ts-prune][57] |
+| Feature                            | **knip** | [depcheck][55] | [unimported][56] | [ts-unused-exports][57] | [ts-prune][58] |
 | :--------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
 | Unused files                       |    ✅    |       -        |        ✅        |            -            |       -        |
 | Unused dependencies                |    ✅    |       ✅       |        ✅        |            -            |       -        |
@@ -569,7 +570,7 @@ The following commands are similar:
     unimported
     knip --production --dependencies --include files
 
-Also see [production mode][58].
+Also see [production mode][59].
 
 ### ts-unused-exports
 
@@ -599,6 +600,12 @@ userland territory, much like code linters.
 Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
 for the job. I'm motivated to make knip perfectly suited for the job of cutting projects to perfection! ✂️
 
+## Contributors
+
+Special thanks to the wonderful people who have contributed to this project:
+
+[![Contributors][60]][61]
+
 [1]: #workspaces--monorepos
 [2]: #plugins
 [3]: #reporters
@@ -615,45 +622,48 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
 [14]: ./src/plugins/capacitor
 [15]: ./src/plugins/changesets
 [16]: ./src/plugins/commitlint
-[17]: ./src/plugins/cypress
-[18]: ./src/plugins/eslint
-[19]: ./src/plugins/gatsby
-[20]: ./src/plugins/github-actions
-[21]: ./src/plugins/husky
-[22]: ./src/plugins/jest
-[23]: ./src/plugins/lefthook
-[24]: ./src/plugins/lint-staged
-[25]: ./src/plugins/markdownlint
-[26]: ./src/plugins/mocha
-[27]: ./src/plugins/next
-[28]: ./src/plugins/npm-package-json-lint
-[29]: ./src/plugins/nx
-[30]: ./src/plugins/nyc
-[31]: ./src/plugins/playwright
-[32]: ./src/plugins/postcss
-[33]: ./src/plugins/prettier
-[34]: ./src/plugins/release-it
-[35]: ./src/plugins/remark
-[36]: ./src/plugins/remix
-[37]: ./src/plugins/rollup
-[38]: ./src/plugins/sentry
-[39]: ./src/plugins/storybook
-[40]: ./src/plugins/stryker
-[41]: ./src/plugins/typedoc
-[42]: ./src/plugins/typescript
-[43]: ./src/plugins/vitest
-[44]: ./src/plugins/webpack
-[45]: #config
-[46]: https://github.com/webpro/knip/blob/main/src/constants.ts
-[47]: #code-owners
-[48]: #compact
-[49]: #json
-[50]: #symbol-default
-[51]: ./docs/custom-reporters.md
-[52]: #create-a-new-plugin
-[53]: #libraries-and-unused-exports
-[54]: https://github.com/depcheck/depcheck
-[55]: https://github.com/smeijer/unimported
-[56]: https://github.com/pzavolinsky/ts-unused-exports
-[57]: https://github.com/nadeesha/ts-prune
-[58]: #production-mode
+[17]: ./src/plugins/cspell
+[18]: ./src/plugins/cypress
+[19]: ./src/plugins/eslint
+[20]: ./src/plugins/gatsby
+[21]: ./src/plugins/github-actions
+[22]: ./src/plugins/husky
+[23]: ./src/plugins/jest
+[24]: ./src/plugins/lefthook
+[25]: ./src/plugins/lint-staged
+[26]: ./src/plugins/markdownlint
+[27]: ./src/plugins/mocha
+[28]: ./src/plugins/next
+[29]: ./src/plugins/npm-package-json-lint
+[30]: ./src/plugins/nx
+[31]: ./src/plugins/nyc
+[32]: ./src/plugins/playwright
+[33]: ./src/plugins/postcss
+[34]: ./src/plugins/prettier
+[35]: ./src/plugins/release-it
+[36]: ./src/plugins/remark
+[37]: ./src/plugins/remix
+[38]: ./src/plugins/rollup
+[39]: ./src/plugins/sentry
+[40]: ./src/plugins/storybook
+[41]: ./src/plugins/stryker
+[42]: ./src/plugins/typedoc
+[43]: ./src/plugins/typescript
+[44]: ./src/plugins/vitest
+[45]: ./src/plugins/webpack
+[46]: #config
+[47]: https://github.com/webpro/knip/blob/main/src/constants.ts
+[48]: #code-owners
+[49]: #compact
+[50]: #json
+[51]: #symbol-default
+[52]: ./docs/custom-reporters.md
+[53]: #create-a-new-plugin
+[54]: #libraries-and-unused-exports
+[55]: https://github.com/depcheck/depcheck
+[56]: https://github.com/smeijer/unimported
+[57]: https://github.com/pzavolinsky/ts-unused-exports
+[58]: https://github.com/nadeesha/ts-prune
+[59]: #production-mode
+[60]: https://contrib.rocks/image?repo=webpro/knip
+[61]: https://github.com/webpro/knip/graphs/contributors
diff --git a/package.json b/package.json
index 6c988fc1..87e534f8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "knip",
-  "version": "1.14.3",
+  "version": "1.15.0",
   "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
   "homepage": "https://github.com/webpro/knip",
   "repository": "github:webpro/knip",
diff --git a/schema.json b/schema.json
index 341968ac..a98e78f1 100644
--- a/schema.json
+++ b/schema.json
@@ -180,6 +180,10 @@
           "title": "commitlint plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/commitlint/README.md)",
           "$ref": "#/definitions/plugin"
         },
+        "cspell": {
+          "title": "cspell plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/cspell/README.md)",
+          "$ref": "#/definitions/plugin"
+        },
         "cypress": {
           "title": "Cypress plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/cypress/README.md)",
           "$ref": "#/definitions/plugin"
diff --git a/src/plugins/commitlint/README.md b/src/plugins/commitlint/README.md
index bc228d2a..87a2d284 100644
--- a/src/plugins/commitlint/README.md
+++ b/src/plugins/commitlint/README.md
@@ -12,7 +12,12 @@ or `devDependencies`:
 ```json
 {
   "commitlint": {
-    "config": ["commitlint.config.{js,ts}"]
+    "config": [
+      ".commitlintrc",
+      ".commitlintrc.{json,yaml,yml,js,cjs,ts,cts}",
+      "commitlint.config.{js,cjs,ts,cts}",
+      "package.json"
+    ]
   }
 }
 ```
diff --git a/src/plugins/commitlint/index.ts b/src/plugins/commitlint/index.ts
index d4371097..91758d2a 100644
--- a/src/plugins/commitlint/index.ts
+++ b/src/plugins/commitlint/index.ts
@@ -4,6 +4,7 @@ import { hasDependency } from '../../util/plugin.js';
 import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
 
 // https://commitlint.js.org
+// https://github.com/conventional-changelog/commitlint#config
 
 type CommitLintConfig = {
   extends: string[];
@@ -16,10 +17,17 @@ export const ENABLERS = ['@commitlint/cli'];
 
 export const isEnabled: IsPluginEnabledCallback = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
 
-export const CONFIG_FILE_PATTERNS = ['commitlint.config.{js,ts}'];
-
-const findCommitLintDependencies: GenericPluginCallback = async configFilePath => {
-  const config: CommitLintConfig = await _load(configFilePath);
+export const CONFIG_FILE_PATTERNS = [
+  '.commitlintrc',
+  '.commitlintrc.{json,yaml,yml,js,cjs,ts,cts}',
+  'commitlint.config.{js,cjs,ts,cts}',
+  'package.json',
+];
+
+const findCommitLintDependencies: GenericPluginCallback = async (configFilePath, { manifest }) => {
+  const config: CommitLintConfig = configFilePath.endsWith('package.json')
+    ? manifest.commitlint
+    : await _load(configFilePath);
   return config?.extends ? [config.extends].flat() : [];
 };
 
diff --git a/src/plugins/cspell/README.md b/src/plugins/cspell/README.md
new file mode 100644
index 00000000..c74dc2e4
--- /dev/null
+++ b/src/plugins/cspell/README.md
@@ -0,0 +1,22 @@
+# cspell
+
+## Enabled
+
+This plugin is enabled when any of the following package names and/or regular expressions has a match in `dependencies`
+or `devDependencies`:
+
+- `cspell`
+
+## Default configuration
+
+```json
+{
+  "cspell": {
+    "config": ["cspell.config.{js,cjs,json,yaml,yml}", "cspell.{json,yaml,yml}", ".c{s,S}pell.json", "cSpell.json"]
+  }
+}
+```
+
+Also see [Knip plugins][1] for more information about plugins.
+
+[1]: https://github.com/webpro/knip/blob/main/README.md#plugins
diff --git a/src/plugins/cspell/index.ts b/src/plugins/cspell/index.ts
new file mode 100644
index 00000000..092be29b
--- /dev/null
+++ b/src/plugins/cspell/index.ts
@@ -0,0 +1,30 @@
+import { _load } from '../../util/loader.js';
+import { getPackageNameFromModuleSpecifier } from '../../util/modules.js';
+import { timerify } from '../../util/performance.js';
+import { hasDependency } from '../../util/plugin.js';
+import type { PluginConfig } from './types.js';
+import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
+
+// https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell#customization
+
+export const NAME = 'cspell';
+
+/** @public */
+export const ENABLERS = ['cspell'];
+
+export const isEnabled: IsPluginEnabledCallback = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
+
+export const CONFIG_FILE_PATTERNS = [
+  'cspell.config.{js,cjs,json,yaml,yml}',
+  'cspell.{json,yaml,yml}',
+  '.c{s,S}pell.json',
+  'cSpell.json',
+];
+
+const findPluginDependencies: GenericPluginCallback = async configFilePath => {
+  const config: PluginConfig = await _load(configFilePath);
+  const imports = config?.import ?? [];
+  return imports.map(getPackageNameFromModuleSpecifier);
+};
+
+export const findDependencies = timerify(findPluginDependencies);
diff --git a/src/plugins/cspell/types.ts b/src/plugins/cspell/types.ts
new file mode 100644
index 00000000..b15817e1
--- /dev/null
+++ b/src/plugins/cspell/types.ts
@@ -0,0 +1,3 @@
+export type PluginConfig = {
+  import?: string[];
+};
diff --git a/src/plugins/index.ts b/src/plugins/index.ts
index cf53f877..5998b82d 100644
--- a/src/plugins/index.ts
+++ b/src/plugins/index.ts
@@ -2,6 +2,7 @@ export * as babel from './babel/index.js';
 export * as capacitor from './capacitor/index.js';
 export * as changesets from './changesets/index.js';
 export * as commitlint from './commitlint/index.js';
+export * as cspell from './cspell/index.js';
 export * as cypress from './cypress/index.js';
 export * as eslint from './eslint/index.js';
 export * as gatsby from './gatsby/index.js';
diff --git a/src/plugins/typedoc/index.ts b/src/plugins/typedoc/index.ts
index 0af7454d..1aa6a9bf 100644
--- a/src/plugins/typedoc/index.ts
+++ b/src/plugins/typedoc/index.ts
@@ -1,4 +1,6 @@
+import path from 'node:path';
 import { _load } from '../../util/loader.js';
+import { isAbsolute } from '../../util/path.js';
 import { timerify } from '../../util/performance.js';
 import { hasDependency } from '../../util/plugin.js';
 import type { PluginConfig } from './types.js';
@@ -20,9 +22,23 @@ export const CONFIG_FILE_PATTERNS = [
   '.config/typedoc.config.{js,cjs}',
 ];
 
-const findPluginDependencies: GenericPluginCallback = async configFilePath => {
+const findPluginDependencies: GenericPluginCallback = async (configFilePath, { cwd }) => {
   const config: PluginConfig = await _load(configFilePath);
-  return config?.plugin ?? [];
+
+  const entryFiles: string[] = [];
+  const dependencies: string[] = [];
+
+  (config?.plugin ?? []).forEach(plugin => {
+    if (isAbsolute(plugin)) {
+      entryFiles.push(plugin);
+    } else if (plugin.startsWith('.')) {
+      entryFiles.push(path.join(cwd, plugin));
+    } else {
+      dependencies.push(plugin);
+    }
+  });
+
+  return { dependencies, entryFiles };
 };
 
 export const findDependencies = timerify(findPluginDependencies);
diff --git a/src/util/fs.ts b/src/util/fs.ts
index c5b8deed..b682dad6 100644
--- a/src/util/fs.ts
+++ b/src/util/fs.ts
@@ -1,6 +1,7 @@
 import { statSync } from 'node:fs';
 import { readFile } from 'node:fs/promises';
 import path from 'node:path';
+import yaml from 'js-yaml';
 import stripJsonComments from 'strip-json-comments';
 import { LoaderError } from './errors.js';
 
@@ -14,11 +15,29 @@ export const findFile = (workingDir: string, fileName: string) => {
   return isFile(filePath) ? filePath : undefined;
 };
 
-export const loadJSON = async (filePath: string) => {
+export const loadFile = async (filePath: string) => {
   try {
     const contents = await readFile(filePath);
-    return JSON.parse(stripJsonComments(contents.toString()));
+    return contents.toString();
   } catch (error) {
     throw new LoaderError(`Error loading ${filePath}`, { cause: error });
   }
 };
+
+export const loadJSON = async (filePath: string) => {
+  const contents = await loadFile(filePath);
+  return parseJSON(contents);
+};
+
+export const loadYAML = async (filePath: string) => {
+  const contents = await loadFile(filePath);
+  return parseYAML(contents);
+};
+
+export const parseJSON = async (contents: string) => {
+  return JSON.parse(stripJsonComments(contents));
+};
+
+export const parseYAML = async (contents: string) => {
+  return yaml.load(contents);
+};
diff --git a/src/util/loader.ts b/src/util/loader.ts
index 2c14f867..2d0636ff 100644
--- a/src/util/loader.ts
+++ b/src/util/loader.ts
@@ -1,23 +1,26 @@
-import fs from 'node:fs/promises';
 import path from 'node:path';
 import { pathToFileURL } from 'node:url';
 // eslint-disable-next-line import/order -- Modules in @types are handled differently
 import { load as esmLoad } from '@esbuild-kit/esm-loader';
-import yaml from 'js-yaml';
 import { require } from '../util/require.js';
 import { LoaderError } from './errors.js';
-import { loadJSON } from './fs.js';
+import { loadJSON, loadYAML, loadFile, parseJSON, parseYAML } from './fs.js';
 import { timerify } from './performance.js';
 
 const load = async (filePath: string) => {
   try {
     const ext = path.extname(filePath);
-    if (ext === '.json' || ext === '.jsonc' || /rc$/.test(filePath)) {
+    if (/rc$/.test(filePath)) {
+      const contents = await loadFile(filePath);
+      return parseYAML(contents).catch(() => parseJSON(contents));
+    }
+
+    if (ext === '.json' || ext === '.jsonc') {
       return loadJSON(filePath);
     }
 
     if (ext === '.yaml' || ext === '.yml') {
-      return yaml.load((await fs.readFile(filePath)).toString());
+      return loadYAML(filePath);
     }
 
     if (ext === '.mjs') {
diff --git a/src/version.ts b/src/version.ts
index 38c5811d..50a75646 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1,1 +1,1 @@
-export const version = '1.14.3';
+export const version = '1.15.0';


Test patch:
diff --git a/test/fixtures/plugins/commitlint/.commitlintrc.json b/test/fixtures/plugins/commitlint/.commitlintrc.json
new file mode 100644
index 00000000..d3d7f0cd
--- /dev/null
+++ b/test/fixtures/plugins/commitlint/.commitlintrc.json
@@ -0,0 +1,1 @@
+{ "extends": ["@commitlint/config-conventional"] }
diff --git a/test/fixtures/plugins/commitlint/package.json b/test/fixtures/plugins/commitlint/package.json
new file mode 100644
index 00000000..1acf59e1
--- /dev/null
+++ b/test/fixtures/plugins/commitlint/package.json
@@ -0,0 +1,7 @@
+{
+  "commitlint": {
+    "extends": [
+      "@commitlint/config-conventional"
+    ]
+  }
+}
diff --git a/test/fixtures/plugins/cspell/.cspell.json b/test/fixtures/plugins/cspell/.cspell.json
new file mode 100644
index 00000000..7287cea0
--- /dev/null
+++ b/test/fixtures/plugins/cspell/.cspell.json
@@ -0,0 +1,6 @@
+{
+  "version": "0.2",
+  "import": [
+    "@cspell/dict-cryptocurrencies/cspell-ext.json"
+  ]
+}
diff --git a/test/fixtures/plugins/typedoc/typedoc.json b/test/fixtures/plugins/typedoc/typedoc.json
index 7fe16d7c..ce346757 100644
--- a/test/fixtures/plugins/typedoc/typedoc.json
+++ b/test/fixtures/plugins/typedoc/typedoc.json
@@ -1,3 +1,3 @@
 {
-  "plugin": ["@appium/typedoc-plugin-appium", "typedoc-plugin-expand-object-like-types"]
+  "plugin": ["@appium/typedoc-plugin-appium", "typedoc-plugin-expand-object-like-types", "./dist/index.cjs"]
 }
diff --git a/test/tests/plugins/commitlint.test.ts b/test/tests/plugins/commitlint.test.ts
index 77745f2d..a0d205a1 100644
--- a/test/tests/plugins/commitlint.test.ts
+++ b/test/tests/plugins/commitlint.test.ts
@@ -2,11 +2,25 @@ import assert from 'node:assert/strict';
 import path from 'node:path';
 import test from 'node:test';
 import * as commitlint from '../../../src/plugins/commitlint/index.js';
+import { getManifest } from '../../helpers/index.js';
 
 const cwd = path.resolve('test/fixtures/plugins/commitlint');
+const manifest = getManifest(cwd);
 
-test('Find dependencies in commitlint configuration', async () => {
+test('Find dependencies in commitlint configuration (js)', async () => {
   const configFilePath = path.join(cwd, 'commitlint.config.js');
-  const dependencies = await commitlint.findDependencies(configFilePath);
+  const dependencies = await commitlint.findDependencies(configFilePath, {});
+  assert.deepEqual(dependencies, ['@commitlint/config-conventional']);
+});
+
+test('Find dependencies in commitlint configuration (json)', async () => {
+  const configFilePath = path.join(cwd, '.commitlintrc.json');
+  const dependencies = await commitlint.findDependencies(configFilePath, {});
+  assert.deepEqual(dependencies, ['@commitlint/config-conventional']);
+});
+
+test('Find dependencies in commitlint configuration (package.json)', async () => {
+  const configFilePath = path.join(cwd, 'package.json');
+  const dependencies = await commitlint.findDependencies(configFilePath, { manifest });
   assert.deepEqual(dependencies, ['@commitlint/config-conventional']);
 });
diff --git a/test/tests/plugins/cspell.test.ts b/test/tests/plugins/cspell.test.ts
new file mode 100644
index 00000000..504058c4
--- /dev/null
+++ b/test/tests/plugins/cspell.test.ts
@@ -0,0 +1,12 @@
+import assert from 'node:assert/strict';
+import path from 'node:path';
+import test from 'node:test';
+import * as cspell from '../../../src/plugins/cspell/index.js';
+
+const cwd = path.resolve('test/fixtures/plugins/cspell');
+
+test('Find dependencies in cspell configuration (json)', async () => {
+  const configFilePath = path.join(cwd, '.cspell.json');
+  const dependencies = await cspell.findDependencies(configFilePath, {});
+  assert.deepEqual(dependencies, ['@cspell/dict-cryptocurrencies']);
+});
diff --git a/test/tests/plugins/typedoc.test.ts b/test/tests/plugins/typedoc.test.ts
index 1757cbd5..664939a4 100644
--- a/test/tests/plugins/typedoc.test.ts
+++ b/test/tests/plugins/typedoc.test.ts
@@ -7,6 +7,9 @@ const cwd = path.resolve('test/fixtures/plugins/typedoc');
 
 test('Find dependencies in typedoc configuration (json)', async () => {
   const configFilePath = path.join(cwd, 'typedoc.json');
-  const dependencies = await typedoc.findDependencies(configFilePath);
-  assert.deepEqual(dependencies, ['@appium/typedoc-plugin-appium', 'typedoc-plugin-expand-object-like-types']);
+  const dependencies = await typedoc.findDependencies(configFilePath, { cwd });
+  assert.deepEqual(dependencies, {
+    dependencies: ['@appium/typedoc-plugin-appium', 'typedoc-plugin-expand-object-like-types'],
+    entryFiles: [path.join(cwd, 'dist/index.cjs')],
+  });
 });