eslint-plugin-markdown-preferences 0.8.0 → 0.9.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.
- package/README.md +3 -1
- package/lib/index.d.ts +31 -2
- package/lib/index.js +877 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ For detailed usage instructions, rule configurations, and examples, visit our co
|
|
|
28
28
|
|
|
29
29
|
## 💿 Installation
|
|
30
30
|
|
|
31
|
-
```
|
|
31
|
+
```sh
|
|
32
32
|
npm install --save-dev eslint eslint-plugin-markdown-preferences
|
|
33
33
|
```
|
|
34
34
|
|
|
@@ -98,8 +98,10 @@ The rules with the following star ⭐ are included in the configs.
|
|
|
98
98
|
|
|
99
99
|
| Rule ID | Description | Fixable | RECOMMENDED |
|
|
100
100
|
|:--------|:------------|:-------:|:-----------:|
|
|
101
|
+
| [markdown-preferences/canonical-code-block-language](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/canonical-code-block-language.html) | enforce canonical language names in code blocks | 🔧 | |
|
|
101
102
|
| [markdown-preferences/definitions-last](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/definitions-last.html) | require link definitions and footnote definitions to be placed at the end of the document | 🔧 | |
|
|
102
103
|
| [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style. | 🔧 | ⭐ |
|
|
104
|
+
| [markdown-preferences/heading-casing](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/heading-casing.html) | enforce consistent casing in headings. | 🔧 | |
|
|
103
105
|
| [markdown-preferences/no-trailing-spaces](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html) | disallow trailing whitespace at the end of lines in Markdown files. | 🔧 | |
|
|
104
106
|
| [markdown-preferences/prefer-link-reference-definitions](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-link-reference-definitions.html) | enforce using link reference definitions instead of inline links | 🔧 | |
|
|
105
107
|
| [markdown-preferences/sort-definitions](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/sort-definitions.html) | enforce a specific order for link definitions and footnote definitions | 🔧 | |
|
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ declare module 'eslint' {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
interface RuleOptions {
|
|
13
|
+
/**
|
|
14
|
+
* enforce canonical language names in code blocks
|
|
15
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/canonical-code-block-language.html
|
|
16
|
+
*/
|
|
17
|
+
'markdown-preferences/canonical-code-block-language'?: Linter.RuleEntry<MarkdownPreferencesCanonicalCodeBlockLanguage>;
|
|
13
18
|
/**
|
|
14
19
|
* require link definitions and footnote definitions to be placed at the end of the document
|
|
15
20
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/definitions-last.html
|
|
@@ -20,6 +25,11 @@ interface RuleOptions {
|
|
|
20
25
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html
|
|
21
26
|
*/
|
|
22
27
|
'markdown-preferences/hard-linebreak-style'?: Linter.RuleEntry<MarkdownPreferencesHardLinebreakStyle>;
|
|
28
|
+
/**
|
|
29
|
+
* enforce consistent casing in headings.
|
|
30
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/heading-casing.html
|
|
31
|
+
*/
|
|
32
|
+
'markdown-preferences/heading-casing'?: Linter.RuleEntry<MarkdownPreferencesHeadingCasing>;
|
|
23
33
|
/**
|
|
24
34
|
* disallow text backslash at the end of a line.
|
|
25
35
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html
|
|
@@ -51,9 +61,20 @@ interface RuleOptions {
|
|
|
51
61
|
*/
|
|
52
62
|
'markdown-preferences/sort-definitions'?: Linter.RuleEntry<MarkdownPreferencesSortDefinitions>;
|
|
53
63
|
}
|
|
64
|
+
type MarkdownPreferencesCanonicalCodeBlockLanguage = [] | [{
|
|
65
|
+
languages?: {
|
|
66
|
+
[k: string]: string;
|
|
67
|
+
};
|
|
68
|
+
}];
|
|
54
69
|
type MarkdownPreferencesHardLinebreakStyle = [] | [{
|
|
55
70
|
style?: ("backslash" | "spaces");
|
|
56
71
|
}];
|
|
72
|
+
type MarkdownPreferencesHeadingCasing = [] | [{
|
|
73
|
+
style?: ("Title Case" | "Sentence case");
|
|
74
|
+
preserveWords?: string[];
|
|
75
|
+
ignorePatterns?: string[];
|
|
76
|
+
minorWords?: string[];
|
|
77
|
+
}];
|
|
57
78
|
type MarkdownPreferencesNoTrailingSpaces = [] | [{
|
|
58
79
|
skipBlankLines?: boolean;
|
|
59
80
|
ignoreComments?: boolean;
|
|
@@ -107,19 +128,27 @@ declare namespace meta_d_exports {
|
|
|
107
128
|
export { name, version };
|
|
108
129
|
}
|
|
109
130
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
110
|
-
declare const version: "0.
|
|
131
|
+
declare const version: "0.9.0";
|
|
111
132
|
//#endregion
|
|
112
133
|
//#region src/index.d.ts
|
|
113
134
|
declare const configs: {
|
|
114
135
|
recommended: typeof recommended_d_exports;
|
|
115
136
|
};
|
|
116
137
|
declare const rules: Record<string, RuleDefinition>;
|
|
138
|
+
declare const resources: {
|
|
139
|
+
defaultPreserveWords: string[];
|
|
140
|
+
defaultMinorWords: string[];
|
|
141
|
+
};
|
|
117
142
|
declare const _default: {
|
|
118
143
|
meta: typeof meta_d_exports;
|
|
119
144
|
configs: {
|
|
120
145
|
recommended: typeof recommended_d_exports;
|
|
121
146
|
};
|
|
122
147
|
rules: Record<string, RuleDefinition<_eslint_core0.RuleDefinitionTypeOptions>>;
|
|
148
|
+
resources: {
|
|
149
|
+
defaultPreserveWords: string[];
|
|
150
|
+
defaultMinorWords: string[];
|
|
151
|
+
};
|
|
123
152
|
};
|
|
124
153
|
//#endregion
|
|
125
|
-
export { RuleOptions, configs, _default as default, meta_d_exports as meta, rules };
|
|
154
|
+
export { RuleOptions, configs, _default as default, meta_d_exports as meta, resources, rules };
|
package/lib/index.js
CHANGED
|
@@ -25,6 +25,98 @@ function createRule(ruleName, rule) {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/rules/canonical-code-block-language.ts
|
|
30
|
+
const DEFAULT_LANGUAGES = {
|
|
31
|
+
javascript: "js",
|
|
32
|
+
jsx: "js",
|
|
33
|
+
mjs: "js",
|
|
34
|
+
cjs: "js",
|
|
35
|
+
typescript: "ts",
|
|
36
|
+
tsx: "ts",
|
|
37
|
+
mts: "ts",
|
|
38
|
+
cts: "ts",
|
|
39
|
+
python: "py",
|
|
40
|
+
bash: "sh",
|
|
41
|
+
shell: "sh",
|
|
42
|
+
zsh: "sh",
|
|
43
|
+
yml: "yaml",
|
|
44
|
+
markdown: "md",
|
|
45
|
+
rust: "rs",
|
|
46
|
+
golang: "go",
|
|
47
|
+
cplusplus: "cpp",
|
|
48
|
+
"c++": "cpp",
|
|
49
|
+
postgresql: "sql",
|
|
50
|
+
mysql: "sql",
|
|
51
|
+
sqlite: "sql"
|
|
52
|
+
};
|
|
53
|
+
var canonical_code_block_language_default = createRule("canonical-code-block-language", {
|
|
54
|
+
meta: {
|
|
55
|
+
type: "suggestion",
|
|
56
|
+
docs: {
|
|
57
|
+
description: "enforce canonical language names in code blocks",
|
|
58
|
+
categories: [],
|
|
59
|
+
listCategory: "Stylistic"
|
|
60
|
+
},
|
|
61
|
+
fixable: "code",
|
|
62
|
+
hasSuggestions: false,
|
|
63
|
+
schema: [{
|
|
64
|
+
type: "object",
|
|
65
|
+
properties: { languages: {
|
|
66
|
+
type: "object",
|
|
67
|
+
patternProperties: { "^[\\s\\S]+$": { type: "string" } },
|
|
68
|
+
additionalProperties: false
|
|
69
|
+
} },
|
|
70
|
+
additionalProperties: false
|
|
71
|
+
}],
|
|
72
|
+
messages: { useCanonical: "Use canonical language name \"{{canonical}}\" instead of \"{{current}}\"." }
|
|
73
|
+
},
|
|
74
|
+
create(context) {
|
|
75
|
+
const sourceCode = context.sourceCode;
|
|
76
|
+
const languages = context.options[0]?.languages || DEFAULT_LANGUAGES;
|
|
77
|
+
return { code(node) {
|
|
78
|
+
if (!node.lang || !languages[node.lang]) return;
|
|
79
|
+
const canonical = languages[node.lang];
|
|
80
|
+
const current = node.lang;
|
|
81
|
+
if (current === canonical) return;
|
|
82
|
+
const nodeRange = sourceCode.getRange(node);
|
|
83
|
+
const nodeText = sourceCode.text.slice(nodeRange[0], nodeRange[1]);
|
|
84
|
+
const fenceRegex = /^(`{3,}|~{3,})(\w*)(?:\s.*)?$/mu;
|
|
85
|
+
const fenceMatch = fenceRegex.exec(nodeText.split("\n")[0]);
|
|
86
|
+
if (!fenceMatch) return;
|
|
87
|
+
const [, fence, langInfo] = fenceMatch;
|
|
88
|
+
const langStart = nodeRange[0] + fence.length;
|
|
89
|
+
const langEnd = langStart + langInfo.length;
|
|
90
|
+
const nodeLoc = sourceCode.getLoc(node);
|
|
91
|
+
const beforeFence = sourceCode.text.slice(nodeRange[0], langStart);
|
|
92
|
+
const beforeLines = beforeFence.split(/\n/u);
|
|
93
|
+
const line = nodeLoc.start.line + beforeLines.length - 1;
|
|
94
|
+
const column = (beforeLines.length === 1 ? nodeLoc.start.column : 0) + (beforeLines.at(-1) || "").length;
|
|
95
|
+
context.report({
|
|
96
|
+
node,
|
|
97
|
+
loc: {
|
|
98
|
+
start: {
|
|
99
|
+
line,
|
|
100
|
+
column
|
|
101
|
+
},
|
|
102
|
+
end: {
|
|
103
|
+
line,
|
|
104
|
+
column: column + langInfo.length
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
messageId: "useCanonical",
|
|
108
|
+
data: {
|
|
109
|
+
canonical,
|
|
110
|
+
current
|
|
111
|
+
},
|
|
112
|
+
fix(fixer) {
|
|
113
|
+
return fixer.replaceTextRange([langStart, langEnd], canonical);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
} };
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
28
120
|
//#endregion
|
|
29
121
|
//#region src/rules/definitions-last.ts
|
|
30
122
|
var definitions_last_default = createRule("definitions-last", {
|
|
@@ -111,6 +203,781 @@ var hard_linebreak_style_default = createRule("hard-linebreak-style", {
|
|
|
111
203
|
}
|
|
112
204
|
});
|
|
113
205
|
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/utils/regexp.ts
|
|
208
|
+
const RE_REGEXP_STR = /^\/(.+)\/([A-Za-z]*)$/u;
|
|
209
|
+
/**
|
|
210
|
+
* Convert a string to the `RegExp`.
|
|
211
|
+
* Normal strings (e.g. `"foo"`) is converted to `/^foo$/` of `RegExp`.
|
|
212
|
+
* Strings like `"/^foo/i"` are converted to `/^foo/i` of `RegExp`.
|
|
213
|
+
*
|
|
214
|
+
* @param {string} string The string to convert.
|
|
215
|
+
* @returns {RegExp} Returns the `RegExp`.
|
|
216
|
+
*/
|
|
217
|
+
function toRegExp(string) {
|
|
218
|
+
const parts = RE_REGEXP_STR.exec(string);
|
|
219
|
+
if (parts) return new RegExp(parts[1], parts[2]);
|
|
220
|
+
return { test: (s) => s === string };
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Checks whether given string is regexp string
|
|
224
|
+
* @param {string} string
|
|
225
|
+
* @returns {boolean}
|
|
226
|
+
*/
|
|
227
|
+
function isRegExp(string) {
|
|
228
|
+
return Boolean(RE_REGEXP_STR.test(string));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/resources/preserve-words.ts
|
|
233
|
+
const defaultPreserveWords = [
|
|
234
|
+
"JavaScript",
|
|
235
|
+
"TypeScript",
|
|
236
|
+
"ECMAScript",
|
|
237
|
+
"ES6",
|
|
238
|
+
...(function* () {
|
|
239
|
+
const end = (/* @__PURE__ */ new Date()).getFullYear() + 3;
|
|
240
|
+
for (let i = 2015; i <= end; i++) yield `ES${i}`;
|
|
241
|
+
})(),
|
|
242
|
+
"PHP",
|
|
243
|
+
"Python",
|
|
244
|
+
"Java",
|
|
245
|
+
"C#",
|
|
246
|
+
"C++",
|
|
247
|
+
"Rust",
|
|
248
|
+
"Go",
|
|
249
|
+
"go",
|
|
250
|
+
"Swift",
|
|
251
|
+
"Kotlin",
|
|
252
|
+
"Dart",
|
|
253
|
+
"Ruby",
|
|
254
|
+
"Scala",
|
|
255
|
+
"Perl",
|
|
256
|
+
"R",
|
|
257
|
+
"MATLAB",
|
|
258
|
+
"Lua",
|
|
259
|
+
"Haskell",
|
|
260
|
+
"Elixir",
|
|
261
|
+
"Clojure",
|
|
262
|
+
"F#",
|
|
263
|
+
"OCaml",
|
|
264
|
+
"Zig",
|
|
265
|
+
"V",
|
|
266
|
+
"Nim",
|
|
267
|
+
"Crystal",
|
|
268
|
+
"Gleam",
|
|
269
|
+
"Odin",
|
|
270
|
+
"Carbon",
|
|
271
|
+
"HTML",
|
|
272
|
+
"CSS",
|
|
273
|
+
"Sass",
|
|
274
|
+
"SCSS",
|
|
275
|
+
"Less",
|
|
276
|
+
"Stylus",
|
|
277
|
+
"JSON",
|
|
278
|
+
"XML",
|
|
279
|
+
"PDF",
|
|
280
|
+
"CSV",
|
|
281
|
+
"YAML",
|
|
282
|
+
"TOML",
|
|
283
|
+
"Markdown",
|
|
284
|
+
"LaTeX",
|
|
285
|
+
"Parquet",
|
|
286
|
+
"Avro",
|
|
287
|
+
"Protobuf",
|
|
288
|
+
"MessagePack",
|
|
289
|
+
"BSON",
|
|
290
|
+
"HDF5",
|
|
291
|
+
"Apache Arrow",
|
|
292
|
+
"ORC",
|
|
293
|
+
"SQL",
|
|
294
|
+
"GraphQL",
|
|
295
|
+
"React",
|
|
296
|
+
"Vue",
|
|
297
|
+
"Angular",
|
|
298
|
+
"Redux",
|
|
299
|
+
"Svelte",
|
|
300
|
+
"SvelteKit",
|
|
301
|
+
"Preact",
|
|
302
|
+
"Solid",
|
|
303
|
+
"Alpine.js",
|
|
304
|
+
"Lit",
|
|
305
|
+
"Stencil",
|
|
306
|
+
"Ember.js",
|
|
307
|
+
"Backbone.js",
|
|
308
|
+
"jQuery",
|
|
309
|
+
"D3.js",
|
|
310
|
+
"Three.js",
|
|
311
|
+
"Chart.js",
|
|
312
|
+
"Plotly",
|
|
313
|
+
"Astro",
|
|
314
|
+
"Remix",
|
|
315
|
+
"Qwik",
|
|
316
|
+
"SolidJS",
|
|
317
|
+
"Vike",
|
|
318
|
+
"Node.js",
|
|
319
|
+
"Deno",
|
|
320
|
+
"Bun",
|
|
321
|
+
"Electron",
|
|
322
|
+
"Tauri",
|
|
323
|
+
"Next.js",
|
|
324
|
+
"Nuxt.js",
|
|
325
|
+
"Gatsby",
|
|
326
|
+
"Express.js",
|
|
327
|
+
"NestJS",
|
|
328
|
+
"FastAPI",
|
|
329
|
+
"Django",
|
|
330
|
+
"Flask",
|
|
331
|
+
"Ruby on Rails",
|
|
332
|
+
"Spring Boot",
|
|
333
|
+
"Laravel",
|
|
334
|
+
"Phoenix",
|
|
335
|
+
"Actix",
|
|
336
|
+
"Axum",
|
|
337
|
+
"Rocket",
|
|
338
|
+
"Flutter",
|
|
339
|
+
"React Native",
|
|
340
|
+
"Ionic",
|
|
341
|
+
"Xamarin",
|
|
342
|
+
"Expo",
|
|
343
|
+
"Unity",
|
|
344
|
+
"Unreal Engine",
|
|
345
|
+
"ESLint",
|
|
346
|
+
"Prettier",
|
|
347
|
+
"Biome",
|
|
348
|
+
"oxc",
|
|
349
|
+
"swc",
|
|
350
|
+
"Webpack",
|
|
351
|
+
"Vite",
|
|
352
|
+
"Babel",
|
|
353
|
+
"Workbox",
|
|
354
|
+
"Rollup",
|
|
355
|
+
"Parcel",
|
|
356
|
+
"esbuild",
|
|
357
|
+
"Turbo",
|
|
358
|
+
"Turborepo",
|
|
359
|
+
"Nx",
|
|
360
|
+
"Lerna",
|
|
361
|
+
"Rush",
|
|
362
|
+
"npm",
|
|
363
|
+
"yarn",
|
|
364
|
+
"pnpm",
|
|
365
|
+
"bun",
|
|
366
|
+
"bower",
|
|
367
|
+
"composer",
|
|
368
|
+
"pip",
|
|
369
|
+
"conda",
|
|
370
|
+
"Maven",
|
|
371
|
+
"Gradle",
|
|
372
|
+
"SBT",
|
|
373
|
+
"Cargo",
|
|
374
|
+
"homebrew",
|
|
375
|
+
"chocolatey",
|
|
376
|
+
"CocoaPods",
|
|
377
|
+
"Carthage",
|
|
378
|
+
"Swift Package Manager",
|
|
379
|
+
"VS Code",
|
|
380
|
+
"Visual Studio Code",
|
|
381
|
+
"Vim",
|
|
382
|
+
"Neovim",
|
|
383
|
+
"Emacs",
|
|
384
|
+
"Sublime Text",
|
|
385
|
+
"Atom",
|
|
386
|
+
"Brackets",
|
|
387
|
+
"brackets",
|
|
388
|
+
"Visual Studio",
|
|
389
|
+
"IntelliJ IDEA",
|
|
390
|
+
"WebStorm",
|
|
391
|
+
"PHPStorm",
|
|
392
|
+
"PyCharm",
|
|
393
|
+
"Android Studio",
|
|
394
|
+
"Xcode",
|
|
395
|
+
"Docker",
|
|
396
|
+
"Kubernetes",
|
|
397
|
+
"Helm",
|
|
398
|
+
"CI / CD",
|
|
399
|
+
"DevOps",
|
|
400
|
+
"GitOps",
|
|
401
|
+
"IaC",
|
|
402
|
+
"Infrastructure as Code",
|
|
403
|
+
"SaaS",
|
|
404
|
+
"PaaS",
|
|
405
|
+
"IaaS",
|
|
406
|
+
"CDN",
|
|
407
|
+
"Load Balancer",
|
|
408
|
+
"API Gateway",
|
|
409
|
+
"Microservices",
|
|
410
|
+
"Serverless",
|
|
411
|
+
"Lambda",
|
|
412
|
+
"Cloud Functions",
|
|
413
|
+
"Container Registry",
|
|
414
|
+
"Prometheus",
|
|
415
|
+
"Grafana",
|
|
416
|
+
"Terraform",
|
|
417
|
+
"Ansible",
|
|
418
|
+
"Jenkins",
|
|
419
|
+
"GitHub Actions",
|
|
420
|
+
"GitLab CI",
|
|
421
|
+
"CircleCI",
|
|
422
|
+
"Travis CI",
|
|
423
|
+
"Azure DevOps",
|
|
424
|
+
"TeamCity",
|
|
425
|
+
"Bamboo",
|
|
426
|
+
"Buildkite",
|
|
427
|
+
"Drone CI",
|
|
428
|
+
"AWS",
|
|
429
|
+
"Amazon Web Services",
|
|
430
|
+
"Azure",
|
|
431
|
+
"GCP",
|
|
432
|
+
"Google Cloud Platform",
|
|
433
|
+
"Heroku",
|
|
434
|
+
"Vercel",
|
|
435
|
+
"Netlify",
|
|
436
|
+
"Railway",
|
|
437
|
+
"Render",
|
|
438
|
+
"Fly.io",
|
|
439
|
+
"Cloudflare",
|
|
440
|
+
"DigitalOcean",
|
|
441
|
+
"API",
|
|
442
|
+
"APIs",
|
|
443
|
+
"REST",
|
|
444
|
+
"RESTful",
|
|
445
|
+
"gRPC",
|
|
446
|
+
"HTTP",
|
|
447
|
+
"HTTPS",
|
|
448
|
+
"WebSocket",
|
|
449
|
+
"SOAP",
|
|
450
|
+
"XML-RPC",
|
|
451
|
+
"JSON-RPC",
|
|
452
|
+
"CLI",
|
|
453
|
+
"SDK",
|
|
454
|
+
"URL",
|
|
455
|
+
"URI",
|
|
456
|
+
"UUID",
|
|
457
|
+
"GUID",
|
|
458
|
+
"CRUD",
|
|
459
|
+
"ACID",
|
|
460
|
+
"BASE",
|
|
461
|
+
"CAP Theorem",
|
|
462
|
+
"JWT",
|
|
463
|
+
"OAuth",
|
|
464
|
+
"OAuth2",
|
|
465
|
+
"OpenID Connect",
|
|
466
|
+
"SAML",
|
|
467
|
+
"SSO",
|
|
468
|
+
"MFA",
|
|
469
|
+
"2FA",
|
|
470
|
+
"CORS",
|
|
471
|
+
"CSRF",
|
|
472
|
+
"XSS",
|
|
473
|
+
"SSH",
|
|
474
|
+
"FTP",
|
|
475
|
+
"SFTP",
|
|
476
|
+
"SMTP",
|
|
477
|
+
"IMAP",
|
|
478
|
+
"POP3",
|
|
479
|
+
"TCP",
|
|
480
|
+
"UDP",
|
|
481
|
+
"IP",
|
|
482
|
+
"IPv4",
|
|
483
|
+
"IPv6",
|
|
484
|
+
"DNS",
|
|
485
|
+
"DHCP",
|
|
486
|
+
"VPN",
|
|
487
|
+
"SSL",
|
|
488
|
+
"TLS",
|
|
489
|
+
"LDAP",
|
|
490
|
+
"PostgreSQL",
|
|
491
|
+
"MySQL",
|
|
492
|
+
"SQLite",
|
|
493
|
+
"MariaDB",
|
|
494
|
+
"Oracle",
|
|
495
|
+
"SQL Server",
|
|
496
|
+
"CockroachDB",
|
|
497
|
+
"PlanetScale",
|
|
498
|
+
"Neon",
|
|
499
|
+
"NoSQL",
|
|
500
|
+
"MongoDB",
|
|
501
|
+
"DynamoDB",
|
|
502
|
+
"Cassandra",
|
|
503
|
+
"CouchDB",
|
|
504
|
+
"Neo4j",
|
|
505
|
+
"ArangoDB",
|
|
506
|
+
"FaunaDB",
|
|
507
|
+
"Firebase",
|
|
508
|
+
"Supabase",
|
|
509
|
+
"Redis",
|
|
510
|
+
"ElasticSearch",
|
|
511
|
+
"Solr",
|
|
512
|
+
"InfluxDB",
|
|
513
|
+
"TimescaleDB",
|
|
514
|
+
"Prisma",
|
|
515
|
+
"TypeORM",
|
|
516
|
+
"Sequelize",
|
|
517
|
+
"Mongoose",
|
|
518
|
+
"Drizzle",
|
|
519
|
+
"Knex.js",
|
|
520
|
+
"Objection.js",
|
|
521
|
+
"Bookshelf.js",
|
|
522
|
+
"QA",
|
|
523
|
+
"QC",
|
|
524
|
+
"TDD",
|
|
525
|
+
"BDD",
|
|
526
|
+
"E2E",
|
|
527
|
+
"Unit Testing",
|
|
528
|
+
"Integration Testing",
|
|
529
|
+
"Jest",
|
|
530
|
+
"Mocha",
|
|
531
|
+
"Chai",
|
|
532
|
+
"Jasmine",
|
|
533
|
+
"Karma",
|
|
534
|
+
"Vitest",
|
|
535
|
+
"Ava",
|
|
536
|
+
"Tape",
|
|
537
|
+
"Cypress",
|
|
538
|
+
"Playwright",
|
|
539
|
+
"Selenium",
|
|
540
|
+
"Puppeteer",
|
|
541
|
+
"WebDriver",
|
|
542
|
+
"TestCafe",
|
|
543
|
+
"SonarQube",
|
|
544
|
+
"Husky",
|
|
545
|
+
"lint-staged",
|
|
546
|
+
"commitizen",
|
|
547
|
+
"semantic-release",
|
|
548
|
+
"Codecov",
|
|
549
|
+
"CodeClimate",
|
|
550
|
+
"TensorFlow",
|
|
551
|
+
"PyTorch",
|
|
552
|
+
"Keras",
|
|
553
|
+
"Scikit-learn",
|
|
554
|
+
"Pandas",
|
|
555
|
+
"NumPy",
|
|
556
|
+
"OpenCV",
|
|
557
|
+
"Hugging Face",
|
|
558
|
+
"LangChain",
|
|
559
|
+
"OpenAI",
|
|
560
|
+
"Anthropic",
|
|
561
|
+
"Jupyter",
|
|
562
|
+
"MLflow",
|
|
563
|
+
"Weights & Biases",
|
|
564
|
+
"CUDA",
|
|
565
|
+
"ONNX",
|
|
566
|
+
"GPT",
|
|
567
|
+
"BERT",
|
|
568
|
+
"Transformer",
|
|
569
|
+
"Claude",
|
|
570
|
+
"Gemini",
|
|
571
|
+
"LLaMA",
|
|
572
|
+
"Stable Diffusion",
|
|
573
|
+
"DALL-E",
|
|
574
|
+
"Midjourney",
|
|
575
|
+
"AutoML",
|
|
576
|
+
"ETL",
|
|
577
|
+
"ELT",
|
|
578
|
+
"Big Data",
|
|
579
|
+
"Data Lake",
|
|
580
|
+
"Data Warehouse",
|
|
581
|
+
"OLAP",
|
|
582
|
+
"OLTP",
|
|
583
|
+
"Apache Spark",
|
|
584
|
+
"Apache Kafka",
|
|
585
|
+
"Apache Airflow",
|
|
586
|
+
"Hadoop",
|
|
587
|
+
"Snowflake",
|
|
588
|
+
"Databricks",
|
|
589
|
+
"Tableau",
|
|
590
|
+
"Power BI",
|
|
591
|
+
"Looker",
|
|
592
|
+
"OWASP",
|
|
593
|
+
"SAST",
|
|
594
|
+
"DAST",
|
|
595
|
+
"IAST",
|
|
596
|
+
"SCA",
|
|
597
|
+
"Penetration Testing",
|
|
598
|
+
"Vulnerability Assessment",
|
|
599
|
+
"RBAC",
|
|
600
|
+
"ABAC",
|
|
601
|
+
"Zero Trust",
|
|
602
|
+
"PKI",
|
|
603
|
+
"HSM",
|
|
604
|
+
"WAF",
|
|
605
|
+
"DDoS",
|
|
606
|
+
"PWA",
|
|
607
|
+
"SPA",
|
|
608
|
+
"SSR",
|
|
609
|
+
"SSG",
|
|
610
|
+
"CSR",
|
|
611
|
+
"JAMstack",
|
|
612
|
+
"Headless CMS",
|
|
613
|
+
"Edge Computing",
|
|
614
|
+
"WebAssembly",
|
|
615
|
+
"WASM",
|
|
616
|
+
"Service Worker",
|
|
617
|
+
"Web Components",
|
|
618
|
+
"Micro Frontends",
|
|
619
|
+
"BFF",
|
|
620
|
+
"Backend for Frontend",
|
|
621
|
+
"GraphQL",
|
|
622
|
+
"tRPC",
|
|
623
|
+
"gRPC-Web",
|
|
624
|
+
"WebRTC",
|
|
625
|
+
"WebGL",
|
|
626
|
+
"WebGPU",
|
|
627
|
+
"Material UI",
|
|
628
|
+
"Ant Design",
|
|
629
|
+
"Chakra UI",
|
|
630
|
+
"React Bootstrap",
|
|
631
|
+
"Semantic UI React",
|
|
632
|
+
"Blueprint",
|
|
633
|
+
"Mantine",
|
|
634
|
+
"NextUI",
|
|
635
|
+
"Arco Design",
|
|
636
|
+
"Tailwind CSS",
|
|
637
|
+
"Bootstrap",
|
|
638
|
+
"Bulma",
|
|
639
|
+
"Foundation",
|
|
640
|
+
"Semantic UI",
|
|
641
|
+
"Materialize",
|
|
642
|
+
"Spectre.css",
|
|
643
|
+
"Tachyons",
|
|
644
|
+
"PureCSS",
|
|
645
|
+
"styled-components",
|
|
646
|
+
"CSS-in-JS",
|
|
647
|
+
"Emotion",
|
|
648
|
+
"JSS",
|
|
649
|
+
"Styled System",
|
|
650
|
+
"Stitches",
|
|
651
|
+
"Vanilla Extract",
|
|
652
|
+
"Linaria",
|
|
653
|
+
"Aphrodite",
|
|
654
|
+
"Glamorous",
|
|
655
|
+
"Radium",
|
|
656
|
+
"Git",
|
|
657
|
+
"Mercurial",
|
|
658
|
+
"SVN",
|
|
659
|
+
"GitHub",
|
|
660
|
+
"GitLab",
|
|
661
|
+
"Bitbucket",
|
|
662
|
+
"Pull Request",
|
|
663
|
+
"Merge Request",
|
|
664
|
+
"Code Review",
|
|
665
|
+
"Pair Programming",
|
|
666
|
+
"Mob Programming",
|
|
667
|
+
"Docusaurus",
|
|
668
|
+
"GitBook",
|
|
669
|
+
"VitePress",
|
|
670
|
+
"VuePress",
|
|
671
|
+
"Docsify",
|
|
672
|
+
"MkDocs",
|
|
673
|
+
"Sphinx",
|
|
674
|
+
"Jekyll",
|
|
675
|
+
"Hugo",
|
|
676
|
+
"Eleventy",
|
|
677
|
+
"Hexo",
|
|
678
|
+
"Zola",
|
|
679
|
+
"Swagger",
|
|
680
|
+
"OpenAPI",
|
|
681
|
+
"Postman",
|
|
682
|
+
"Insomnia",
|
|
683
|
+
"Redoc",
|
|
684
|
+
"Stoplight",
|
|
685
|
+
"FAQ"
|
|
686
|
+
];
|
|
687
|
+
|
|
688
|
+
//#endregion
|
|
689
|
+
//#region src/resources/minor-words.ts
|
|
690
|
+
const articles = [
|
|
691
|
+
"a",
|
|
692
|
+
"an",
|
|
693
|
+
"the"
|
|
694
|
+
];
|
|
695
|
+
const conjunctions = [
|
|
696
|
+
"for",
|
|
697
|
+
"and",
|
|
698
|
+
"nor",
|
|
699
|
+
"but",
|
|
700
|
+
"or",
|
|
701
|
+
"yet",
|
|
702
|
+
"so"
|
|
703
|
+
];
|
|
704
|
+
const prepositions = [
|
|
705
|
+
"a",
|
|
706
|
+
"as",
|
|
707
|
+
"at",
|
|
708
|
+
"by",
|
|
709
|
+
"ex",
|
|
710
|
+
"in",
|
|
711
|
+
"of",
|
|
712
|
+
"on",
|
|
713
|
+
"re",
|
|
714
|
+
"to",
|
|
715
|
+
"up"
|
|
716
|
+
];
|
|
717
|
+
const defaultMinorWords = [
|
|
718
|
+
...articles,
|
|
719
|
+
...conjunctions,
|
|
720
|
+
...prepositions
|
|
721
|
+
];
|
|
722
|
+
|
|
723
|
+
//#endregion
|
|
724
|
+
//#region src/rules/heading-casing.ts
|
|
725
|
+
/**
|
|
726
|
+
* Parse preserve words and phrases from the options
|
|
727
|
+
* - Single words are added to preserveWords
|
|
728
|
+
* - Multi-word phrases are added to preservePhrases and added to preserveWords with no spaces
|
|
729
|
+
*/
|
|
730
|
+
function parsePreserveWords(preserveWordsOption) {
|
|
731
|
+
const preserveWords = /* @__PURE__ */ new Map();
|
|
732
|
+
/**
|
|
733
|
+
* Add a single word to the preserveWords map
|
|
734
|
+
*/
|
|
735
|
+
function addPreserveWord(word) {
|
|
736
|
+
const lowerWord = word.toLowerCase();
|
|
737
|
+
let list = preserveWords.get(lowerWord);
|
|
738
|
+
if (!list) {
|
|
739
|
+
list = [];
|
|
740
|
+
preserveWords.set(lowerWord, list);
|
|
741
|
+
}
|
|
742
|
+
list.push(word);
|
|
743
|
+
}
|
|
744
|
+
const preservePhrases = /* @__PURE__ */ new Map();
|
|
745
|
+
for (const word of preserveWordsOption) {
|
|
746
|
+
const splitted = word.split(/\s+/);
|
|
747
|
+
if (splitted.length <= 1) addPreserveWord(word);
|
|
748
|
+
else {
|
|
749
|
+
preservePhrases.set(word, splitted);
|
|
750
|
+
addPreserveWord(splitted.join(""));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return {
|
|
754
|
+
preserveWords,
|
|
755
|
+
preservePhrases: [...preservePhrases.values()].sort((a, b) => b.length - a.length)
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Parse text into words with offsets
|
|
760
|
+
*/
|
|
761
|
+
function parseText(text, firstNode, lastNode) {
|
|
762
|
+
const words = [];
|
|
763
|
+
const pattern = /(\w+(?:[^\s\w]\w+)*|:\w+:|[^\s\w]+|\s+)/gu;
|
|
764
|
+
let match;
|
|
765
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
766
|
+
const token = match[1];
|
|
767
|
+
if (/^\s+$/.test(token)) continue;
|
|
768
|
+
const punctuation = /^(?::\w+:|[^\s\w]+)$/.test(token);
|
|
769
|
+
words.push({
|
|
770
|
+
word: token,
|
|
771
|
+
offset: match.index,
|
|
772
|
+
punctuation,
|
|
773
|
+
first: false,
|
|
774
|
+
last: false
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
if (firstNode) {
|
|
778
|
+
for (const w of words) if (!w.punctuation) {
|
|
779
|
+
w.first = true;
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (lastNode) for (let i = words.length - 1; i >= 0; i--) {
|
|
784
|
+
const w = words[i];
|
|
785
|
+
if (!w.punctuation) {
|
|
786
|
+
w.last = true;
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return words;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Convert a single word based on case style and context
|
|
794
|
+
*/
|
|
795
|
+
function convertWord({ word, first, last }, caseStyle, minorWords) {
|
|
796
|
+
if (caseStyle === "Title Case") {
|
|
797
|
+
if (first || last) return {
|
|
798
|
+
word: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),
|
|
799
|
+
isMinorWord: false
|
|
800
|
+
};
|
|
801
|
+
if (minorWords.some((minorWord) => minorWord.toLowerCase() === word.toLowerCase())) return {
|
|
802
|
+
word: word.toLowerCase(),
|
|
803
|
+
isMinorWord: true
|
|
804
|
+
};
|
|
805
|
+
return {
|
|
806
|
+
word: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),
|
|
807
|
+
isMinorWord: false
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
if (first) return {
|
|
811
|
+
word: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),
|
|
812
|
+
isMinorWord: false
|
|
813
|
+
};
|
|
814
|
+
return {
|
|
815
|
+
word: word.toLowerCase(),
|
|
816
|
+
isMinorWord: false
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
var heading_casing_default = createRule("heading-casing", {
|
|
820
|
+
meta: {
|
|
821
|
+
type: "suggestion",
|
|
822
|
+
docs: {
|
|
823
|
+
description: "enforce consistent casing in headings.",
|
|
824
|
+
categories: [],
|
|
825
|
+
listCategory: "Stylistic"
|
|
826
|
+
},
|
|
827
|
+
fixable: "code",
|
|
828
|
+
hasSuggestions: false,
|
|
829
|
+
schema: [{
|
|
830
|
+
type: "object",
|
|
831
|
+
properties: {
|
|
832
|
+
style: { enum: ["Title Case", "Sentence case"] },
|
|
833
|
+
preserveWords: {
|
|
834
|
+
type: "array",
|
|
835
|
+
items: { type: "string" },
|
|
836
|
+
description: "Words that should be preserved as-is (case-insensitive matching)"
|
|
837
|
+
},
|
|
838
|
+
ignorePatterns: {
|
|
839
|
+
type: "array",
|
|
840
|
+
items: { type: "string" },
|
|
841
|
+
description: "Regular expression patterns for words to ignore during casing checks"
|
|
842
|
+
},
|
|
843
|
+
minorWords: {
|
|
844
|
+
type: "array",
|
|
845
|
+
items: { type: "string" },
|
|
846
|
+
description: "Words that should not be capitalized in Title Case (unless they're the first or last word)"
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
additionalProperties: false
|
|
850
|
+
}],
|
|
851
|
+
messages: {
|
|
852
|
+
expectedTitleCase: "Expected \"{{actual}}\" to be \"{{expected}}\" (Title Case).",
|
|
853
|
+
expectedTitleCaseMinorWord: "Expected \"{{actual}}\" to be \"{{expected}}\" (Title Case - minor word).",
|
|
854
|
+
expectedSentenceCase: "Expected \"{{actual}}\" to be \"{{expected}}\" (Sentence case).",
|
|
855
|
+
expectedPreserveWord: "Expected \"{{actual}}\" to be \"{{expected}}\" (preserved word)."
|
|
856
|
+
}
|
|
857
|
+
},
|
|
858
|
+
create(context) {
|
|
859
|
+
const sourceCode = context.sourceCode;
|
|
860
|
+
const caseStyle = context.options[0]?.style || "Title Case";
|
|
861
|
+
const { preserveWords, preservePhrases } = parsePreserveWords(context.options[0]?.preserveWords || defaultPreserveWords);
|
|
862
|
+
const minorWords = context.options[0]?.minorWords || defaultMinorWords;
|
|
863
|
+
const ignorePatterns = (context.options[0]?.ignorePatterns || [
|
|
864
|
+
"/^v\\d+/u",
|
|
865
|
+
"/\\w+\\.[a-z\\d]+$/u",
|
|
866
|
+
"/\\w*(?:API|Api)$/u",
|
|
867
|
+
"/\\w*(?:SDK|Sdk)$/u",
|
|
868
|
+
"/\\w*(?:CLI|Cli)$/u"
|
|
869
|
+
]).map((pattern) => {
|
|
870
|
+
if (isRegExp(pattern)) return toRegExp(pattern);
|
|
871
|
+
try {
|
|
872
|
+
return new RegExp(pattern, "v");
|
|
873
|
+
} catch {}
|
|
874
|
+
try {
|
|
875
|
+
return new RegExp(pattern, "u");
|
|
876
|
+
} catch {}
|
|
877
|
+
return new RegExp(pattern);
|
|
878
|
+
});
|
|
879
|
+
/**
|
|
880
|
+
* Check text node and report word-level errors
|
|
881
|
+
*/
|
|
882
|
+
function checkTextNode(node, firstNode, lastNode) {
|
|
883
|
+
const text = sourceCode.getText(node);
|
|
884
|
+
const wordAndOffsets = parseText(text, firstNode, lastNode);
|
|
885
|
+
const processed = /* @__PURE__ */ new Set();
|
|
886
|
+
for (let index = 0; index < wordAndOffsets.length; index++) {
|
|
887
|
+
if (processed.has(index)) continue;
|
|
888
|
+
processed.add(index);
|
|
889
|
+
const wordAndOffset = wordAndOffsets[index];
|
|
890
|
+
if (wordAndOffset.punctuation) continue;
|
|
891
|
+
if (ignorePatterns.some((pattern) => pattern.test(wordAndOffset.word))) continue;
|
|
892
|
+
const preservePhrase = findPreservePhrase(wordAndOffsets, index);
|
|
893
|
+
if (preservePhrase) {
|
|
894
|
+
for (let wordIndex = 0; wordIndex < preservePhrase.length; wordIndex++) {
|
|
895
|
+
processed.add(index + wordIndex);
|
|
896
|
+
verifyWord(wordAndOffsets[index + wordIndex], preservePhrase[wordIndex], "preserved");
|
|
897
|
+
}
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
const preserveWordList = preserveWords.get(wordAndOffset.word.toLowerCase());
|
|
901
|
+
if (preserveWordList) {
|
|
902
|
+
if (!preserveWordList.some((w) => w === wordAndOffset.word)) verifyWord(wordAndOffset, preserveWordList[0], "preserved");
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
const expectedWordResult = convertWord(wordAndOffset, caseStyle, minorWords);
|
|
906
|
+
verifyWord(wordAndOffset, expectedWordResult.word, expectedWordResult.isMinorWord ? "minor" : "normal");
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Verify a single word against the expected casing
|
|
910
|
+
*/
|
|
911
|
+
function verifyWord(wordAndOffset, expectedWord, wordType = "normal") {
|
|
912
|
+
const { word, offset } = wordAndOffset;
|
|
913
|
+
if (word === expectedWord) return;
|
|
914
|
+
const nodeLoc = sourceCode.getLoc(node);
|
|
915
|
+
const beforeLines = text.slice(0, offset).split(/\n/u);
|
|
916
|
+
const line = nodeLoc.start.line + beforeLines.length - 1;
|
|
917
|
+
const column = (beforeLines.length === 1 ? nodeLoc.start.column : 1) + (beforeLines.at(-1) || "").length;
|
|
918
|
+
const nodeRange = sourceCode.getRange(node);
|
|
919
|
+
const wordRange = [nodeRange[0] + offset, nodeRange[0] + offset + word.length];
|
|
920
|
+
context.report({
|
|
921
|
+
node,
|
|
922
|
+
messageId: wordType === "preserved" ? "expectedPreserveWord" : caseStyle === "Title Case" ? wordType === "minor" ? "expectedTitleCaseMinorWord" : "expectedTitleCase" : "expectedSentenceCase",
|
|
923
|
+
data: {
|
|
924
|
+
actual: word,
|
|
925
|
+
expected: expectedWord
|
|
926
|
+
},
|
|
927
|
+
loc: {
|
|
928
|
+
start: {
|
|
929
|
+
line,
|
|
930
|
+
column
|
|
931
|
+
},
|
|
932
|
+
end: {
|
|
933
|
+
line,
|
|
934
|
+
column: column + word.length
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
fix(fixer) {
|
|
938
|
+
return fixer.replaceTextRange(wordRange, expectedWord);
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Find a preserve phrase starting from the given index
|
|
945
|
+
* Returns the longest matching phrase or null if no match is found
|
|
946
|
+
*/
|
|
947
|
+
function findPreservePhrase(wordAndOffsets, index) {
|
|
948
|
+
const firstWord = wordAndOffsets[index];
|
|
949
|
+
if (firstWord.punctuation) return null;
|
|
950
|
+
const firstLowerWord = firstWord.word.toLowerCase();
|
|
951
|
+
let returnCandidate = null;
|
|
952
|
+
let subWords = null;
|
|
953
|
+
for (const phrase of preservePhrases) {
|
|
954
|
+
if (returnCandidate && returnCandidate.preservePhrase.length !== phrase.length) break;
|
|
955
|
+
if (firstLowerWord !== phrase[0].toLowerCase()) continue;
|
|
956
|
+
if (!subWords || subWords.length !== phrase.length) subWords = wordAndOffsets.slice(index, index + phrase.length).map((wo) => wo.word);
|
|
957
|
+
if (subWords.length === phrase.length && subWords.every((word, i) => word.toLowerCase() === phrase[i].toLowerCase())) {
|
|
958
|
+
let matchCount = 0;
|
|
959
|
+
for (let i = 0; i < subWords.length; i++) {
|
|
960
|
+
const word = subWords[i];
|
|
961
|
+
if (word === phrase[i]) matchCount++;
|
|
962
|
+
}
|
|
963
|
+
if (!returnCandidate || matchCount > returnCandidate.matchCount) returnCandidate = {
|
|
964
|
+
preservePhrase: phrase,
|
|
965
|
+
matchCount
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
return returnCandidate?.preservePhrase ?? null;
|
|
970
|
+
}
|
|
971
|
+
return { heading(node) {
|
|
972
|
+
if (!node.children.length) return;
|
|
973
|
+
const children = node.children.filter((child) => child.type !== "text" || child.value.trim());
|
|
974
|
+
children.forEach((child, i) => {
|
|
975
|
+
if (child.type === "text") checkTextNode(child, i === 0, i === node.children.length - 1);
|
|
976
|
+
});
|
|
977
|
+
} };
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
|
|
114
981
|
//#endregion
|
|
115
982
|
//#region src/rules/no-text-backslash-linebreak.ts
|
|
116
983
|
var no_text_backslash_linebreak_default = createRule("no-text-backslash-linebreak", {
|
|
@@ -749,31 +1616,6 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
749
1616
|
}
|
|
750
1617
|
});
|
|
751
1618
|
|
|
752
|
-
//#endregion
|
|
753
|
-
//#region src/utils/regexp.ts
|
|
754
|
-
const RE_REGEXP_STR = /^\/(.+)\/([A-Za-z]*)$/u;
|
|
755
|
-
/**
|
|
756
|
-
* Convert a string to the `RegExp`.
|
|
757
|
-
* Normal strings (e.g. `"foo"`) is converted to `/^foo$/` of `RegExp`.
|
|
758
|
-
* Strings like `"/^foo/i"` are converted to `/^foo/i` of `RegExp`.
|
|
759
|
-
*
|
|
760
|
-
* @param {string} string The string to convert.
|
|
761
|
-
* @returns {RegExp} Returns the `RegExp`.
|
|
762
|
-
*/
|
|
763
|
-
function toRegExp(string) {
|
|
764
|
-
const parts = RE_REGEXP_STR.exec(string);
|
|
765
|
-
if (parts) return new RegExp(parts[1], parts[2]);
|
|
766
|
-
return { test: (s) => s === string };
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Checks whether given string is regexp string
|
|
770
|
-
* @param {string} string
|
|
771
|
-
* @returns {boolean}
|
|
772
|
-
*/
|
|
773
|
-
function isRegExp(string) {
|
|
774
|
-
return Boolean(RE_REGEXP_STR.test(string));
|
|
775
|
-
}
|
|
776
|
-
|
|
777
1619
|
//#endregion
|
|
778
1620
|
//#region src/rules/sort-definitions.ts
|
|
779
1621
|
var sort_definitions_default = createRule("sort-definitions", {
|
|
@@ -1060,8 +1902,10 @@ function normalizedURL(url) {
|
|
|
1060
1902
|
//#endregion
|
|
1061
1903
|
//#region src/utils/rules.ts
|
|
1062
1904
|
const rules$1 = [
|
|
1905
|
+
canonical_code_block_language_default,
|
|
1063
1906
|
definitions_last_default,
|
|
1064
1907
|
hard_linebreak_style_default,
|
|
1908
|
+
heading_casing_default,
|
|
1065
1909
|
no_text_backslash_linebreak_default,
|
|
1066
1910
|
no_trailing_spaces_default,
|
|
1067
1911
|
prefer_inline_code_words_default,
|
|
@@ -1102,7 +1946,7 @@ __export(meta_exports, {
|
|
|
1102
1946
|
version: () => version
|
|
1103
1947
|
});
|
|
1104
1948
|
const name = "eslint-plugin-markdown-preferences";
|
|
1105
|
-
const version = "0.
|
|
1949
|
+
const version = "0.9.0";
|
|
1106
1950
|
|
|
1107
1951
|
//#endregion
|
|
1108
1952
|
//#region src/index.ts
|
|
@@ -1111,11 +1955,16 @@ const rules = rules$1.reduce((obj, r) => {
|
|
|
1111
1955
|
obj[r.meta.docs.ruleName] = r;
|
|
1112
1956
|
return obj;
|
|
1113
1957
|
}, {});
|
|
1958
|
+
const resources = {
|
|
1959
|
+
defaultPreserveWords,
|
|
1960
|
+
defaultMinorWords
|
|
1961
|
+
};
|
|
1114
1962
|
var src_default = {
|
|
1115
1963
|
meta: meta_exports,
|
|
1116
1964
|
configs,
|
|
1117
|
-
rules
|
|
1965
|
+
rules,
|
|
1966
|
+
resources
|
|
1118
1967
|
};
|
|
1119
1968
|
|
|
1120
1969
|
//#endregion
|
|
1121
|
-
export { configs, src_default as default, meta_exports as meta, rules };
|
|
1970
|
+
export { configs, src_default as default, meta_exports as meta, resources, rules };
|