@markuplint/file-resolver 5.0.0-alpha.0 → 5.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/lib/force-import-json-in-module.js +2 -6
- package/lib/general-import.js +3 -1
- package/lib/ml-file/get-files.js +3 -2
- package/lib/ml-file/ml-file.js +6 -24
- package/lib/path-utils.d.ts +19 -0
- package/lib/path-utils.js +46 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [5.0.0-alpha.2](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.1...v5.0.0-alpha.2) (2026-02-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @markuplint/file-resolver
|
|
9
|
+
|
|
10
|
+
# [5.0.0-alpha.1](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.0...v5.0.0-alpha.1) (2026-02-22)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **file-resolver:** fix matches() normalization asymmetry and harden tests ([4651df9](https://github.com/markuplint/markuplint/commit/4651df9679427755a3848937b3b8f5546cb04371))
|
|
15
|
+
- **file-resolver:** fix Windows path normalization for non-C: drives ([f31a942](https://github.com/markuplint/markuplint/commit/f31a9427fc417f444df26ad1a931d4df5957f29f)), closes [#1806](https://github.com/markuplint/markuplint/issues/1806)
|
|
16
|
+
- **file-resolver:** skip platform-specific fromFileURL tests per OS ([4c05356](https://github.com/markuplint/markuplint/commit/4c0535657a748d63f7832efeb3d33b43e5b8e081))
|
|
17
|
+
|
|
6
18
|
# [5.0.0-alpha.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v5.0.0-alpha.0) (2026-02-20)
|
|
7
19
|
|
|
8
20
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { log } from './debug.js';
|
|
3
|
+
import { fromFileURL } from './path-utils.js';
|
|
4
4
|
const fLog = log.extend('force-import-json-in-module');
|
|
5
5
|
export async function forceImportJsonInModule(modPath) {
|
|
6
6
|
const error = await import(modPath).catch(error => error);
|
|
@@ -18,11 +18,7 @@ export async function forceImportJsonInModule(modPath) {
|
|
|
18
18
|
if (!absPath) {
|
|
19
19
|
return error;
|
|
20
20
|
}
|
|
21
|
-
const normalizePath = absPath
|
|
22
|
-
.replace(/^file:\/\//, '')
|
|
23
|
-
.replaceAll('/', path.sep)
|
|
24
|
-
// Windows
|
|
25
|
-
.replace(/^[/\\](?=[a-z]:)/i, ''); // only remove a leading slash
|
|
21
|
+
const normalizePath = absPath.startsWith('file:') ? fromFileURL(absPath) : absPath;
|
|
26
22
|
fLog('Find JSON file path: %s', normalizePath);
|
|
27
23
|
const fileContent = await readFile(normalizePath, { encoding: 'utf8' });
|
|
28
24
|
return JSON.parse(fileContent);
|
package/lib/general-import.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
5
|
import { resolve } from 'import-meta-resolve';
|
|
6
6
|
import { log } from './debug.js';
|
|
7
|
+
import { fromFileURL } from './path-utils.js';
|
|
7
8
|
const gLog = log.extend('general-import');
|
|
8
9
|
const gLogSuccess = gLog.extend('success');
|
|
9
10
|
const gLogError = gLog.extend('error');
|
|
@@ -53,7 +54,8 @@ export async function generalImport(name) {
|
|
|
53
54
|
?.groups ?? {};
|
|
54
55
|
if (filePath && packageName) {
|
|
55
56
|
const modFile = resolve(packageName, import.meta.url);
|
|
56
|
-
const
|
|
57
|
+
const modNativePath = modFile.startsWith('file:') ? fromFileURL(modFile) : modFile;
|
|
58
|
+
const modPath = path.dirname(modNativePath);
|
|
57
59
|
const candidate = path.join(modPath, filePath);
|
|
58
60
|
gLog('Try import absolute path: "%s"', candidate);
|
|
59
61
|
const result = await generalImport(candidate);
|
package/lib/ml-file/get-files.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { glob } from 'glob';
|
|
2
2
|
import { minimatch } from 'minimatch';
|
|
3
|
+
import { normalizeForGlob } from '../path-utils.js';
|
|
3
4
|
import { getFile } from './get-file.js';
|
|
4
5
|
/**
|
|
5
6
|
* Get files
|
|
@@ -9,7 +10,7 @@ import { getFile } from './get-file.js';
|
|
|
9
10
|
* @param filePathOrGlob
|
|
10
11
|
*/
|
|
11
12
|
export async function getFiles(filePathOrGlob, ignoreGlob) {
|
|
12
|
-
const fileList = await glob(filePathOrGlob, {}).catch(() => []);
|
|
13
|
-
const filtered = fileList.filter(fileName => !minimatch(fileName, ignoreGlob ?? ''));
|
|
13
|
+
const fileList = await glob(normalizeForGlob(filePathOrGlob), {}).catch(() => []);
|
|
14
|
+
const filtered = fileList.filter(fileName => !minimatch(fileName, normalizeForGlob(ignoreGlob ?? '')));
|
|
14
15
|
return filtered.map(fileName => getFile(fileName));
|
|
15
16
|
}
|
package/lib/ml-file/ml-file.js
CHANGED
|
@@ -2,6 +2,7 @@ import { promises as fs } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import ignore from 'ignore';
|
|
4
4
|
import { minimatch } from 'minimatch';
|
|
5
|
+
import { normalizeForIgnore } from '../path-utils.js';
|
|
5
6
|
export class MLFile {
|
|
6
7
|
#basename;
|
|
7
8
|
#code;
|
|
@@ -39,13 +40,13 @@ export class MLFile {
|
|
|
39
40
|
* Normalized `MLFile.dirname`
|
|
40
41
|
*/
|
|
41
42
|
get nDirname() {
|
|
42
|
-
return
|
|
43
|
+
return normalizeForIgnore(this.dirname);
|
|
43
44
|
}
|
|
44
45
|
/**
|
|
45
46
|
* Normalized `MLFile.path`
|
|
46
47
|
*/
|
|
47
48
|
get nPath() {
|
|
48
|
-
return
|
|
49
|
+
return normalizeForIgnore(this.path);
|
|
49
50
|
}
|
|
50
51
|
get path() {
|
|
51
52
|
return path.resolve(this.#dirname, this.#basename);
|
|
@@ -64,10 +65,10 @@ export class MLFile {
|
|
|
64
65
|
}
|
|
65
66
|
ignored(globPath) {
|
|
66
67
|
globPath = typeof globPath === 'string' ? [globPath] : globPath;
|
|
67
|
-
const normalizedPaths = globPath.map(p =>
|
|
68
|
+
const normalizedPaths = globPath.map(p => normalizeForIgnore(p, true));
|
|
68
69
|
// @ts-ignore
|
|
69
70
|
const ig = ignore().add(normalizedPaths);
|
|
70
|
-
const ignored = ig.ignores(
|
|
71
|
+
const ignored = ig.ignores(normalizeForIgnore(this.path, true));
|
|
71
72
|
return ignored;
|
|
72
73
|
}
|
|
73
74
|
async isExist() {
|
|
@@ -85,7 +86,7 @@ export class MLFile {
|
|
|
85
86
|
return !!stat && stat.isFile();
|
|
86
87
|
}
|
|
87
88
|
matches(globPath) {
|
|
88
|
-
return minimatch(this.
|
|
89
|
+
return minimatch(normalizeForIgnore(this.path), normalizeForIgnore(globPath));
|
|
89
90
|
}
|
|
90
91
|
setCode(code) {
|
|
91
92
|
if (this.#type === 'file-base') {
|
|
@@ -121,22 +122,3 @@ async function stat(filePath) {
|
|
|
121
122
|
throw error;
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
function pathNormalize(filePath, relative = false) {
|
|
125
|
-
const hasBang = filePath.startsWith('!');
|
|
126
|
-
if (hasBang) {
|
|
127
|
-
filePath = filePath.slice(1);
|
|
128
|
-
}
|
|
129
|
-
// Remove the local disk scheme of Windows OS
|
|
130
|
-
if (path.isAbsolute(filePath)) {
|
|
131
|
-
filePath = filePath.replace(/^[a-z]+:/i, '');
|
|
132
|
-
if (relative) {
|
|
133
|
-
filePath = path.relative(path.sep, filePath);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// Replace the separator of Windows OS
|
|
137
|
-
filePath = filePath.split(path.sep).join('/');
|
|
138
|
-
if (hasBang) {
|
|
139
|
-
filePath = `!${filePath}`;
|
|
140
|
-
}
|
|
141
|
-
return filePath;
|
|
142
|
-
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert OS-native separators to forward slashes.
|
|
3
|
+
* Identity function on POSIX.
|
|
4
|
+
*/
|
|
5
|
+
export declare function toSlash(filePath: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Convert a `file://` URL to a native file path using Node.js built-in.
|
|
8
|
+
* Correctly handles URL encoding, UNC paths, and all drive letters.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fromFileURL(fileUrl: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a path for the `ignore` library (gitignore-style matching).
|
|
13
|
+
* Removes drive letters, converts to forward slashes, and optionally makes relative.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeForIgnore(filePath: string, relative?: boolean): string;
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a path for glob libraries (forward slashes required).
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeForGlob(filePath: string): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* Convert OS-native separators to forward slashes.
|
|
5
|
+
* Identity function on POSIX.
|
|
6
|
+
*/
|
|
7
|
+
export function toSlash(filePath) {
|
|
8
|
+
return filePath.replaceAll('\\', '/');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Convert a `file://` URL to a native file path using Node.js built-in.
|
|
12
|
+
* Correctly handles URL encoding, UNC paths, and all drive letters.
|
|
13
|
+
*/
|
|
14
|
+
export function fromFileURL(fileUrl) {
|
|
15
|
+
return fileURLToPath(fileUrl);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Normalize a path for the `ignore` library (gitignore-style matching).
|
|
19
|
+
* Removes drive letters, converts to forward slashes, and optionally makes relative.
|
|
20
|
+
*/
|
|
21
|
+
export function normalizeForIgnore(filePath, relative = false) {
|
|
22
|
+
const hasBang = filePath.startsWith('!');
|
|
23
|
+
if (hasBang) {
|
|
24
|
+
filePath = filePath.slice(1);
|
|
25
|
+
}
|
|
26
|
+
// Remove the local disk scheme of Windows OS (e.g. "C:", "P:")
|
|
27
|
+
if (path.isAbsolute(filePath) || /^[a-z]:/i.test(filePath)) {
|
|
28
|
+
filePath = filePath.replace(/^[a-z]:/i, '');
|
|
29
|
+
}
|
|
30
|
+
// Convert backslashes to forward slashes
|
|
31
|
+
filePath = toSlash(filePath);
|
|
32
|
+
if (relative) {
|
|
33
|
+
// Strip leading slashes to make the path relative
|
|
34
|
+
filePath = filePath.replace(/^\/+/, '');
|
|
35
|
+
}
|
|
36
|
+
if (hasBang) {
|
|
37
|
+
filePath = `!${filePath}`;
|
|
38
|
+
}
|
|
39
|
+
return filePath;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a path for glob libraries (forward slashes required).
|
|
43
|
+
*/
|
|
44
|
+
export function normalizeForGlob(filePath) {
|
|
45
|
+
return toSlash(filePath);
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/file-resolver",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.2",
|
|
4
4
|
"description": "The file resolver of markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"@types/node": "24.5.1"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@markuplint/html-parser": "5.0.0-alpha.
|
|
34
|
-
"@markuplint/ml-ast": "5.0.0-alpha.
|
|
35
|
-
"@markuplint/ml-config": "5.0.0-alpha.
|
|
36
|
-
"@markuplint/ml-core": "5.0.0-alpha.
|
|
37
|
-
"@markuplint/ml-spec": "5.0.0-alpha.
|
|
38
|
-
"@markuplint/parser-utils": "5.0.0-alpha.
|
|
39
|
-
"@markuplint/selector": "5.0.0-alpha.
|
|
40
|
-
"@markuplint/shared": "5.0.0-alpha.
|
|
33
|
+
"@markuplint/html-parser": "5.0.0-alpha.2",
|
|
34
|
+
"@markuplint/ml-ast": "5.0.0-alpha.2",
|
|
35
|
+
"@markuplint/ml-config": "5.0.0-alpha.2",
|
|
36
|
+
"@markuplint/ml-core": "5.0.0-alpha.2",
|
|
37
|
+
"@markuplint/ml-spec": "5.0.0-alpha.2",
|
|
38
|
+
"@markuplint/parser-utils": "5.0.0-alpha.2",
|
|
39
|
+
"@markuplint/selector": "5.0.0-alpha.2",
|
|
40
|
+
"@markuplint/shared": "5.0.0-alpha.2",
|
|
41
41
|
"cosmiconfig": "9.0.0",
|
|
42
42
|
"debug": "4.4.3",
|
|
43
43
|
"glob": "13.0.6",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"jsonc": "2.0.0",
|
|
47
47
|
"minimatch": "10.2.2"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "31ccf1e81443ea3f93597d287595211f1823ddcf"
|
|
50
50
|
}
|