webpro / knip Goto Github PK
View Code? Open in Web Editor NEW✂️ Find unused files, dependencies and exports in your JavaScript and TypeScript projects. Knip it before you ship it!
Home Page: https://knip.dev
License: ISC License
✂️ Find unused files, dependencies and exports in your JavaScript and TypeScript projects. Knip it before you ship it!
Home Page: https://knip.dev
License: ISC License
Report unused dependencies (and optionally devDependencies
) from package.json
.
Knip version: 1.8.0
For someone like me who is new to writing libraries and Apis, I easily get over 200 - 400 things found. It would be great to have a proper result message that shows the final results of the things found (like the listing that is done while processing the files).
On another project I got a error message at the end that said:
ELIFECYCLE exited with code <sum of found things>
I installed knip
on one of my projects and faced an issue with a dependency I have on @types/estree
.
Specifically, @types/estree
only exists as a @types/
package - there's no estree
package. However, to import types from @types/
package in TypeScript, you must (I believe) import it from the "base" package (which happens here). But since estree
doesn't exist, knip
cannot find the dependency and reports an unlisted dependency.
Even if this can be fixed by updating my TypeScript configuration, I would expect knip
to support the import style I'm currently using.
Hello, when I run knip on my project, I get unused types in my report but the command still returns 0 as exit code.
By reading the code here
const reportGroup = report.files ? 'files' : (Object.keys(report) as IssueGroup[]).find(key => report[key]);
const counterGroup = reportGroup === 'unlisted' ? 'unresolved' : reportGroup;
if (counterGroup) {
const count = counters[counterGroup];
if (count > Number(maxIssues)) process.exit(count);
}
It seems to always take the file counter instead of aggregating all the counters. Is it expected?
I can do a pull request if you need help :)
The default process exit code with the total number of errors should probably be optional.
Here's our use case that caused issues recently:
knip
in our stack I had to add a knip ... || true
in our CI command that runs this tool, to not block the CI workflow|| true
there, but in reality it errored out.Proposal: Add an optional CLI flag to always use process exit code 0.
Not sure how possible it would be but the ability to detect unused enum values would be a nice addition.
Might be interesting to use the CODEOWNERS file and display code owners with results and/or group results by code owner
Some examples:
{
"scripts": {
"example1": "node ./scripts/start.js",
"example2": "node --require ./local.js some-package",
"example3": "npx cli.js",
"example4": "node --loader tsx ./scripts/dev.ts",
"example5": "ts-node ./run.ts"
}
}
Some common patterns like this can be added as entry files automatically, saves manual globs in entry
config.
Also, error-prone, although by checking if the local file exists this feature sounds feasible and useful.
Hi,
really awesome project! Thanks!
Any chances there is a way / plan to add a feature to analyze React.lazy() loaded components?
For example:
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
I would like to have 'OtherComponent' code analyzed.
Currently Knip only supports .json
and .jsonc
. It could be very interesting for some projects to be able to add custom/dynamic configuration.
Add something so (dev) dependencies that are not imported using import
or require
are also marked as used.
For example, ESLint plugins or Babel presets are listed in configuration files using string literals. Would be nice to detect those and mark them as a used/referenced dependency (and thus also list unused ones).
But it should be trivial to add such custom resolvers. And probably ignore patterns to fill the holes.
Knip version: 1.7.0
IDE: VS Code
While testing around in knip.json
, I found that the json schema for a knip.json
file is very inconsistent or it's default values lead to errors.
Here is a list of my tries with only pressing tab:
{
"$schema": "https://unpkg.com/knip@1/schema.json",
"babel"
"capacitor"
"changesets"
"commitlint"
"cypress"
"entry": [
"index.{js,ts,tsx}",
"src/index.{js,ts,tsx}"
]
"eslint"
"exclude": "classMembers" // Zod error: expected array
"gatsby"
"github-actions"
"husky"
"ignore": []
"ignoreBinaries": "curl" // Zod error: expected array
"ignoreDependencies": "husky" // Zod error: expected array
"ignoreWorkspaces": "packages/ignore-me" // Zod error: expected array
"include": "dependencies" // Zod error: expected array
"jest"
"lint-staged"
"markdownlint"
"mocha"
"next"
"npm-package-json-lint"
"nx"
"nyc"
"paths": {
"" // no suggestions
}
"playwright"
"postcss"
"prettier"
"project": [
"**/*.{js,ts,tsx}"
]
"release-it"
"remark"
"remix"
"rollup"
"sentry"
"storybook"
"stryker"
"typescript"
"vitest"
"webpack"
"workspaces": {
"" // no suggestions
}
}
Properties with no values are boolean values that didn't have a suggestion.
It would be great to have auto completion to make it easier to work with knip. :)
👋 , coming over here from JoshuaKGoldberg/create-typescript-app#174. This package looks great and I'm excited for it! 🙂
But, the name Knip -while very cute and thematic per ## Knip?!
- gives no indication to non-Dutch-speakers what the project does. Which makes it harder for developers new to the ecosystem to keep track of what packages all do. Confusing project names is a problem for all levels of developers -I personally have a hard time keeping track of everything- and is especially troublesome for early/novice developers.
Could this project please be renamed to something that won't add another word-to-memorize for folks? Just throwing out some first thoughts, maybe... cleanall
? find-unused-everything
? megaprune
? package-prune
?
there's lots of class's properties in my project. can knip support remove these properties?
The main
function in src/index.ts
or something similar/new could be exposed for programmatic usage. Yet needs attention in terms of API: what should it look like for external usage?
Knip version:
Setting up multiple workspaces in a monorepo the wrong way results in this error message:
Resolving plugin configuration files...
<project-path>/knip/node_modules/knip/dist/workspace-worker.js:236
return dependencies.map(symbol => ({ type: 'unlisted', filePath: configFilePath, symbol }));
^
TypeError: dependencies.map is not a function
at <project-path>/knip/node_modules/knip/dist/workspace-worker.js:236:33
at async Promise.all (index 0)
at async WorkspaceWorker.findDependenciesByPlugin (<project-path>/knip/node_modules/knip/dist/workspace-worker.js:227:45)
at async WorkspaceWorker.findDependenciesByPlugins (<project-path>/knip/node_modules/knip/dist/workspace-worker.js:205:42)
at async main (<project-path>/knip/node_modules/knip/dist/index.js:186:56)
at async run (<project-path>/knip/node_modules/knip/dist/cli.js:21:46)
at async <project-path>/knip/node_modules/knip/dist/cli.js:48:1
"workspaces": []
in package.json
"workspaces": {}
in custom knip.json
package.json
or knip.json
Idk, this monorepo functionality is quite buggy, which is why I can't really use knip :(
Sometimes dependencies are only referenced in a GitHub Action (yaml) or some other "obscure" configuration.
At least this type of false positives should be documented clearly.
Hello 👋
esbuild
released a 0.16.17
version and the 1.2.0
release of Knip has a fixed-version dependency on 0.16.16
.
In our repository we also use esbuild and we are not able to update to knip 1.2.0
because we have esbuild 0.16.17
, updating our Yarn lockfile yields the following error:
error /home/madx/company_project/node_modules/knip/node_modules/esbuild: Command failed.
Exit code: 1
Command: node install.js
Arguments:
Directory: /home/madx/company_project/node_modules/knip/node_modules/esbuild
Output:
/home/madx/company_project/node_modules/knip/node_modules/esbuild/install.js:130
throw new Error(`Expected ${JSON.stringify("0.16.16")} but got ${JSON.stringify(stdout)}`);
^
Error: Expected "0.16.16" but got "0.16.17"
at validateBinaryVersion (/home/madx/company_project/node_modules/knip/node_modules/esbuild/install.js:130:11)
Would it be possible to update to 0.16.17
? (or have a more relaxed policy on patch versions?)
Thanks
Knip version: 1.8.0
While digging through the output objects in --debug
, I noticed that knip is not tracking the tsconfig file. I have the typescript plugin enabled, whether I specify the option in my custom knip.json
or not, the root tsconfig does not get tracked.
Excerpt from the debug message:
[knip] Unresolved configuration
{
cwd: '<root>',
tsConfigFile: undefined,
gitignore: true,
isStrict: false,
isProduction: false,
isShowProgress: false,
isIncludeEntryExports: false
}
[knip] Included workspaces
[
{
name: '.',
dir: '<root>',
config: {
entry: [ 'src/visual.ts' ],
project: [ 'src/**/*.ts' ],
paths: {},
ignore: [],
typescript: { config: [ 'tsconfig.json' ], entry: null, project: null }
},
ancestors: []
}
]
[knip] Enabled plugins (.)
[
'Babel',
'commitlint',
'ESLint',
'husky',
'Prettier',
'TypeScript',
'Webpack'
]
Installing [email protected]
with yarn
prints the following:
YN0002: │ knip@npm:0.13.1 doesn't provide esbuild (peefd7), requested by esbuild-register
And as expected, it fails to run:
node:internal/modules/cjs/loader:995
const err = new Error(message);
^
Error: Cannot find module 'esbuild'
Require stack:
- /home/dev/knip-test/node_modules/esbuild-register/dist/node.js
at Module._resolveFilename (node:internal/modules/cjs/loader:995:15)
at Module._load (node:internal/modules/cjs/loader:841:27)
at Module.require (node:internal/modules/cjs/loader:1061:19)
at require (node:internal/modules/cjs/helpers:103:18)
at Object.<anonymous> (/home/dev/knip-test/node_modules/esbuild-register/dist/node.js:4622:16)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._compile (/home/dev/knip-test/node_modules/pirates/lib/index.js:136:24)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at Object.newLoader [as .js] (/home/dev/knip-test/node_modules/pirates/lib/index.js:141:7)
at Module.load (node:internal/modules/cjs/loader:1037:32) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/home/dev/knip-test/node_modules/esbuild-register/dist/node.js'
]
}
Hi @webpro, when I was testing this out on the freecodecamp repo, node ran out of memory when I used the tool. The proximate cause was that a bunch of build artifacts were included in the projectFiles, ballooning the memory usage. The ultimate cause (as far as I can see) is that ts-morph has to hold the entire project's AST in memory at once and that gets quite large.
It might be worth saying something in the docs to help mitigate this. Maybe a troubleshooting section?
Much like dependencies
and devDependencies
First of all, knip
is an amazing tool and I can see this becoming really useful!
We use https://pnpm.io/ as package manager and it took me a while to go through all error messages when executing knip
until I was able to make it work. In the end, I had to copy over our workspaces config from pnpm-workspace.yaml
to package.json
and update the format.
It would be cool to support pnpm
out of the box, or at least put a note into the readme for now, so these users are not excluded and can get started with knip
.
Using a custom reporter in a top level project using "type": "commonjs"
is not possible since v0.12.0 when the ESM migration was done:
module.exports = async function reporter() {
// ...
};
Adding the following log after the printReport
is defined:
console.log('printReport', printReport);
Yields the following:
printReport [Module: null prototype] { default: [AsyncFunction: reporter] }
Running the tool errors like:
file:///home/runner/work/foo/node_modules/knip/dist/cli.js:37
await printReport({ report, issues, cwd, workingDir, isDev, options: reporterOptions });
^
TypeError: printReport is not a function
at run (file:///home/runner/work/foo/node_modules/knip/dist/cli.js:37:15)
This used to work on knip v0.11.0. The log above printed this on that version:
printReport [AsyncFunction: reporter]
Hello,
I was playing around with the CLI in my local project, and I got an error when running it in the following context:
command:
pnpx knip --reporter json --include files,duplicates
output:
failed to load codeowners file from C:\coding-work\halo-discord\halo-discord-bot\.github\CODEOWNERS Error: is not a valid owner name in rule * @elijaholmos
at createMatcherCodeownersRule (C:\Users\eliol\AppData\Local\pnpm\store\v3\tmp\dlx-19668\node_modules\.pnpm\@snyk+github-codeowners@1.0.0\node_modules\@snyk\github-codeowners\dist\lib\ownership\OwnershipEngine.js:72:23)
at Function.FromCodeownersFile (C:\Users\eliol\AppData\Local\pnpm\store\v3\tmp\dlx-19668\node_modules\.pnpm\@snyk+github-codeowners@1.0.0\node_modules\@snyk\github-codeowners\dist\lib\ownership\OwnershipEngine.js:50:28)
at exports.default (C:\Users\eliol\AppData\Local\pnpm\store\v3\tmp\dlx-19668\node_modules\.pnpm\knip@0.9.1\node_modules\knip\dist\reporters\json.js:21:106)
at async run (C:\Users\eliol\AppData\Local\pnpm\store\v3\tmp\dlx-19668\node_modules\.pnpm\knip@0.9.1\node_modules\knip\dist\cli.js:62:9)
knip.json
:
{
"dev": true,
"entryFiles": ["index.js"],
"projectFiles": ["/**/*.js"]
}
The project I'm testing knip in is open-source and can be found at https://github.com/elijaholmos/halo-discord-bot. In my CODEOWNERS file, I'm using the global owners syntax, as specified here.
The husky
dependency demands to run husky install
which adds hooksPath = .husky
to .git/config
. Then, for example, lint-staged
could be executed from an executable script such as .husky/pre-commit
.
This means packages like this require another way of finding out whether they're actually used or not:
husky
: look for git config core.hooksPath
and see if result (.husky
) is existing directory?lint-staged
: based on the tool used (not necessarily husky!), find it's usage in such a script or config fileNot sure if this is the way to go and/or if it would be enough. And it's just an example, there are more (popular) tools out there that do things differently (not judging). I'm inclined to think it's feasible for Knip to add another type of plugin, or extend the existing plugin system for such use cases.
Just saying, packages can always be added to the ignoreDependencies
list to get rid of such false positives.
Any way to get this working with .js
entry points? Renaming my entry point from index.js
to index.ts
fixes the issue, but I have a large code base where this isn't so practicle.
Cheers
knip doesnt seem to have aversion cli option when looking at knip --help
Since I am now in the process of testing the latest version, it would be great to be able to do knip -v
or knip --version
to know which version I am running.
example:
common
|-- index.js
src
|-- monoA
|-- entry.js
|-- monoB
|-- entry.js
and npm run monoA
, webpack alias "@": 'dir/monoA'
and npm run monoB
, webpack alias "@": 'dir/monoB'
then: How are aliases properly addressed
I'm getting the following error:
/var/www/html/packages/myProject/babel.config.js:41
api.cache(true);
^
TypeError: api.cache is not a function
at module.exports (/var/www/html/packages/myProject/babel.config.js:41:7)
at findBabelDependencies (file:///var/www/html/node_modules/knip/dist/plugins/babel/index.js:32:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///var/www/html/node_modules/knip/dist/workspace-worker.js:228:34
at async Promise.all (index 0)
at async WorkspaceWorker.findDependenciesByPlugin (file:///var/www/html/node_modules/knip/dist/workspace-worker.js:227:45)
at async WorkspaceWorker.findDependenciesByPlugins (file:///var/www/html/node_modules/knip/dist/workspace-worker.js:205:42)
at async main (file:///var/www/html/node_modules/knip/dist/index.js:184:80)
at async run (file:///var/www/html/node_modules/knip/dist/cli.js:20:46)
at async file:///var/www/html/node_modules/knip/dist/cli.js:47:1
The content of the file is:
...
module.exports = function (api) {
api.cache(true);
return {
env: {
test: {
plugins: testPlugins,
//'presets': presets,
compact: false,
comments: true,
sourceMaps: true,
},
},
};
};
It somehow looks like this file is being executed.
knip version: 1.6.1
A little funny thing about running knip after using npm init -y
is that it sees the generated script
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
as unresolved dependencies:
Unlisted or unresolved dependencies (2)
echo package.json
exit package.json
I have little idea about operating systems, but I think it will react the same way with other OS commands.
Knip version: 1.7.0
Running knip in non-production mode triggers my webpack configuration. Since my config has automatic build mode handling, it fails.
My configuration (./webpack.config.js
):
const dev = require('./webpack.dev.js') // configuration for development build
const prod = require('./webpack.prod.js') // configuration for production build
function getConfig(mode) {
switch (mode) {
case 'development':
return dev(process.env)
case 'production':
return prod(process.env)
default:
throw new Error(`Trying to use an unknown mode ${mode}`) // unknown command
}
}
const processModes = {
start: 'development',
prod: 'production'
}
module.exports = () => {
const mode = processModes[process.env.npm_lifecycle_event]
process.env.NODE_ENV = mode
return getConfig(mode)
}
Create a new project, copy this configuration and set a package.json
script with "knip": "knip"
.
The only way to handle this would be either to default to development
or to set "webpack": false
in knip.json
.
I don't think this is the intended way as it flawlessly lints my other files. Is it possible to lint it without triggering my config or should I handle it myself?
Using the knip schema for the config on the next
branch, e.g.1:
{
"$schema": "./node_modules/knip/schema.json",
"entry": ["lib/index.ts!"],
"project": ["lib/**/*.ts!"],
"ignoreBinaries": ["actionlint"],
"ignoreDependencies": [
"@ericcornelissen/eslint-plugin-top",
"eslint-v6",
"eslint-v7",
"eslint-v8"
]
}
results in the following warning by VSCode2:
[{
"resource": ".../eslint-plugin-top/knip.json",
"owner": "_generated_diagnostic_collection_name_#3",
"severity": 4,
"message": "Property $schema is not allowed.",
"startLineNumber": 2,
"startColumn": 3,
"endLineNumber": 2,
"endColumn": 12
}]
This seems to be the result of having the following line in the schema:
Line 43 in 1052ec8
as removing this line from the scheme makes the warning go away.
However, removing that lines makes the scheme stop complaining about all extraneous options. Hence, it might be better to add the "$schema"
key to the schema like so:
// ...
"properties": {
"$schema": {
"type": "string"
},
// ...
},
// ...
Ideas:
json
+ external toolsjson
has this)I'm getting the following error in [email protected]
/node_modules/knip/dist/util/modules.js:6
const match = value.replace(/\\/g, '/').match(/(?<=node_modules\/)(@[^/]+\/[^/]+|[^/]+)/);
^
TypeError: value.replace is not a function
at getPackageName (/node_modules/knip/dist/util/modules.js:6:25)
at Array.map (<anonymous>)
at findPostCSSDependencies (/node_modules/knip/dist/plugins/postcss/index.js:13:90)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /node_modules/knip/dist/workspace-worker.js:232:34
at async Promise.all (index 0)
at async WorkspaceWorker.findDependenciesByPlugin (/node_modules/knip/dist/workspace-worker.js:231:45)
at async WorkspaceWorker.findDependenciesByPlugins (/node_modules/knip/dist/workspace-worker.js:209:42)
at async main (/node_modules/knip/dist/index.js:179:80)
at async run (/node_modules/knip/dist/cli.js:21:46)
It seems to break when reading the package name from postcss.config.js
Our postcss.config.js contains the autoprefixer import which is a function instead of a string :)
module.exports = {
plugins: [require('autoprefixer')],
};
I wanted to try this great tool for our project, but I get this error message:
Processing: packages/store/src/Reducer/OptimisticReduce.ts
/var/www/html/node_modules/@ts-morph/common/dist/ts-morph-common.js:448
throw new InvalidOperationError(typeof errorMessage === "string" ? errorMessage : errorMessage());
^
InvalidOperationError: A child of the kind Identifier was expected.
at Object.throwIfNullOrUndefined (/var/www/html/node_modules/@ts-morph/common/dist/ts-morph-common.js:448:19)
at FunctionDeclaration.getFirstChildByKindOrThrow (/var/www/html/node_modules/ts-morph/dist/ts-morph.js:3776:36)
at file:///var/www/html/node_modules/knip/dist/runner.js:115:54
at Array.forEach (<anonymous>)
at file:///var/www/html/node_modules/knip/dist/runner.js:85:34
at Map.forEach (<anonymous>)
at file:///var/www/html/node_modules/knip/dist/runner.js:84:36
at Array.forEach (<anonymous>)
at findIssues (file:///var/www/html/node_modules/knip/dist/runner.js:61:29)
at main (file:///var/www/html/node_modules/knip/dist/index.js:108:40)
Node.js v18.12.0
Is there anything I can do to find out where the problem is in OptimisticReduce.ts
?
I'm using the latest version of knip.
This project seems to currently support typescript path aliases aliases. However, there are many other possible ways to create path aliases. For instance:
And I'm sure there are a lot more possibilities out there.
I would be interesting if this project had a more generic way to specific aliases through config and CLI parameters instead of trying to figure out through your project config (Even though it's nice if it can figure out magically it sounds a lot easier if we could just tell it what the aliases look like)
I love the project idea though!
In existing and/or new, more extensive reporter
Knip version: 1.8.0
Knip does not check whether the returned webpack configuration has been merged with another configuration via webpack-merge
or a function type configuration.
For example, Knip says that webpack-merge
, esbuild
and esbuild-loader
are not used, even though they are defined and merged with another configuration from
webpack.common.js
const esbuild = require('esbuild')
module.exports = (env) => {
module: {
rules: [
{
test: /(\.js)x|\.js$/,
loader: 'esbuild-loader',
include: srcPath,
exclude: /node_modules/,
options: {
target: 'es2015',
tsConfigRaw: require('./tsconfig.json'),
implementation: esbuild
}
},
]
}
}
webpack.dev.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = (env) => merge(common(env), {
mode: 'development'
}
webpack.config.js
const dev = require('./webpack.dev.js')
module.exports = (env, argv) => {
return env.production ? dev(process.env) : throw new Error('Unsupported mode)
}
Results after running knip
:
Unused dev dependencies (3)
esbuild package.json
esbuild-loader package.json
webpack-merge package.json
I've found that in a test project, ts-morph
seems to not properly resolve React components.
const productionFiles = production.getSourceFiles();
// Now resolve dependencies of entry files to find all production files
production.resolveSourceFileDependencies();
const productionFiles = production.getSourceFiles();
debugLogSourceFiles(options, 1, 'Included production source files', productionFiles);
productionFiles
simply ignores imports that are React
imports
Seems to be a related issue
dsherret/ts-morph#1250
Will follow up with a minimal viable repro / repo later.
Requires some kind of "integration" test to run Knip from the command line, and assert output.
Running Knip with Node v16.14.2 results in the following Error:
node_modules/knip/dist/cli.js:13
const { values: { help, dir, config: configFilePath = 'knip.json', tsConfig: tsConfigFilePath, include = [], exclude = [], ignore = [], 'no-gitignore': isNoGitIgnore = false, dev: isDev = false, 'no-progress': noProgress = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', 'max-issues': maxIssues = '0', jsdoc: jsDoc = [], debug: isDebug = false, 'debug-level': debugLevel = '1', }, } = (0, node_util_1.parseArgs)({
^
TypeError: (0 , node_util_1.parseArgs) is not a function
After upgrading to Node v16.18.0 this issue was resolved. If this is expected, I suggest adding a check and urging the user to upgrade their version of Node.
👋 @webpro!
WDYT of using dependency ranges (e.g. ^
) instead of pinned versions? I just opened blockprotocol/blockprotocol#895 to test #31 and noticed an extra instance of eslint
in my yarn.lock
. It’d be great if it could be deduplicated.
Transcript:
❯ npx knip -h
node:internal/errors:484
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'typescript' imported from /home/tobi/.nvm/versions/node/v18.12.1/lib/node_modules/knip/dist/index.js
at new NodeError (node:internal/errors:393:5)
at packageResolve (node:internal/modules/esm/resolve:860:9)
at moduleResolve (node:internal/modules/esm/resolve:909:20)
at defaultResolve (node:internal/modules/esm/resolve:1124:11)
at nextResolve (node:internal/modules/esm/loader:163:28)
at ESMLoader.resolve (node:internal/modules/esm/loader:841:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
at link (node:internal/modules/esm/module_job:75:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v18.12.1
I’m using nvm, maybe this is the reason?
❯ nvm -v
0.39.1
Related to #31, but at least a plugin to find binaries used in lint-staged configuration is regular stuff Knip should have.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.