@markuplint/file-resolver 3.10.0 → 3.12.0

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.
@@ -3,6 +3,6 @@ import type { Ruleset, AnyMLRule } from '@markuplint/ml-core';
3
3
  * @deprecated
4
4
  */
5
5
  export declare function autoLoadRules(ruleset: Ruleset): Promise<{
6
- rules: AnyMLRule[];
7
- errors: unknown[];
6
+ rules: AnyMLRule[];
7
+ errors: unknown[];
8
8
  }>;
@@ -3,12 +3,13 @@ import type { ConfigSet } from './types';
3
3
  import type { Config } from '@markuplint/ml-config';
4
4
  import type { Nullable } from '@markuplint/shared';
5
5
  export declare class ConfigProvider {
6
- #private;
7
- resolve(targetFile: Readonly<MLFile>, names: readonly Nullable<string>[], cache?: boolean): Promise<ConfigSet>;
8
- search(targetFile: Readonly<MLFile>): Promise<string | null>;
9
- set(config: Config, key?: string): string;
10
- private _load;
11
- private _mergeConfigs;
12
- private _pathResolve;
13
- private _recursiveLoad;
6
+ #private;
7
+ resolve(targetFile: Readonly<MLFile>, names: readonly Nullable<string>[], cache?: boolean): Promise<ConfigSet>;
8
+ search(targetFile: Readonly<MLFile>): Promise<string | null>;
9
+ set(config: Config, key?: string): string;
10
+ private _load;
11
+ private _mergeConfigs;
12
+ private _pathResolve;
13
+ private _recursiveLoad;
14
+ private _validateConfig;
14
15
  }
@@ -6,6 +6,8 @@ const tslib_1 = require("tslib");
6
6
  const path_1 = tslib_1.__importDefault(require("path"));
7
7
  const ml_config_1 = require("@markuplint/ml-config");
8
8
  const ml_core_1 = require("@markuplint/ml-core");
9
+ const parser_utils_1 = require("@markuplint/parser-utils");
10
+ const selector_1 = require("@markuplint/selector");
9
11
  const shared_1 = require("@markuplint/shared");
10
12
  const cosmiconfig_1 = require("./cosmiconfig");
11
13
  const resolve_plugins_1 = require("./resolve-plugins");
@@ -32,6 +34,14 @@ class ConfigProvider {
32
34
  return currentConfig;
33
35
  }
34
36
  let configSet = await this._mergeConfigs(keys, cache);
37
+ const filePath = Array.from(configSet.files).reverse()[0];
38
+ if (!filePath) {
39
+ throw new parser_utils_1.ConfigParserError('Config file not found', {
40
+ filePath: targetFile.path,
41
+ });
42
+ }
43
+ const errors = this._validateConfig(configSet.config, filePath);
44
+ configSet.errs.push(...errors);
35
45
  const plugins = await (0, resolve_plugins_1.resolvePlugins)(configSet.config.plugins);
36
46
  if (tslib_1.__classPrivateFieldGet(this, _ConfigProvider_held, "f").size > 0) {
37
47
  const extendHelds = Array.from(tslib_1.__classPrivateFieldGet(this, _ConfigProvider_held, "f").values());
@@ -189,6 +199,26 @@ class ConfigProvider {
189
199
  stack.add(key);
190
200
  return { stack, errs };
191
201
  }
202
+ _validateConfig(config, filePath) {
203
+ var _a;
204
+ const errors = [];
205
+ (_a = config.nodeRules) === null || _a === void 0 ? void 0 : _a.forEach(rule => {
206
+ if (rule.selector) {
207
+ try {
208
+ (0, selector_1.createSelector)(rule.selector);
209
+ }
210
+ catch (error) {
211
+ if (error instanceof selector_1.InvalidSelectorError) {
212
+ errors.push(new parser_utils_1.ConfigParserError(error.message, {
213
+ filePath,
214
+ raw: rule.selector,
215
+ }));
216
+ }
217
+ }
218
+ }
219
+ });
220
+ return errors;
221
+ }
192
222
  }
193
223
  exports.ConfigProvider = ConfigProvider;
194
224
  _ConfigProvider_cache = new WeakMap(), _ConfigProvider_held = new WeakMap(), _ConfigProvider_recursiveLoadKeyAndDepth = new WeakMap(), _ConfigProvider_store = new WeakMap();
@@ -243,10 +273,15 @@ function pathResolve(dir, filePath, resolveProps, resolveKey = false) {
243
273
  return res;
244
274
  }
