streetsidesoftware / cspell

A Spell Checker for Code!
https://cspell.org
MIT License
1.26k stars 103 forks source link

Add a way to ignore package names from package.json #3215

Open gajus opened 2 years ago

gajus commented 2 years ago

Is your feature request related to a problem? Please describe.

At the moment, we have to pretty much whitelist every package name in our dictionary.

Describe the solution you'd like

It would be nice if cspell had an option to read names from package.json dependencies and add them to the dictionary.

Describe alternatives you've considered

We manually add all package names to the dictionary, but it causes unnecessary noise in the dictionary file.

Additional context Add any other context or screenshots about the feature request here.

Jason3S commented 2 years ago

@gajus,

Work is in progress to add parsing of JavaScript and other file types to enable ignoring imports and related things. See: #2684

In the meantime, you can use a configuration like this:

cspell-node.config.cjs

const fs = require('fs');
const path = require('path');

/**
 * Search for `package.json`
 * @param {string} from - search `from` directory.
 * @returns {string} - path to package.json
 */
function findNearestPackageJson(from) {
    from = path.resolve(from);
    const parent = path.dirname(from);
    if (!from || parent === from) {
        return;
    }

    const pkg = path.join(from, 'package.json');
    if (fs.existsSync(pkg)) {
        return pkg;
    }
    return findNearestPackageJson(parent);
}

/**
 * Load the nearest package.json
 * @param {string} cwd
 * @returns
 */
function loadPackage(cwd) {
    const pkgFile = findNearestPackageJson(cwd);
    console.log('found: %o', pkgFile);
    if (!pkgFile) return;
    return JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
}

function determinePackageNamesAndMethods(cwd = process.cwd()) {
    const pkg = loadPackage(cwd) || {};
    const packageNames = Object.keys(pkg.dependencies || {}).concat(Object.keys(pkg.devDependencies || {}));
    const setOfWords = new Set(packageNames.flatMap((name) => name.replace(/[@]/g, '').split('/')));
    const words = [...setOfWords];
    return { words };
}

module.exports = {
    words: determinePackageNamesAndMethods().words,
};

cspell.json

{
  "import": ["./cspell-node.config.cjs"]
}
icetbr commented 2 years ago

My solution. I have a shared project with cspell.json. Every other project of mine has a symlink to this file, therefore any words added in one project are available to the others.

In any project, I can call this to refresh my list of words. This handles entries like @hapi/hapijs, which need to be turned into two:

node -e "import('../utils/src/listDependencies.js').then(m => m.listDependencies())"

import fs from 'fs';
const keys = Object.keys;

export const listDependencies = () => {
    const { dependencies, devDependencies } = JSON.parse(fs.readFileSync('./package.json'));
    const packages = keys(dependencies).concat(keys(devDependencies));
    const packagesNames = packages.reduce((acc, p) => [...acc, ...p.replace('@', '').split('/')] , []);
    fs.writeFileSync('./.vscode/packages-words.txt', packagesNames.join('\n'));
};
    "dictionaryDefinitions": [
        {
            "name": "packages-words",
            "path": "./packages-words.txt"
        }
    ],
    "dictionaries": [
        "packages-words"
    ],
chrismorison-wt commented 2 years ago

@Jason3S brilliant work-around, thanks! Here's my adjustment to handle package names like @fontsource/roboto:

function determinePackageNamesAndMethods(cwd = process.cwd()) {
    const package = loadPackage(cwd) || {};
    const packageNames = Object.keys(package.dependencies || {}).concat(Object.keys(package.devDependencies || {}));
    const nameSet = new Set();
    packageNames.forEach(name => nameSet.add(...name.replace('@', '').split('/')));
    return [...nameSet];
}

module.exports = {
    words: determinePackageNamesAndMethods(),
};
wvhulle commented 1 year ago

@gajus,

Work is in progress to add parsing of JavaScript and other file types to enable ignoring imports and related things. See: #2684

In the meantime, you can use a configuration like this:

cspell-node.config.js

const fs = require('fs');
const path = require('path');

/**
 * Search for `package.json`
 * @param {string} from - search `from` directory.
 * @returns {string} - path to package.json
 */
function findNearestPackageJson(from) {
    from = path.resolve(from);
    const parent = path.dirname(from);
    if (!from || parent === from) {
        return;
    }

    const pkg = path.join(from, 'package.json');
    if (fs.existsSync(pkg)) {
        return pkg;
    }
    return findNearestPackageJson(parent);
}

/**
 * Load the nearest package.json
 * @param {string} cwd
 * @returns
 */
function loadPackage(cwd) {
    const pkgFile = findNearestPackageJson(cwd);
    console.log('found: %o', pkgFile)
    if (!pkgFile) return;
    return JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
}

function determinePackageNamesAndMethods(cwd = process.cwd()) {
    const package = loadPackage(cwd) || {};
    const packageNames = Object.keys(package.dependencies || {}).concat(Object.keys(package.devDependencies || {}));
    return { packageNames };
}

module.exports = {
    words: determinePackageNamesAndMethods().packageNames,
};

cspell.json

{
  "import": ["./cspell-node.config.js"]
}

This gives me Configuration Error: Failed to read config file: "/home/.../cspell-node.config.js"

Jason3S commented 1 year ago

@wvhulle,

This gives me Configuration Error: Failed to read config file: "/home/.../cspell-node.config.js"

You might need to make it a .cjs file if you are running it in a "module" package.

CSpell will not load a .mjs or ESM module files.

I have changed https://github.com/streetsidesoftware/cspell/issues/3215#issuecomment-1181992508 to reflect the need for a .cjs file.

nickserv commented 1 year ago

Could we have a dependency parser like this built into cspell or a plugin?

jeremiah-snee-openx commented 1 year ago

@nickmccurdy This bugged me for a while too.

I ended up just creating a $ make cSpell cmd in my make file, but you can easily add to as a task to run on folder open of vscode. I used the jq util to parse package.json and generate a custom dictionary text. Then I just added custom dict config to .vscode/settings.json

cSpell Package Dictionary Generator

geovannimp commented 6 months ago

Here is my version with monorepo support:

cSpell package.json dictionary