@brnshkr/config 0.0.1-beta.2 → 0.0.1-beta.4
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/README.md +177 -228
- package/conf/.gitignore.dist +15 -0
- package/conf/Makefile +3778 -0
- package/conf/Makefile.dist +13 -0
- package/conf/bunfig.dist.toml +5 -0
- package/conf/commitlint.dist.mjs +1 -0
- package/conf/editorconfig.dist +19 -0
- package/conf/launch.dist.json +31 -0
- package/conf/markdownlint.dist.mjs +1 -0
- package/conf/spelling/defaults.json +185 -0
- package/conf/tsconfig.dist.json +3 -0
- package/conf/tsconfig.json +31 -27
- package/conf/vitest.dist.mjs +1 -0
- package/conf/vscode-css-custom-data.dist.json +95 -0
- package/conf/vscode-extensions.dist.json +21 -0
- package/conf/vscode-settings.dist.jsonc +338 -0
- package/dist/commitlint/index.d.mts +72 -0
- package/dist/commitlint/index.mjs +239 -0
- package/dist/eslint/index.d.mts +3897 -1383
- package/dist/eslint/index.mjs +2784 -419
- package/dist/markdownlint/index.d.mts +2304 -0
- package/dist/markdownlint/index.mjs +440 -0
- package/dist/shared.mjs +405 -65
- package/dist/spelling/index.d.mts +30 -0
- package/dist/spelling/index.mjs +2 -0
- package/dist/spelling/spelling.test.d.mts +1 -0
- package/dist/spelling/spelling.test.mjs +12 -0
- package/dist/stylelint/index.d.mts +47 -9
- package/dist/stylelint/index.mjs +145 -47
- package/dist/vitest/index.d.mts +73 -0
- package/dist/vitest/index.mjs +181 -0
- package/package.json +192 -105
- package/conf/tsconfig.json.example +0 -3
- package/dist/scripts/eslint.mjs +0 -16
- package/dist/scripts/stylelint.mjs +0 -29
- /package/conf/{eslint.config.mjs.example → eslint.dist.mjs} +0 -0
- /package/conf/{stylelint.config.mjs.example → stylelint.dist.mjs} +0 -0
package/dist/shared.mjs
CHANGED
|
@@ -1,38 +1,52 @@
|
|
|
1
1
|
import { isPackageExists } from "local-pkg";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
2
5
|
//#region ../package.json
|
|
3
6
|
var name = "@brnshkr/config";
|
|
4
|
-
var version = "0.0.1-beta.
|
|
7
|
+
var version = "0.0.1-beta.4";
|
|
5
8
|
//#endregion
|
|
6
9
|
//#region ../src/js/shared/utils/package-json.ts
|
|
7
|
-
|
|
10
|
+
/**
|
|
11
|
+
* @internal @brnshkr/config
|
|
12
|
+
*/
|
|
13
|
+
const packageOrganizationInternal = name.split("/", 1).at(0)?.replace(/^@/v, "");
|
|
8
14
|
if (packageOrganizationInternal === void 0 || packageOrganizationInternal.length === 0) throw new Error("Failed to read package organization from package.json file.");
|
|
9
15
|
const packageOrganization = packageOrganizationInternal;
|
|
10
16
|
const packageOrganizationUpper = packageOrganizationInternal.toUpperCase();
|
|
11
17
|
//#endregion
|
|
12
18
|
//#region ../src/js/shared/utils/log.ts
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @internal @brnshkr/config
|
|
21
|
+
*/
|
|
22
|
+
const log = (message) => {
|
|
23
|
+
console.error(`[${name}] ${message}`);
|
|
16
24
|
};
|
|
17
25
|
//#endregion
|
|
18
26
|
//#region ../src/js/shared/utils/object.ts
|
|
19
27
|
const objectKeys = (object) => Object.keys(object);
|
|
28
|
+
const objectValues = (object) => Object.values(object);
|
|
20
29
|
const objectEntries = (object) => Object.entries(object);
|
|
21
30
|
const objectFromEntries = (entries) => Object.fromEntries(entries);
|
|
22
|
-
const objectFreeze = (object) => Object.freeze(object);
|
|
23
31
|
const objectAssign = (target, source) => Object.assign(target, source);
|
|
32
|
+
const isPlainObject = (value) => {
|
|
33
|
+
if (typeof value !== "object" || !value) return false;
|
|
34
|
+
return (Object.getPrototypeOf(value) ?? Object.prototype) === Object.prototype;
|
|
35
|
+
};
|
|
24
36
|
//#endregion
|
|
25
37
|
//#region ../src/js/shared/utils/interop-import.ts
|
|
26
38
|
const interopImport = async (thePackage) => {
|
|
27
39
|
const resolved = await thePackage;
|
|
28
|
-
return typeof resolved === "object" && resolved
|
|
40
|
+
return typeof resolved === "object" && resolved && "default" in resolved ? resolved.default : resolved;
|
|
29
41
|
};
|
|
30
42
|
//#endregion
|
|
31
43
|
//#region ../src/js/shared/utils/package-resolvers.ts
|
|
44
|
+
/**
|
|
45
|
+
* @internal @brnshkr/config
|
|
46
|
+
*/
|
|
32
47
|
const ESLINT_PACKAGES = {
|
|
33
48
|
ESLINT_CSS: "@eslint/css",
|
|
34
|
-
|
|
35
|
-
ESLINT_IMPORT_RESOVLER_TYPESCRIPT: "eslint-import-resolver-typescript",
|
|
49
|
+
ESLINT_IMPORT_RESOLVER_TYPESCRIPT: "eslint-import-resolver-typescript",
|
|
36
50
|
ESLINT_JSON: "@eslint/json",
|
|
37
51
|
ESLINT_MARKDOWN: "@eslint/markdown",
|
|
38
52
|
ESLINT_MERGE_PROCESSORS: "eslint-merge-processors",
|
|
@@ -52,47 +66,74 @@ const ESLINT_PACKAGES = {
|
|
|
52
66
|
ESLINT_PLUGIN_UNUSED_IMPORTS: "eslint-plugin-unused-imports",
|
|
53
67
|
ESLINT_PLUGIN_YML: "eslint-plugin-yml",
|
|
54
68
|
SVELTE: "svelte",
|
|
69
|
+
TAILWINDCSS: "tailwindcss",
|
|
55
70
|
TYPESCRIPT: "typescript",
|
|
56
71
|
TYPESCRIPT_ESLINT: "typescript-eslint",
|
|
57
72
|
VITEST_ESLINT_PLUGIN: "@vitest/eslint-plugin"
|
|
58
73
|
};
|
|
59
74
|
const ESLINT_PACKAGE_RESOLVERS = {
|
|
60
|
-
[ESLINT_PACKAGES.ESLINT_CSS]: async () =>
|
|
61
|
-
[ESLINT_PACKAGES.
|
|
62
|
-
[ESLINT_PACKAGES.
|
|
63
|
-
[ESLINT_PACKAGES.
|
|
64
|
-
[ESLINT_PACKAGES.
|
|
65
|
-
[ESLINT_PACKAGES.
|
|
66
|
-
[ESLINT_PACKAGES.
|
|
67
|
-
[ESLINT_PACKAGES.
|
|
68
|
-
[ESLINT_PACKAGES.
|
|
69
|
-
[ESLINT_PACKAGES.
|
|
70
|
-
[ESLINT_PACKAGES.
|
|
71
|
-
[ESLINT_PACKAGES.
|
|
72
|
-
[ESLINT_PACKAGES.
|
|
73
|
-
[ESLINT_PACKAGES.
|
|
74
|
-
[ESLINT_PACKAGES.
|
|
75
|
-
[ESLINT_PACKAGES.
|
|
76
|
-
[ESLINT_PACKAGES.
|
|
77
|
-
[ESLINT_PACKAGES.
|
|
78
|
-
[ESLINT_PACKAGES.
|
|
79
|
-
[ESLINT_PACKAGES.
|
|
80
|
-
[ESLINT_PACKAGES.ESLINT_PLUGIN_YML]: async () => await interopImport(import("eslint-plugin-yml")),
|
|
75
|
+
[ESLINT_PACKAGES.ESLINT_CSS]: async () => interopImport(import("@eslint/css")),
|
|
76
|
+
[ESLINT_PACKAGES.ESLINT_JSON]: async () => interopImport(import("@eslint/json")),
|
|
77
|
+
[ESLINT_PACKAGES.ESLINT_IMPORT_RESOLVER_TYPESCRIPT]: async () => interopImport(import("eslint-import-resolver-typescript")),
|
|
78
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_ANTFU]: async () => interopImport(import("eslint-plugin-antfu")),
|
|
79
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_ESLINT_COMMENTS]: async () => interopImport(import("@eslint-community/eslint-plugin-eslint-comments")),
|
|
80
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_IMPORT_X]: async () => interopImport(import("eslint-plugin-import-x")),
|
|
81
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_JSDOC]: async () => interopImport(import("eslint-plugin-jsdoc")),
|
|
82
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_JSONC]: async () => interopImport(import("eslint-plugin-jsonc")),
|
|
83
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_JSDOC_PROCESSOR]: async () => interopImport(import("eslint-plugin-jsdoc/getJsdocProcessorPlugin.js")),
|
|
84
|
+
[ESLINT_PACKAGES.ESLINT_MARKDOWN]: async () => interopImport(import("@eslint/markdown")),
|
|
85
|
+
[ESLINT_PACKAGES.ESLINT_MERGE_PROCESSORS]: async () => interopImport(import("eslint-merge-processors")),
|
|
86
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_N]: async () => interopImport(import("eslint-plugin-n")),
|
|
87
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_PERFECTIONIST]: async () => interopImport(import("eslint-plugin-perfectionist")),
|
|
88
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_REGEXP]: async () => interopImport(import("eslint-plugin-regexp")),
|
|
89
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_STYLISTIC]: async () => interopImport(import("@stylistic/eslint-plugin")),
|
|
90
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_SVELTE]: async () => interopImport(import("eslint-plugin-svelte")),
|
|
91
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_TOML]: async () => interopImport(import("eslint-plugin-toml")),
|
|
92
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_UNICORN]: async () => interopImport(import("eslint-plugin-unicorn")),
|
|
93
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_UNUSED_IMPORTS]: async () => interopImport(import("eslint-plugin-unused-imports")),
|
|
94
|
+
[ESLINT_PACKAGES.ESLINT_PLUGIN_YML]: async () => interopImport(import("eslint-plugin-yml")),
|
|
81
95
|
[ESLINT_PACKAGES.SVELTE]: () => isPackageExists(ESLINT_PACKAGES.SVELTE),
|
|
96
|
+
[ESLINT_PACKAGES.TAILWINDCSS]: () => isPackageExists(ESLINT_PACKAGES.TAILWINDCSS),
|
|
82
97
|
[ESLINT_PACKAGES.TYPESCRIPT]: () => isPackageExists(ESLINT_PACKAGES.TYPESCRIPT),
|
|
83
|
-
[ESLINT_PACKAGES.TYPESCRIPT_ESLINT]: async () =>
|
|
84
|
-
[ESLINT_PACKAGES.VITEST_ESLINT_PLUGIN]: async () =>
|
|
98
|
+
[ESLINT_PACKAGES.TYPESCRIPT_ESLINT]: async () => interopImport(import("typescript-eslint")),
|
|
99
|
+
[ESLINT_PACKAGES.VITEST_ESLINT_PLUGIN]: async () => interopImport(import("@vitest/eslint-plugin"))
|
|
100
|
+
};
|
|
101
|
+
const COMMITLINT_PACKAGES = {
|
|
102
|
+
COMMITLINT_CONFIG_CONVENTIONAL: "@commitlint/config-conventional",
|
|
103
|
+
COMMITLINT_PLUGIN_FUNCTION_RULES: "commitlint-plugin-function-rules",
|
|
104
|
+
COMMITLINT_PLUGIN_TENSE: "commitlint-plugin-tense"
|
|
105
|
+
};
|
|
106
|
+
const COMMITLINT_PACKAGE_RESOLVERS = {
|
|
107
|
+
[COMMITLINT_PACKAGES.COMMITLINT_CONFIG_CONVENTIONAL]: () => isPackageExists(COMMITLINT_PACKAGES.COMMITLINT_CONFIG_CONVENTIONAL),
|
|
108
|
+
[COMMITLINT_PACKAGES.COMMITLINT_PLUGIN_FUNCTION_RULES]: () => isPackageExists(COMMITLINT_PACKAGES.COMMITLINT_PLUGIN_FUNCTION_RULES),
|
|
109
|
+
[COMMITLINT_PACKAGES.COMMITLINT_PLUGIN_TENSE]: () => isPackageExists(COMMITLINT_PACKAGES.COMMITLINT_PLUGIN_TENSE)
|
|
110
|
+
};
|
|
111
|
+
const MARKDOWNLINT_PACKAGES = {
|
|
112
|
+
MARKDOWNLINT_GITHUB: "@github/markdownlint-github",
|
|
113
|
+
MARKDOWNLINT_RULES: "@hongminhee/markdownlint-rules",
|
|
114
|
+
MARKDOWNLINT_RULE_NO_TRAILING_SLASH_IN_LINKS: "markdownlint-rule-no-trailing-slash-in-links",
|
|
115
|
+
MARKDOWNLINT_RULE_RELATIVE_LINKS: "markdownlint-rule-relative-links",
|
|
116
|
+
MARKDOWNLINT_RULE_SEARCH_REPLACE: "markdownlint-rule-search-replace",
|
|
117
|
+
MARKDOWNLINT_RULE_TABLE_FORMAT: "markdownlint-rule-table-format"
|
|
118
|
+
};
|
|
119
|
+
const MARKDOWNLINT_PACKAGE_RESOLVERS = {
|
|
120
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_GITHUB]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_GITHUB),
|
|
121
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULES]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULES),
|
|
122
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_NO_TRAILING_SLASH_IN_LINKS]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_NO_TRAILING_SLASH_IN_LINKS),
|
|
123
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_RELATIVE_LINKS]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_RELATIVE_LINKS),
|
|
124
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_SEARCH_REPLACE]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_SEARCH_REPLACE),
|
|
125
|
+
[MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_TABLE_FORMAT]: () => isPackageExists(MARKDOWNLINT_PACKAGES.MARKDOWNLINT_RULE_TABLE_FORMAT)
|
|
85
126
|
};
|
|
86
127
|
const STYLELINT_PACKAGES = {
|
|
87
128
|
POSTCSS_HTML: "postcss-html",
|
|
88
129
|
STYLELINT_CONFIG_CSS_MODULES: "stylelint-config-css-modules",
|
|
89
130
|
STYLELINT_CONFIG_HTML: "stylelint-config-html",
|
|
90
131
|
STYLELINT_CONFIG_RECESS_ORDER: "stylelint-config-recess-order",
|
|
132
|
+
STYLELINT_CONFIG_STANDARD_LESS: "stylelint-config-standard-less",
|
|
91
133
|
STYLELINT_CONFIG_STANDARD_SCSS: "stylelint-config-standard-scss",
|
|
92
134
|
STYLELINT_DECLARATION_STRICT_VALUE: "stylelint-declaration-strict-value",
|
|
93
135
|
STYLELINT_ORDER: "stylelint-order",
|
|
94
136
|
STYLELINT_PLUGIN_DEFENSIVE_CSS: "stylelint-plugin-defensive-css",
|
|
95
|
-
STYLELINT_PLUGIN_LOGICAL_CSS: "stylelint-plugin-logical-css",
|
|
96
137
|
STYLELINT_PLUGIN_USE_BASELINE: "stylelint-plugin-use-baseline",
|
|
97
138
|
STYLELINT_USE_NESTING: "stylelint-use-nesting",
|
|
98
139
|
STYLISTIC_STYLELINT_CONFIG: "@stylistic/stylelint-config"
|
|
@@ -102,51 +143,98 @@ const STYLELINT_PACKAGE_RESOLVERS = {
|
|
|
102
143
|
[STYLELINT_PACKAGES.STYLELINT_CONFIG_CSS_MODULES]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_CONFIG_CSS_MODULES),
|
|
103
144
|
[STYLELINT_PACKAGES.STYLELINT_CONFIG_HTML]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_CONFIG_HTML),
|
|
104
145
|
[STYLELINT_PACKAGES.STYLELINT_CONFIG_RECESS_ORDER]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_CONFIG_RECESS_ORDER),
|
|
146
|
+
[STYLELINT_PACKAGES.STYLELINT_CONFIG_STANDARD_LESS]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_CONFIG_STANDARD_LESS),
|
|
105
147
|
[STYLELINT_PACKAGES.STYLELINT_CONFIG_STANDARD_SCSS]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_CONFIG_STANDARD_SCSS),
|
|
106
148
|
[STYLELINT_PACKAGES.STYLELINT_DECLARATION_STRICT_VALUE]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_DECLARATION_STRICT_VALUE),
|
|
107
149
|
[STYLELINT_PACKAGES.STYLELINT_ORDER]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_ORDER),
|
|
108
150
|
[STYLELINT_PACKAGES.STYLELINT_PLUGIN_DEFENSIVE_CSS]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_PLUGIN_DEFENSIVE_CSS),
|
|
109
|
-
[STYLELINT_PACKAGES.STYLELINT_PLUGIN_LOGICAL_CSS]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_PLUGIN_LOGICAL_CSS),
|
|
110
151
|
[STYLELINT_PACKAGES.STYLELINT_PLUGIN_USE_BASELINE]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_PLUGIN_USE_BASELINE),
|
|
111
152
|
[STYLELINT_PACKAGES.STYLELINT_USE_NESTING]: () => isPackageExists(STYLELINT_PACKAGES.STYLELINT_USE_NESTING),
|
|
112
153
|
[STYLELINT_PACKAGES.STYLISTIC_STYLELINT_CONFIG]: () => isPackageExists(STYLELINT_PACKAGES.STYLISTIC_STYLELINT_CONFIG)
|
|
113
154
|
};
|
|
155
|
+
const VITEST_PACKAGES = {
|
|
156
|
+
HAPPY_DOM: "happy-dom",
|
|
157
|
+
JSDOM: "jsdom",
|
|
158
|
+
VITEST_UI: "@vitest/ui"
|
|
159
|
+
};
|
|
160
|
+
const VITEST_PACKAGE_RESOLVERS = {
|
|
161
|
+
[VITEST_PACKAGES.HAPPY_DOM]: () => isPackageExists(VITEST_PACKAGES.HAPPY_DOM),
|
|
162
|
+
[VITEST_PACKAGES.JSDOM]: () => isPackageExists(VITEST_PACKAGES.JSDOM),
|
|
163
|
+
[VITEST_PACKAGES.VITEST_UI]: () => isPackageExists(VITEST_PACKAGES.VITEST_UI)
|
|
164
|
+
};
|
|
114
165
|
//#endregion
|
|
115
166
|
//#region ../src/js/shared/utils/string.ts
|
|
167
|
+
/**
|
|
168
|
+
* @internal @brnshkr/config
|
|
169
|
+
*/
|
|
116
170
|
const joinAsQuotedList = (strings, type = "conjunction") => strings.length > 1 ? `"${strings.slice(0, -1).join("\", \"")}" ${type === "conjunction" ? "and" : "or"} "${strings.slice(-1).join("")}"` : {
|
|
117
171
|
0: "",
|
|
118
172
|
1: `"${strings[0] ?? ""}"`
|
|
119
173
|
}[strings.length] ?? "";
|
|
120
174
|
//#endregion
|
|
121
175
|
//#region ../src/js/shared/utils/module.ts
|
|
176
|
+
/**
|
|
177
|
+
* @internal @brnshkr/config
|
|
178
|
+
*/
|
|
122
179
|
const PACKAGE_RESOLVERS = {
|
|
180
|
+
...COMMITLINT_PACKAGE_RESOLVERS,
|
|
123
181
|
...ESLINT_PACKAGE_RESOLVERS,
|
|
124
|
-
...
|
|
182
|
+
...MARKDOWNLINT_PACKAGE_RESOLVERS,
|
|
183
|
+
...STYLELINT_PACKAGE_RESOLVERS,
|
|
184
|
+
...VITEST_PACKAGE_RESOLVERS
|
|
125
185
|
};
|
|
126
186
|
const warnMissingPackages = (moduleInfo, packages, type) => {
|
|
127
|
-
log(
|
|
128
|
-
log(
|
|
187
|
+
log(`Failed resolving required dependencies for module "${moduleInfo.name}". Please install ${joinAsQuotedList([...packages], type === "requiredAny" ? "disjunction" : "conjunction")} or disable the ${moduleInfo.name} module in the config.`);
|
|
188
|
+
log(`Run \`bun a -D -E ${packages.join(" ")}\` to install.`);
|
|
129
189
|
};
|
|
130
190
|
const packageCache = {};
|
|
191
|
+
const loadPackageAsynchronously = async (thePackage) => {
|
|
192
|
+
try {
|
|
193
|
+
return await PACKAGE_RESOLVERS[thePackage]();
|
|
194
|
+
} catch {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const loadPackageSynchronously = (thePackage) => {
|
|
199
|
+
try {
|
|
200
|
+
return PACKAGE_RESOLVERS[thePackage]();
|
|
201
|
+
} catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
const collectPackagesAsynchronously = async (moduleInfo, type, packages) => {
|
|
206
|
+
const collectedPackages = [];
|
|
207
|
+
for (const thePackage of packages) {
|
|
208
|
+
const resolvedPackage = packageCache[thePackage] ?? await loadPackageAsynchronously(thePackage);
|
|
209
|
+
packageCache[thePackage] ??= resolvedPackage;
|
|
210
|
+
if (type === "requiredAll" && resolvedPackage === false) {
|
|
211
|
+
warnMissingPackages(moduleInfo, packages, type);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
collectedPackages.push(resolvedPackage === false ? void 0 : resolvedPackage);
|
|
215
|
+
}
|
|
216
|
+
return collectedPackages;
|
|
217
|
+
};
|
|
218
|
+
const collectPackagesSynchronously = (moduleInfo, type, packages) => {
|
|
219
|
+
const collectedPackages = [];
|
|
220
|
+
for (const thePackage of packages) {
|
|
221
|
+
const resolvedPackage = packageCache[thePackage] ?? loadPackageSynchronously(thePackage);
|
|
222
|
+
packageCache[thePackage] ??= resolvedPackage;
|
|
223
|
+
if (type === "requiredAll" && resolvedPackage === false) {
|
|
224
|
+
warnMissingPackages(moduleInfo, packages, type);
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
collectedPackages.push(resolvedPackage === false ? void 0 : resolvedPackage);
|
|
228
|
+
}
|
|
229
|
+
return collectedPackages;
|
|
230
|
+
};
|
|
131
231
|
const resolvePackagesSharedAsynchronously = async (moduleInfo, type) => {
|
|
132
232
|
if (moduleInfo.packages === void 0) return {};
|
|
133
233
|
const resolvedPackages = {};
|
|
134
234
|
const packages = type === void 0 ? moduleInfo.packages : { [type]: moduleInfo.packages[type] };
|
|
135
235
|
for (const [currentType, currentPackages] of objectEntries(packages)) {
|
|
136
236
|
if (!currentPackages || currentPackages.length === 0) continue;
|
|
137
|
-
resolvedPackages[currentType]
|
|
138
|
-
for (const currentPackage of currentPackages) try {
|
|
139
|
-
const resolvedPackage = packageCache[currentPackage] ?? await PACKAGE_RESOLVERS[currentPackage]();
|
|
140
|
-
packageCache[currentPackage] ??= resolvedPackage;
|
|
141
|
-
if (resolvedPackage === false) throw new Error("Skip to catch block.");
|
|
142
|
-
resolvedPackages[currentType].push(resolvedPackage);
|
|
143
|
-
} catch {
|
|
144
|
-
if (currentType === "requiredAll") {
|
|
145
|
-
warnMissingPackages(moduleInfo, currentPackages, currentType);
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
resolvedPackages[currentType].push(void 0);
|
|
149
|
-
}
|
|
237
|
+
resolvedPackages[currentType] = await collectPackagesAsynchronously(moduleInfo, currentType, currentPackages);
|
|
150
238
|
if (currentType === "requiredAny" && resolvedPackages[currentType].filter((thePackage) => thePackage !== void 0).length === 0) warnMissingPackages(moduleInfo, currentPackages, currentType);
|
|
151
239
|
}
|
|
152
240
|
return type === void 0 ? resolvedPackages : resolvedPackages[type] ?? [];
|
|
@@ -157,19 +245,7 @@ const resolvePackagesSharedSynchronously = (moduleInfo, type) => {
|
|
|
157
245
|
const packages = type === void 0 ? moduleInfo.packages : { [type]: moduleInfo.packages[type] };
|
|
158
246
|
for (const [currentType, currentPackages] of objectEntries(packages)) {
|
|
159
247
|
if (!currentPackages || currentPackages.length === 0) continue;
|
|
160
|
-
resolvedPackages[currentType]
|
|
161
|
-
for (const currentPackage of currentPackages) try {
|
|
162
|
-
const resolvedPackage = packageCache[currentPackage] ?? PACKAGE_RESOLVERS[currentPackage]();
|
|
163
|
-
packageCache[currentPackage] ??= resolvedPackage;
|
|
164
|
-
if (resolvedPackage === false) throw new Error("Skip to catch block.");
|
|
165
|
-
resolvedPackages[currentType].push(resolvedPackage);
|
|
166
|
-
} catch {
|
|
167
|
-
if (currentType === "requiredAll") {
|
|
168
|
-
warnMissingPackages(moduleInfo, currentPackages, currentType);
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
resolvedPackages[currentType].push(void 0);
|
|
172
|
-
}
|
|
248
|
+
resolvedPackages[currentType] = collectPackagesSynchronously(moduleInfo, currentType, currentPackages);
|
|
173
249
|
if (currentType === "requiredAny" && resolvedPackages[currentType].filter((thePackage) => thePackage !== void 0).length === 0) warnMissingPackages(moduleInfo, currentPackages, currentType);
|
|
174
250
|
}
|
|
175
251
|
return type === void 0 ? resolvedPackages : resolvedPackages[type] ?? [];
|
|
@@ -182,13 +258,31 @@ const isModuleEnabledByDefault = (moduleInfo) => {
|
|
|
182
258
|
let isEnabled = false;
|
|
183
259
|
for (const [currentType, currentPackages] of objectEntries(packages)) {
|
|
184
260
|
if (currentType === "optional") continue;
|
|
185
|
-
if (currentPackages && currentPackages.length > 0) isEnabled = currentType === "requiredAll" ? doAllPackagesExist
|
|
261
|
+
if (currentPackages && currentPackages.length > 0) isEnabled = (currentType === "requiredAll" ? doAllPackagesExist : doesAnyPackageExist)(currentPackages);
|
|
186
262
|
if (isEnabled) break;
|
|
187
263
|
}
|
|
188
264
|
return isEnabled;
|
|
189
265
|
};
|
|
266
|
+
const createModuleState = () => {
|
|
267
|
+
const enabledStates = {};
|
|
268
|
+
return {
|
|
269
|
+
isModuleEnabled: (moduleInfo) => enabledStates[moduleInfo.name] ?? isModuleEnabledByDefault(moduleInfo),
|
|
270
|
+
setModuleEnabled: (moduleInfo, isEnabled) => {
|
|
271
|
+
enabledStates[moduleInfo.name] = isEnabled;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
};
|
|
190
275
|
//#endregion
|
|
191
276
|
//#region ../src/js/shared/utils/globs.ts
|
|
277
|
+
/**
|
|
278
|
+
* @internal @brnshkr/config
|
|
279
|
+
*/
|
|
280
|
+
const GLOB_TEST_FILES = [
|
|
281
|
+
"**/__tests__/**/*.?(c|m)[jt]s?(x)",
|
|
282
|
+
"**/*.spec.?(c|m)[jt]s?(x)",
|
|
283
|
+
"**/*.test.?(c|m)[jt]s?(x)"
|
|
284
|
+
];
|
|
285
|
+
const GLOB_BENCHMARK_FILES = ["**/*.bench.?(c|m)[jt]s?(x)", "**/*.benchmark.?(c|m)[jt]s?(x)"];
|
|
192
286
|
const GLOB_IGNORES = [
|
|
193
287
|
"**/.cache/**",
|
|
194
288
|
"**/.changeset/**",
|
|
@@ -197,6 +291,7 @@ const GLOB_IGNORES = [
|
|
|
197
291
|
"**/.hg/store/**",
|
|
198
292
|
"**/.history/**",
|
|
199
293
|
"**/.idea/**",
|
|
294
|
+
"**/.local/**",
|
|
200
295
|
"**/.next/**",
|
|
201
296
|
"**/.nuxt/**",
|
|
202
297
|
"**/.output/**",
|
|
@@ -206,7 +301,9 @@ const GLOB_IGNORES = [
|
|
|
206
301
|
"**/.vercel/**",
|
|
207
302
|
"**/.vite-inspect/**",
|
|
208
303
|
"**/.vitepress/cache/**",
|
|
304
|
+
"**/.vitest/**",
|
|
209
305
|
"**/.yarn/**",
|
|
306
|
+
"**/__generated__/**",
|
|
210
307
|
"**/__snapshots__/**",
|
|
211
308
|
"**/*.code-search",
|
|
212
309
|
"**/*.example",
|
|
@@ -221,13 +318,256 @@ const GLOB_IGNORES = [
|
|
|
221
318
|
"**/package-lock.json",
|
|
222
319
|
"**/pnpm-lock.yaml",
|
|
223
320
|
"**/temp/**",
|
|
321
|
+
"**/tests/**/[Ff]ixture?(s)/**",
|
|
224
322
|
"**/tmp/**",
|
|
225
323
|
"**/vendor/**",
|
|
226
324
|
"**/vite.config.*.timestamp-*",
|
|
227
325
|
"**/yarn.lock"
|
|
228
326
|
];
|
|
229
327
|
//#endregion
|
|
328
|
+
//#region ../src/js/shared/utils/filesystem.ts
|
|
329
|
+
/**
|
|
330
|
+
* @internal @brnshkr/config
|
|
331
|
+
*/
|
|
332
|
+
const toPosix = (value) => value.replaceAll("\\", "/");
|
|
333
|
+
const doesFileExist = (filePath) => {
|
|
334
|
+
try {
|
|
335
|
+
fs.accessSync(filePath, fs.constants.R_OK);
|
|
336
|
+
return true;
|
|
337
|
+
} catch {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
const getMtime = (filePath) => {
|
|
342
|
+
try {
|
|
343
|
+
return fs.statSync(filePath).mtimeMs;
|
|
344
|
+
} catch {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
const readTextFile = (filePath) => {
|
|
349
|
+
try {
|
|
350
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
351
|
+
} catch {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
const readJsonFile = (filePath) => {
|
|
356
|
+
const content = readTextFile(filePath);
|
|
357
|
+
if (content === void 0) return;
|
|
358
|
+
try {
|
|
359
|
+
return JSON.parse(content);
|
|
360
|
+
} catch {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const readJsonObjectFile = (filePath) => {
|
|
365
|
+
const parsedContent = readJsonFile(filePath);
|
|
366
|
+
return isPlainObject(parsedContent) ? parsedContent : void 0;
|
|
367
|
+
};
|
|
368
|
+
const findNearestPackageJson = (startDirectory) => {
|
|
369
|
+
let current = path.resolve(startDirectory);
|
|
370
|
+
let parent = path.dirname(current);
|
|
371
|
+
while (current !== parent) {
|
|
372
|
+
const candidate = path.join(current, "package.json");
|
|
373
|
+
if (doesFileExist(candidate)) return candidate;
|
|
374
|
+
current = parent;
|
|
375
|
+
parent = path.dirname(current);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
//#endregion
|
|
230
379
|
//#region ../src/js/shared/utils/constants.ts
|
|
231
380
|
const QUOTES = "single";
|
|
232
381
|
//#endregion
|
|
233
|
-
|
|
382
|
+
//#region ../src/js/spelling/utils/files.ts
|
|
383
|
+
/**
|
|
384
|
+
* @internal @brnshkr/config/spelling
|
|
385
|
+
*/
|
|
386
|
+
const COMMAND_TIMEOUT_MILLISECONDS = 6e4;
|
|
387
|
+
const listTrackedFiles = (rootDirectory) => {
|
|
388
|
+
return execFileSync("git", ["ls-files", "-z"], {
|
|
389
|
+
cwd: rootDirectory,
|
|
390
|
+
encoding: "utf-8",
|
|
391
|
+
maxBuffer: Infinity,
|
|
392
|
+
timeout: COMMAND_TIMEOUT_MILLISECONDS
|
|
393
|
+
}).split("\0").filter((filePath) => filePath !== "");
|
|
394
|
+
};
|
|
395
|
+
const isScannedPath = (filePath, scannedExtensions, scannedNames, ignoreExpressions) => {
|
|
396
|
+
if (ignoreExpressions.some((ignoreExpression) => ignoreExpression.test(filePath))) return false;
|
|
397
|
+
return scannedNames.has(path.basename(filePath)) || scannedExtensions.has(path.extname(filePath));
|
|
398
|
+
};
|
|
399
|
+
const collectFilePaths = (rootDirectory, settings) => {
|
|
400
|
+
const scannedExtensions = new Set(settings.fileExtensions);
|
|
401
|
+
const scannedNames = new Set(settings.fileNames);
|
|
402
|
+
const ignoreExpressions = settings.ignorePatterns.map((ignorePattern) => new RegExp(ignorePattern, "u"));
|
|
403
|
+
return listTrackedFiles(rootDirectory).filter((filePath) => isScannedPath(filePath, scannedExtensions, scannedNames, ignoreExpressions)).filter((filePath) => doesFileExist(path.join(rootDirectory, filePath)));
|
|
404
|
+
};
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region ../src/js/spelling/utils/patterns.ts
|
|
407
|
+
/**
|
|
408
|
+
* @internal @brnshkr/config/spelling
|
|
409
|
+
*/
|
|
410
|
+
const buildPatterns = (settings) => {
|
|
411
|
+
const stemSuffixGroup = `(?:${settings.stemSuffixes.join("|")})`;
|
|
412
|
+
return [...objectEntries(settings.britishSpellings).map(([britishSpelling, americanSpelling]) => ({
|
|
413
|
+
pattern: new RegExp(String.raw`\b${britishSpelling}\w*`, "giv"),
|
|
414
|
+
toAmericanSpelling: (word) => americanSpelling + word.slice(britishSpelling.length)
|
|
415
|
+
})), ...settings.britishStems.map((britishStem) => ({
|
|
416
|
+
pattern: new RegExp(String.raw`\b${britishStem}${stemSuffixGroup}\b`, "giv"),
|
|
417
|
+
toAmericanSpelling: (word) => `${britishStem.slice(0, -1)}z${word.slice(britishStem.length)}`
|
|
418
|
+
}))];
|
|
419
|
+
};
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region ../src/js/spelling/utils/settings.ts
|
|
422
|
+
/**
|
|
423
|
+
* @internal @brnshkr/config/spelling
|
|
424
|
+
*/
|
|
425
|
+
const EVERY_PATH$1 = "*";
|
|
426
|
+
const DEFAULTS_FILE = "defaults.json";
|
|
427
|
+
const LINE_SUFFIX_PATTERN = /^(?<text>.*):(?<lineNumbers>\d+(?:,\d+)*)$/v;
|
|
428
|
+
const findShippedDirectory = () => {
|
|
429
|
+
const packageJsonPath = findNearestPackageJson(import.meta.dirname);
|
|
430
|
+
if (packageJsonPath === void 0) throw new Error("Unable to locate the shipped defaults of \"@brnshkr/config\".");
|
|
431
|
+
return path.join(path.dirname(packageJsonPath), "conf", "spelling");
|
|
432
|
+
};
|
|
433
|
+
const readSettingsFile = (filePath) => {
|
|
434
|
+
const settings = readJsonObjectFile(filePath);
|
|
435
|
+
if (settings === void 0) throw new Error(`Unable to read "${filePath}".`);
|
|
436
|
+
return settings;
|
|
437
|
+
};
|
|
438
|
+
const readStringList = (settings, settingName) => {
|
|
439
|
+
const declaredSetting = settings[settingName];
|
|
440
|
+
return Array.isArray(declaredSetting) ? declaredSetting.filter((entry) => typeof entry === "string") : [];
|
|
441
|
+
};
|
|
442
|
+
const readStringMap = (settings, settingName) => {
|
|
443
|
+
const declaredSetting = settings[settingName];
|
|
444
|
+
const stringMap = {};
|
|
445
|
+
if (!isPlainObject(declaredSetting)) return stringMap;
|
|
446
|
+
for (const [settingKey, entry] of objectEntries(declaredSetting)) if (typeof entry === "string") stringMap[settingKey] = entry;
|
|
447
|
+
return stringMap;
|
|
448
|
+
};
|
|
449
|
+
const readStringListMap = (settings, settingName) => {
|
|
450
|
+
const declaredSetting = settings[settingName];
|
|
451
|
+
const stringListMap = {};
|
|
452
|
+
if (!isPlainObject(declaredSetting)) return stringListMap;
|
|
453
|
+
for (const settingKey of objectKeys(declaredSetting)) stringListMap[settingKey] = readStringList(declaredSetting, settingKey);
|
|
454
|
+
return stringListMap;
|
|
455
|
+
};
|
|
456
|
+
const toSettings = (settings) => ({
|
|
457
|
+
fileExtensions: readStringList(settings, "fileExtensions"),
|
|
458
|
+
fileNames: readStringList(settings, "fileNames"),
|
|
459
|
+
ignorePatterns: readStringList(settings, "ignorePatterns"),
|
|
460
|
+
britishSpellings: readStringMap(settings, "britishSpellings"),
|
|
461
|
+
britishStems: readStringList(settings, "britishStems"),
|
|
462
|
+
stemSuffixes: readStringList(settings, "stemSuffixes"),
|
|
463
|
+
allowlist: readStringListMap(settings, "allowlist")
|
|
464
|
+
});
|
|
465
|
+
const mergeLists = (shippedEntries, declaredEntries) => [.../* @__PURE__ */ new Set([...shippedEntries, ...declaredEntries])];
|
|
466
|
+
const mergeSettings = (shippedSettings, declaredSettings) => ({
|
|
467
|
+
fileExtensions: mergeLists(shippedSettings.fileExtensions, declaredSettings.fileExtensions),
|
|
468
|
+
fileNames: mergeLists(shippedSettings.fileNames, declaredSettings.fileNames),
|
|
469
|
+
ignorePatterns: mergeLists(shippedSettings.ignorePatterns, declaredSettings.ignorePatterns),
|
|
470
|
+
britishSpellings: {
|
|
471
|
+
...shippedSettings.britishSpellings,
|
|
472
|
+
...declaredSettings.britishSpellings
|
|
473
|
+
},
|
|
474
|
+
britishStems: mergeLists(shippedSettings.britishStems, declaredSettings.britishStems),
|
|
475
|
+
stemSuffixes: mergeLists(shippedSettings.stemSuffixes, declaredSettings.stemSuffixes),
|
|
476
|
+
allowlist: {
|
|
477
|
+
...shippedSettings.allowlist,
|
|
478
|
+
...declaredSettings.allowlist
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
const readSettings = (rootDirectory, configPath) => {
|
|
482
|
+
const shippedPath = path.join(findShippedDirectory(), DEFAULTS_FILE);
|
|
483
|
+
const shippedSettings = toSettings(readSettingsFile(shippedPath));
|
|
484
|
+
const settingsPath = path.resolve(rootDirectory, configPath);
|
|
485
|
+
return doesFileExist(settingsPath) ? mergeSettings(shippedSettings, toSettings(readSettingsFile(settingsPath))) : shippedSettings;
|
|
486
|
+
};
|
|
487
|
+
const parseAllowedLiterals = (declaredLiterals) => declaredLiterals.map((declaredLiteral) => {
|
|
488
|
+
const matchedGroups = LINE_SUFFIX_PATTERN.exec(declaredLiteral)?.groups;
|
|
489
|
+
return {
|
|
490
|
+
text: matchedGroups?.["text"] ?? declaredLiteral,
|
|
491
|
+
lineNumbers: matchedGroups === void 0 ? void 0 : (matchedGroups["lineNumbers"] ?? "").split(",").map(Number)
|
|
492
|
+
};
|
|
493
|
+
});
|
|
494
|
+
const isCoveredBy = (coveringCandidate, allowedLiteral) => {
|
|
495
|
+
if (coveringCandidate.text.toLowerCase() !== allowedLiteral.text.toLowerCase()) return false;
|
|
496
|
+
if (coveringCandidate.lineNumbers === void 0) return true;
|
|
497
|
+
return allowedLiteral.lineNumbers?.every((lineNumber) => coveringCandidate.lineNumbers?.includes(lineNumber) === true) ?? false;
|
|
498
|
+
};
|
|
499
|
+
const formatAllowedLiteral = ({ text, lineNumbers }) => lineNumbers === void 0 ? text : `${text}:${lineNumbers.join(",")}`;
|
|
500
|
+
const rejectCoveredLiterals = (allowlist) => {
|
|
501
|
+
const literalsAllowedEverywhere = allowlist[EVERY_PATH$1] ?? [];
|
|
502
|
+
for (const [allowedPath, allowedLiterals] of objectEntries(allowlist)) for (const [index, allowedLiteral] of allowedLiterals.entries()) {
|
|
503
|
+
const coveringLiteral = [...allowedPath === EVERY_PATH$1 ? [] : literalsAllowedEverywhere, ...allowedLiterals.slice(0, index)].find((coveringCandidate) => isCoveredBy(coveringCandidate, allowedLiteral));
|
|
504
|
+
if (coveringLiteral !== void 0) throw new Error(`Allowed word "${formatAllowedLiteral(allowedLiteral)}" under "${allowedPath}" is already covered by "${formatAllowedLiteral(coveringLiteral)}".`);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
const readAllowlist = (settings) => {
|
|
508
|
+
const allowlist = {};
|
|
509
|
+
const allowlistEntries = objectEntries(settings.allowlist ?? {});
|
|
510
|
+
for (const [allowedPath, declaredLiterals] of allowlistEntries) allowlist[allowedPath] = parseAllowedLiterals(declaredLiterals);
|
|
511
|
+
rejectCoveredLiterals(allowlist);
|
|
512
|
+
return allowlist;
|
|
513
|
+
};
|
|
514
|
+
//#endregion
|
|
515
|
+
//#region ../src/js/spelling/index.ts
|
|
516
|
+
const EVERY_PATH = "*";
|
|
517
|
+
const DEFAULT_CONFIG_PATH = "conf/spelling.json";
|
|
518
|
+
const REGEX_METACHARACTERS = /[$\(\)*+.?\[\\\]^\{\|\}]/gv;
|
|
519
|
+
const escapeRegexLiteral = (value) => value.replaceAll(REGEX_METACHARACTERS, String.raw`\$&`);
|
|
520
|
+
const maskAllowedLiterals = (line, allowedLiterals, lineNumber) => {
|
|
521
|
+
let maskedLine = line;
|
|
522
|
+
for (const { text, lineNumbers } of allowedLiterals) if (lineNumbers === void 0 || lineNumbers.includes(lineNumber)) maskedLine = maskedLine.replaceAll(new RegExp(escapeRegexLiteral(text), "giu"), (matchedText) => ".".repeat(matchedText.length));
|
|
523
|
+
return maskedLine;
|
|
524
|
+
};
|
|
525
|
+
const compareCaseInsensitively = (firstValue, secondValue) => {
|
|
526
|
+
const firstLowercased = firstValue.toLowerCase();
|
|
527
|
+
const secondLowercased = secondValue.toLowerCase();
|
|
528
|
+
if (firstLowercased !== secondLowercased) return firstLowercased < secondLowercased ? -1 : 1;
|
|
529
|
+
return firstValue < secondValue ? -1 : Number(firstValue > secondValue);
|
|
530
|
+
};
|
|
531
|
+
const compareFindings = (firstFinding, secondFinding) => {
|
|
532
|
+
const pathOrder = compareCaseInsensitively(firstFinding.path, secondFinding.path);
|
|
533
|
+
if (pathOrder !== 0) return pathOrder;
|
|
534
|
+
return firstFinding.line === secondFinding.line ? compareCaseInsensitively(firstFinding.word, secondFinding.word) : firstFinding.line - secondFinding.line;
|
|
535
|
+
};
|
|
536
|
+
const findInFile = (fileContents, filePath, patterns, allowlist) => {
|
|
537
|
+
const allowedLiterals = [...allowlist[EVERY_PATH] ?? [], ...allowlist[filePath] ?? []];
|
|
538
|
+
const findings = [];
|
|
539
|
+
for (const [index, line] of fileContents.split("\n").entries()) {
|
|
540
|
+
const lineNumber = index + 1;
|
|
541
|
+
const maskedLine = maskAllowedLiterals(line, allowedLiterals, lineNumber);
|
|
542
|
+
for (const { pattern, toAmericanSpelling } of patterns) for (const [word] of maskedLine.matchAll(pattern)) findings.push({
|
|
543
|
+
path: filePath,
|
|
544
|
+
line: lineNumber,
|
|
545
|
+
word,
|
|
546
|
+
suggestion: toAmericanSpelling(word)
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
return findings;
|
|
550
|
+
};
|
|
551
|
+
/**
|
|
552
|
+
* Report every British spelling in a repository's tracked prose, docblocks and identifiers.
|
|
553
|
+
*
|
|
554
|
+
* @api
|
|
555
|
+
*
|
|
556
|
+
* @param options where to scan, which settings to read, and which files to look at
|
|
557
|
+
*
|
|
558
|
+
* @returns every finding, sorted by path, line and word
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```js
|
|
562
|
+
* scan({ rootDirectory: process.cwd() });
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
const scan = (options) => {
|
|
566
|
+
const { rootDirectory = process.cwd(), configPath = DEFAULT_CONFIG_PATH, paths } = options ?? {};
|
|
567
|
+
const settings = readSettings(rootDirectory, configPath);
|
|
568
|
+
const allowlist = readAllowlist(settings);
|
|
569
|
+
const patterns = buildPatterns(settings);
|
|
570
|
+
return (paths ?? collectFilePaths(rootDirectory, settings)).map((filePath) => findInFile(readTextFile(path.join(rootDirectory, filePath)) ?? "", filePath, patterns, allowlist)).flat().toSorted(compareFindings);
|
|
571
|
+
};
|
|
572
|
+
//#endregion
|
|
573
|
+
export { name as A, objectAssign as C, objectValues as D, objectKeys as E, packageOrganization as O, isPlainObject as S, objectFromEntries as T, COMMITLINT_PACKAGES as _, getMtime as a, STYLELINT_PACKAGES as b, toPosix as c, GLOB_TEST_FILES as d, createModuleState as f, resolvePackagesSharedSynchronously as g, resolvePackagesSharedAsynchronously as h, findNearestPackageJson as i, version as j, packageOrganizationUpper as k, GLOB_BENCHMARK_FILES as l, isModuleEnabledByDefault as m, QUOTES as n, readJsonObjectFile as o, doAllPackagesExist as p, doesFileExist as r, readTextFile as s, scan as t, GLOB_IGNORES as u, ESLINT_PACKAGES as v, objectEntries as w, VITEST_PACKAGES as x, MARKDOWNLINT_PACKAGES as y };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region ../src/js/spelling/types/options.d.ts
|
|
2
|
+
interface SpellingOptions {
|
|
3
|
+
rootDirectory?: string;
|
|
4
|
+
configPath?: string;
|
|
5
|
+
paths?: string[];
|
|
6
|
+
}
|
|
7
|
+
interface SpellingFinding {
|
|
8
|
+
path: string;
|
|
9
|
+
line: number;
|
|
10
|
+
word: string;
|
|
11
|
+
suggestion: string;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region ../src/js/spelling/index.d.ts
|
|
15
|
+
/**
|
|
16
|
+
* Report every British spelling in a repository's tracked prose, docblocks and identifiers.
|
|
17
|
+
*
|
|
18
|
+
* @api
|
|
19
|
+
*
|
|
20
|
+
* @param options where to scan, which settings to read, and which files to look at
|
|
21
|
+
*
|
|
22
|
+
* @returns every finding, sorted by path, line and word
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```js
|
|
26
|
+
* scan({ rootDirectory: process.cwd() });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const scan: (options?: Partial<SpellingOptions>) => SpellingFinding[];
|
|
30
|
+
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as scan } from "../shared.mjs";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
//#region ../src/js/spelling/spelling.test.ts
|
|
4
|
+
/**
|
|
5
|
+
* @internal @brnshkr/config/spelling
|
|
6
|
+
*/
|
|
7
|
+
test("every tracked file is written in american english", () => {
|
|
8
|
+
const findings = scan().map(({ path, line, word, suggestion }) => `${path}:${String(line)} — "${word}", use "${suggestion}"`);
|
|
9
|
+
expect(findings).toStrictEqual([]);
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
export {};
|