245
275
  function resolve(dir, pathOrModName) {
276
+ var _a, _b, _c;
246
277
  if (moduleExists(pathOrModName) || isPreset(pathOrModName) || isPlugin(pathOrModName)) {
247
278
  return pathOrModName;
248
279
  }
249
- return path_1.default.resolve(dir, pathOrModName);
280
+ const bangAndPath = (_a = /^(!)(.*)/.exec(pathOrModName)) !== null && _a !== void 0 ? _a : [];
281
+ const bang = (_b = bangAndPath[1]) !== null && _b !== void 0 ? _b : '';
282
+ const pathname = (_c = bangAndPath[2]) !== null && _c !== void 0 ? _c : pathOrModName;
283
+ const absPath = path_1.default.resolve(dir, pathname);
284
+ return bang + absPath;
250
285
  }
251
286
  function moduleExists(name) {
252
287
  try {
@@ -1,17 +1,11 @@
1
1
  import type { LoaderSync } from 'cosmiconfig';
2
2
  type CosmiConfig = ReturnType<LoaderSync>;
3
- export declare function search<T = CosmiConfig>(
4
- dir: string,
5
- cacheClear: boolean,
6
- ): Promise<{
7
- filePath: string;
8
- config: T;
3
+ export declare function search<T = CosmiConfig>(dir: string, cacheClear: boolean): Promise<{
4
+ filePath: string;
5
+ config: T;
9
6
  } | null>;
10
- export declare function load<T = CosmiConfig>(
11
- filePath: string,
12
- cacheClear: boolean,
13
- ): Promise<{
14
- filePath: string;
15
- config: T;
7
+ export declare function load<T = CosmiConfig>(filePath: string, cacheClear: boolean): Promise<{
8
+ filePath: string;
9
+ config: T;
16
10
  } | null>;
17
11
  export {};
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.load = exports.search = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const path_1 = tslib_1.__importDefault(require("path"));
6
+ const parser_utils_1 = require("@markuplint/parser-utils");
6
7
  const cosmiconfig_1 = require("cosmiconfig");
7
8
  const cosmiconfig_typescript_loader_1 = require("cosmiconfig-typescript-loader");
8
9
  const jsonc_1 = require("jsonc");
@@ -27,7 +28,7 @@ async function search(dir, cacheClear) {
27
28
  explorer.clearCaches();
28
29
  }
29
30
  dir = path_1.default.dirname(dir);
30
- const result = await explorer.search(dir);
31
+ const result = await explorer.search(dir).catch(cacheConfigError(dir));
31
32
  if (!result || result.isEmpty) {
32
33
  return null;
33
34
  }
@@ -41,7 +42,7 @@ async function load(filePath, cacheClear) {
41
42
  if (cacheClear) {
42
43
  explorer.clearCaches();
43
44
  }
44
- const result = await explorer.load(filePath);
45
+ const result = await explorer.load(filePath).catch(cacheConfigError(filePath));
45
46
  if (!result || result.isEmpty) {
46
47
  return null;
47
48
  }
@@ -51,3 +52,25 @@ async function load(filePath, cacheClear) {
51
52
  };
52
53
  }
53
54
  exports.load = load;
55
+ class ConfigLoadError extends Error {
56
+ constructor(message, filePath) {
57
+ super(message + ` in ${filePath}`);
58
+ this.name = 'ConfigLoadError';
59
+ }
60
+ }
61
+ function cacheConfigError(fileOrDirPath) {
62
+ return (reason) => {
63
+ var _a;
64
+ if (reason instanceof Error) {
65
+ switch (reason.name) {
66
+ case 'YAMLException':
67
+ throw new parser_utils_1.ConfigParserError(reason.message, {
68
+ // @ts-ignore
69
+ filePath: (_a = reason.filepath) !== null && _a !== void 0 ? _a : fileOrDirPath,
70
+ });
71
+ }
72
+ throw new ConfigLoadError(reason.message, fileOrDirPath);
73
+ }
74
+ throw reason;
75
+ };
76
+ }
@@ -1,23 +1,24 @@
1
1
  import type { Target } from '../types';
2
2
  export declare class MLFile {
3
- #private;
4
- constructor(target: Target);
5
- get dirname(): string;
6
- /**
7
- * Normalized `MLFile.dirname`
8
- */
9
- get nDirname(): string;
10
- /**
11
- * Normalized `MLFile.path`
12
- */
13
- get nPath(): string;
14
- get path(): string;
15
- dirExists(): Promise<boolean>;
16
- getCode(): Promise<string>;
17
- isExist(): Promise<boolean>;
18
- isFile(): Promise<boolean>;
19
- matches(globPath: string): boolean;
20
- setCode(code: string): void;
21
- private _fetch;
22
- private _stat;
3
+ #private;
4
+ constructor(target: Target);
5
+ get dirname(): string;
6
+ /**
7
+ * Normalized `MLFile.dirname`
8
+ */
9
+ get nDirname(): string;
10
+ /**
11
+ * Normalized `MLFile.path`
12
+ */
13
+ get nPath(): string;
14
+ get path(): string;
15
+ dirExists(): Promise<boolean>;
16
+ getCode(): Promise<string>;
17
+ ignored(globPath: string | readonly string[]): boolean;
18
+ isExist(): Promise<boolean>;
19
+ isFile(): Promise<boolean>;
20
+ matches(globPath: string): boolean;
21
+ setCode(code: string): void;
22
+ private _fetch;
23
+ private _stat;
23
24
  }
@@ -5,6 +5,7 @@ exports.MLFile = void 0;
5
5
  const tslib_1 = require("tslib");
6
6
  const fs_1 = require("fs");
7
7
  const path_1 = tslib_1.__importDefault(require("path"));
8
+ const ignore_1 = tslib_1.__importDefault(require("ignore"));
8
9
  const minimatch_1 = require("minimatch");
9
10
  class MLFile {
10
11
  constructor(target) {
@@ -67,6 +68,13 @@ class MLFile {
67
68
  }
68
69
  return '';
69
70
  }
71
+ ignored(globPath) {
72
+ globPath = typeof globPath === 'string' ? [globPath] : globPath;
73
+ const normalizedPaths = globPath.map(p => pathNormalize(p, true));
74
+ const ig = (0, ignore_1.default)().add(normalizedPaths);
75
+ const ignored = ig.ignores(pathNormalize(this.nPath, true));
76
+ return ignored;
77
+ }
70
78
  async isExist() {
71
79
  if (tslib_1.__classPrivateFieldGet(this, _MLFile_type, "f") === 'code-base') {
72
80
  return true;
@@ -120,12 +128,22 @@ async function stat(filePath) {
120
128
  throw err;
121
129
  }
122
130
  }
123
- function pathNormalize(filePath) {
131
+ function pathNormalize(filePath, relative = false) {
132
+ const hasBang = filePath.startsWith('!');
133
+ if (hasBang) {
134
+ filePath = filePath.slice(1);
135
+ }
124
136
  // Remove the local disk scheme of Windows OS
125
137
  if (path_1.default.isAbsolute(filePath)) {
126
138
  filePath = filePath.replace(/^[a-z]+:/i, '');
139
+ if (relative) {
140
+ filePath = path_1.default.relative(path_1.default.sep, filePath);
141
+ }
127
142
  }
128
143
  // Replace the separator of Windows OS
129
144
  filePath = filePath.split(path_1.default.sep).join('/');
145
+ if (hasBang) {
146
+ filePath = `!${filePath}`;
147
+ }
130
148
  return filePath;
131
149
  }
@@ -1,13 +1,9 @@
1
1
  import type { MLFile } from './ml-file';
2
2
  import type { MLMarkupLanguageParser, ParserOptions } from '@markuplint/ml-ast';
3
3
  import type { ParserConfig } from '@markuplint/ml-config';
4
- export declare function resolveParser(
5
- file: Readonly<MLFile>,
6
- parserConfig?: ParserConfig,
7
- parserOptions?: ParserOptions,
8
- ): Promise<{
9
- parserModName: string;
10
- parser: MLMarkupLanguageParser;
11
- parserOptions: ParserOptions;
12
- matched: boolean;
4
+ export declare function resolveParser(file: Readonly<MLFile>, parserConfig?: ParserConfig, parserOptions?: ParserOptions): Promise<{
5
+ parserModName: string;
6
+ parser: MLMarkupLanguageParser;
7
+ parserOptions: ParserOptions;
8
+ matched: boolean;
13
9
  }>;
@@ -1,10 +1,6 @@
1
1
  import type { AnyMLRule, Ruleset, Plugin } from '@markuplint/ml-core';
2
- export declare function resolveRules(
3
- plugins: readonly Plugin[],
4
- ruleset: Ruleset,
5
- importPreset: boolean,
6
- /**
7
- * @deprecated
8
- */
9
- autoLoad: boolean,
10
- ): Promise<Readonly<AnyMLRule>[]>;
2
+ export declare function resolveRules(plugins: readonly Plugin[], ruleset: Ruleset, importPreset: boolean,
3
+ /**
4
+ * @deprecated
5
+ */
6
+ autoLoad: boolean): Promise<Readonly<AnyMLRule>[]>;
@@ -30,9 +30,6 @@ import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
30
30
  * @param specConfig The `spec` property part of the config
31
31
  * @returns
32
32
  */
33
- export declare function resolveSpecs(
34
- filePath: string,
35
- specConfig?: SpecConfig,
36
- ): Promise<{
37
- schemas: readonly [MLMLSpec, ...ExtendedSpec[]];
33
+ export declare function resolveSpecs(filePath: string, specConfig?: SpecConfig): Promise<{
34
+ schemas: readonly [MLMLSpec, ...ExtendedSpec[]];
38
35
  }>;
package/lib/types.d.ts CHANGED
@@ -1,24 +1,22 @@
1
1
  import type { Config } from '@markuplint/ml-config';
2
2
  import type { Plugin } from '@markuplint/ml-core';
3
3
  export interface ConfigSet {
4
- readonly config: Config;
5
- readonly plugins: readonly Plugin[];
6
- readonly files: ReadonlySet<string>;
7
- readonly errs: readonly Readonly<Error>[];
4
+ readonly config: Config;
5
+ readonly plugins: readonly Plugin[];
6
+ readonly files: ReadonlySet<string>;
7
+ readonly errs: readonly Readonly<Error>[];
8
8
  }
9
- export type Target =
10
- | string
11
- | {
12
- /**
13
- * Target source code of evaluation
14
- */
15
- readonly sourceCode: string;
16
- /**
17
- * File names when `sourceCodes`
18
- */
19
- readonly name?: string;
20
- /**
21
- * Workspace path when `sourceCodes`
22
- */
23
- readonly workspace?: string;
24
- };
9
+ export type Target = string | {
10
+ /**
11
+ * Target source code of evaluation
12
+ */
13
+ readonly sourceCode: string;
14
+ /**
15
+ * File names when `sourceCodes`
16
+ */
17
+ readonly name?: string;
18
+ /**
19
+ * Workspace path when `sourceCodes`
20
+ */
21
+ readonly workspace?: string;
22
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/file-resolver",
3
- "version": "3.10.0",
3
+ "version": "3.12.0",
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>",
@@ -19,21 +19,24 @@
19
19
  "clean": "tsc --build --clean"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/node": "20.0.0"
22
+ "@types/node": "20.4.1"
23
23
  },
24
24
  "dependencies": {
25
- "@markuplint/html-parser": "3.8.0",
26
- "@markuplint/ml-ast": "3.1.0",
27
- "@markuplint/ml-config": "3.9.0",
28
- "@markuplint/ml-core": "3.10.0",
29
- "@markuplint/ml-spec": "3.9.0",
30
- "@markuplint/shared": "3.6.0",
31
- "cosmiconfig": "^8.1.3",
25
+ "@markuplint/html-parser": "3.10.0",
26
+ "@markuplint/ml-ast": "3.2.0",
27
+ "@markuplint/ml-config": "3.11.0",
28
+ "@markuplint/ml-core": "3.12.0",
29
+ "@markuplint/ml-spec": "3.11.0",
30
+ "@markuplint/parser-utils": "3.10.0",
31
+ "@markuplint/selector": "3.11.0",
32
+ "@markuplint/shared": "3.8.0",
33
+ "cosmiconfig": "^8.2.0",
32
34
  "cosmiconfig-typescript-loader": "^4.3.0",
33
- "glob": "^10.2.2",
35
+ "glob": "^10.3.2",
36
+ "ignore": "^5.2.4",
34
37
  "jsonc": "^2.0.0",
35
- "minimatch": "^9.0.0",
36
- "tslib": "^2.5.0"
38
+ "minimatch": "^9.0.3",
39
+ "tslib": "^2.6.0"
37
40
  },
38
- "gitHead": "af370797bfc887e5a5a2ff57fbaa8392ac98ead2"
41
+ "gitHead": "4ab20276db48a6acb29a923ea8666890ca853442"
39
42
  }