Skip to content

Commit ec0a653

Browse files
Jason3SCopilot
andauthored
fix: Enable reading dictionaries from cspell-vfs (#8553)
Signed-off-by: Jason Dent <Jason3S@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4617611 commit ec0a653

File tree

24 files changed

+293
-69
lines changed

24 files changed

+293
-69
lines changed

packages/cspell-dictionary-bundler-plugin/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
"plugin"
1717
],
1818
"exports": {
19-
".": "./dist/index.js",
20-
"./api": "./dist/api.js",
21-
"./esbuild": "./dist/esbuild.js",
22-
"./farm": "./dist/farm.js",
23-
"./rolldown": "./dist/rolldown.js",
24-
"./rollup": "./dist/rollup.js",
25-
"./rspack": "./dist/rspack.js",
26-
"./vite": "./dist/vite.js",
27-
"./webpack": "./dist/webpack.js",
19+
".": "./dist/index.mjs",
20+
"./api": "./dist/api.mjs",
21+
"./esbuild": "./dist/esbuild.mjs",
22+
"./farm": "./dist/farm.mjs",
23+
"./rolldown": "./dist/rolldown.mjs",
24+
"./rollup": "./dist/rollup.mjs",
25+
"./rspack": "./dist/rspack.mjs",
26+
"./vite": "./dist/vite.mjs",
27+
"./webpack": "./dist/webpack.mjs",
2828
"./package.json": "./package.json"
2929
},
3030
"files": [

packages/cspell-dictionary-bundler-plugin/src/core/bundler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ export class CSpellDictionaryBundler {
4545
if (!def.path) continue;
4646
const d = { ...def };
4747
dictDefs[i] = d;
48-
delete d.file;
4948
const url = new URL(def.btrie ?? def.path, config.url);
5049
if (url.protocol !== 'file:') continue;
5150
const vfsUrl = await populateVfs(vfs, url);
51+
delete d.file;
52+
delete d.btrie;
5253
d.path = vfsUrl.href;
5354
}
5455

packages/cspell-dictionary-bundler-plugin/src/core/core.ts

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { fileURLToPath, pathToFileURL } from 'node:url';
1+
import { createRequire } from 'node:module';
2+
import path from 'node:path';
3+
import { pathToFileURL } from 'node:url';
24

35
import { createFilter, dataToEsm } from '@rollup/pluginutils';
46
import type { CSpellConfigFileReaderWriter } from 'cspell-config-lib';
@@ -12,6 +14,7 @@ export function createPlugin(): UnpluginInstance<Options | undefined, false> {
1214
return createUnplugin((rawOptions = {}) => {
1315
const options = resolveOptions(rawOptions);
1416
const filter = createFilter(options.include, options.exclude);
17+
const consoleLog = options.debug ? console.log.bind(console) : () => {};
1518

1619
let readerWriter: CSpellConfigFileReaderWriter | undefined = undefined;
1720
let bundler: CSpellDictionaryBundler | undefined = undefined;
@@ -22,13 +25,13 @@ export function createPlugin(): UnpluginInstance<Options | undefined, false> {
2225
enforce: options.enforce,
2326

2427
transform: {
25-
// filter: {
26-
// id: { include: options.include, exclude: options.exclude },
27-
// },
28+
filter: {
29+
id: { include: options.include, exclude: options.exclude },
30+
},
2831
async handler(code, id) {
29-
console.log(`Can transform ${id}? ${filter(id) ? 'yes' : 'no'}`);
32+
consoleLog(`Can transform ${id}? ${filter(id) ? 'yes' : 'no'}`);
3033
if (!filter(id)) return undefined;
31-
console.log(`Transforming ${id} with ${code.length} characters`);
34+
consoleLog(`Transforming ${id} with ${code.length} characters`);
3235
readerWriter ??= createReaderWriter();
3336
bundler ??= new CSpellDictionaryBundler(readerWriter);
3437

@@ -49,15 +52,17 @@ export function createPlugin(): UnpluginInstance<Options | undefined, false> {
4952
},
5053
},
5154
resolveId: {
52-
// filter: {
53-
// id: { include: options.include, exclude: options.exclude },
54-
// },
55+
filter: {
56+
id: { include: options.include, exclude: options.exclude },
57+
},
5558
handler(id, importer) {
56-
console.log(`Can Resolve ${id}? ${filter(id) ? 'yes' : 'no'} %o`, { id, importer });
59+
consoleLog(`Can Resolve ${id}? ${filter(id) ? 'yes' : 'no'} %o`, { id, importer });
5760
if (id.includes('\0') || !filter(id)) return undefined;
58-
const importedFromUrl = pathToFileURL(importer || process.cwd() + '/');
59-
const resolvedId = fileURLToPath(import.meta.resolve(id, importedFromUrl));
60-
console.log(`Resolving ${id}: %o`, import.meta.resolve(id));
61+
const resolvedId = resolveId(id, importer);
62+
if (!resolvedId) return undefined;
63+
consoleLog(`Resolving ${id}: %o`, {
64+
resolvedId,
65+
});
6166
return {
6267
id: resolvedId,
6368
external: false,
@@ -69,6 +74,20 @@ export function createPlugin(): UnpluginInstance<Options | undefined, false> {
6974
});
7075
}
7176

77+
function resolveId(id: string, importer?: string): string | undefined {
78+
if (id.includes('\0')) return undefined;
79+
const dir = (importer ? path.dirname(importer) : process.cwd()) + '/';
80+
if (id.startsWith('./') || id.startsWith('../')) {
81+
return path.resolve(dir, id);
82+
}
83+
const require = createRequire(pathToFileURL(dir));
84+
try {
85+
return require.resolve(id, { paths: [dir] });
86+
} catch {
87+
return undefined;
88+
}
89+
}
90+
7291
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
7392

7493
export type OptionsResolved = Overwrite<Required<Options>, Pick<Options, 'enforce' | 'exclude'>>;
@@ -78,5 +97,6 @@ export function resolveOptions(options: Options): OptionsResolved {
7897
include: options.include || [/.*cspell(?:[-]ext)?(\..*)?\.(?:jsonc?|ya?ml|toml)$/i],
7998
exclude: options.exclude || undefined,
8099
enforce: 'enforce' in options ? options.enforce : 'pre',
100+
debug: !!options.debug,
81101
};
82102
}

packages/cspell-dictionary-bundler-plugin/src/core/options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export interface Options {
44
include?: FilterPattern | undefined;
55
exclude?: FilterPattern | undefined;
66
enforce?: 'pre' | 'post' | undefined;
7+
debug?: boolean;
78
}

packages/cspell-io/src/VirtualFS/CVirtualFS.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import type { CSpellIO } from '../CSpellIO.js';
33
import { getDefaultCSpellIO } from '../CSpellIONode.js';
44
import type { Disposable } from '../models/index.js';
55
import type { LogEvent } from '../models/LogEvent.js';
6+
import { CSPELL_VFS_PROTOCOL } from './constants.js';
67
import { CVFileSystem } from './CVFileSystem.js';
78
import { VFSErrorUnsupportedRequest } from './errors.js';
9+
import { MemFileSystemProvider } from './MemVfsProvider.js';
810
import type { UrlOrReference, VFileSystem, VFileSystemCore } from './VFileSystem.js';
911
import type { NextProvider, VFileSystemProvider, VirtualFS } from './VirtualFS.js';
1012
import { debug } from './VirtualFS.js';
@@ -161,6 +163,7 @@ export function createVirtualFS(cspellIO?: CSpellIO): VirtualFS {
161163
const cspell = cspellIO || getDefaultCSpellIO();
162164
const vfs = new CVirtualFS();
163165
vfs.registerFileSystemProvider(cspellIOToFsProvider(cspell));
166+
vfs.registerFileSystemProvider(new MemFileSystemProvider(CSPELL_VFS_PROTOCOL + 'default', CSPELL_VFS_PROTOCOL));
164167
return vfs;
165168
}
166169
let defaultVirtualFs: VirtualFS | undefined = undefined;

packages/cspell-io/src/VirtualFS/MemVfsProvider.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ export class MemVFileSystem implements VProviderFileSystem {
115115
* It is up to the provider to define what information is available.
116116
*/
117117
readonly providerInfo: FileSystemProviderInfo;
118-
readonly hasProvider: boolean = true;
119118

120119
dispose(): void {
121120
this.#files.clear();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const CSPELL_VFS_PROTOCOL = 'cspell-vfs:' as const;

packages/cspell-io/src/VirtualFS/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { CSPELL_VFS_PROTOCOL } from './constants.js';
12
export { CVFileSystem } from './CVFileSystem.js';
23
export { createVirtualFS, getDefaultVirtualFs } from './CVirtualFS.js';
34
export { VFSError, VFSErrorUnsupportedRequest, VFSNotImplemented, VFSNotSupported } from './errors.js';

packages/cspell-io/src/__snapshots__/index.test.ts.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ exports[`index > api 1`] = `
44
[
55
"CFileReference => function",
66
"CFileResource => function",
7+
"CSPELL_VFS_PROTOCOL => string",
78
"CSpellIONode => function",
89
"FSCapabilityFlags => object",
910
"VFileType => object",

packages/cspell-io/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ export type {
3030
VirtualFS,
3131
VProviderFileSystem,
3232
} from './VirtualFS/index.js';
33-
export { createRedirectProvider, createVirtualFS, FSCapabilityFlags, getDefaultVirtualFs } from './VirtualFS/index.js';
33+
export {
34+
createRedirectProvider,
35+
createVirtualFS,
36+
CSPELL_VFS_PROTOCOL,
37+
FSCapabilityFlags,
38+
getDefaultVirtualFs,
39+
} from './VirtualFS/index.js';

0 commit comments

Comments
 (0)