UNPKG

cspell

Version:

A Spelling Checker for Code!

137 lines 4.68 kB
import assert from 'node:assert'; import { promises as fs } from 'node:fs'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { toFileDirURL, urlRelative } from '@cspell/url'; import { isCfgArrayNode, MutableCSpellConfigFile } from 'cspell-config-lib'; import { toError } from '../util/errors.js'; async function fileExists(url) { if (url.protocol !== 'file:') { return false; // Only check file URLs } try { const stats = await fs.stat(url); return stats.isFile(); } catch (e) { const err = toError(e); if (err.code === 'ENOENT') return false; throw e; } } export async function resolveImports(configFile, imports) { const fromConfigDir = new URL('./', configFile.url); const fromCurrentDir = toFileDirURL('./'); const require = createRequire(fromConfigDir); function isPackageName(name) { try { require.resolve(name, { paths: [fileURLToPath(fromConfigDir)] }); return true; } catch { return false; } } const _imports = []; for (const imp of imports) { const url = new URL(imp, fromCurrentDir); if (url.protocol !== 'file:') { _imports.push(imp); continue; } if (await fileExists(url)) { let rel = urlRelative(fromConfigDir, url); if (!(rel.startsWith('./') || rel.startsWith('../'))) { rel = './' + rel; // Ensure relative path starts with './' or '../' } _imports.push(rel); continue; } if (url.protocol !== 'file:') { _imports.push(url.href); continue; } if (isPackageName(imp)) { _imports.push(imp); continue; } throw new Error(`Cannot resolve import: ${imp}`); } return _imports; } function addImportsToMutableConfigFile(configFile, resolvedImports, comment) { let importNode = configFile.getNode('import', []); if (importNode.type === 'scalar') { configFile.setValue('import', [importNode.value]); importNode = configFile.getNode('import', []); } assert(isCfgArrayNode(importNode)); const knownImports = new Set(importNode.value); for (const imp of resolvedImports) { if (knownImports.has(imp)) continue; importNode.push(imp); } if (comment) { configFile.setComment('import', comment); } } export async function addImportsToConfigFile(configFile, imports, comment) { const resolvedImports = await resolveImports(configFile, imports); if (configFile instanceof MutableCSpellConfigFile) { return addImportsToMutableConfigFile(configFile, resolvedImports, comment); } const settings = configFile.settings; let importNode = settings.import; if (!Array.isArray(importNode)) { importNode = typeof importNode === 'string' ? [importNode] : []; settings.import = importNode; if (comment) { configFile.setComment('import', comment); } } assert(Array.isArray(importNode)); const knownImports = new Set(importNode); for (const imp of resolvedImports) { if (knownImports.has(imp)) continue; importNode.push(imp); } } export function setConfigFieldValue(configFile, key, value, comment) { configFile.setValue(key, value); if (comment !== undefined) { configFile.setComment(key, comment); } } export function addDictionariesToConfigFile(configFile, dictionaries, comment) { if (configFile instanceof MutableCSpellConfigFile) { const found = configFile.getValue('dictionaries'); const dicts = configFile.getNode('dictionaries', []); assert(isCfgArrayNode(dicts)); const knownDicts = new Set(dicts.value); for (const dict of dictionaries) { if (!knownDicts.has(dict)) { dicts.push(dict); knownDicts.add(dict); } } if (!found && comment) { // Set the comment on the field, not the list. configFile.setComment('dictionaries', comment); } return; } const settings = configFile.settings; const dicts = settings.dictionaries || []; const knownDicts = new Set(dicts); for (const dict of dictionaries) { if (!knownDicts.has(dict)) { dicts.push(dict); knownDicts.add(dict); } } setConfigFieldValue(configFile, 'dictionaries', dicts, comment); } //# sourceMappingURL=adjustConfig.js.map