eslint-plugin-markdown-preferences 0.9.0 → 0.11.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 +13 -5
- package/lib/index.d.ts +31 -3
- package/lib/index.js +495 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ Example **eslint.config.js**:
|
|
|
50
50
|
```js
|
|
51
51
|
import { defineConfig } from "eslint/config";
|
|
52
52
|
// import markdown from "@eslint/markdown";
|
|
53
|
-
import markdownPreferences from
|
|
53
|
+
import markdownPreferences from "eslint-plugin-markdown-preferences";
|
|
54
54
|
export default [
|
|
55
55
|
// add more generic rule sets here, such as:
|
|
56
56
|
// markdown.configs.recommended,
|
|
@@ -59,8 +59,8 @@ export default [
|
|
|
59
59
|
rules: {
|
|
60
60
|
// override/add rules settings here, such as:
|
|
61
61
|
// 'markdown-preferences/prefer-linked-words': 'error'
|
|
62
|
-
}
|
|
63
|
-
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
64
|
];
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -86,10 +86,13 @@ The rules with the following star ⭐ are included in the configs.
|
|
|
86
86
|
|
|
87
87
|
<!--RULES_TABLE_START-->
|
|
88
88
|
|
|
89
|
+
<!-- prettier-ignore-start -->
|
|
90
|
+
|
|
89
91
|
### Preference Rules
|
|
90
92
|
|
|
91
93
|
| Rule ID | Description | Fixable | RECOMMENDED |
|
|
92
94
|
|:--------|:------------|:-------:|:-----------:|
|
|
95
|
+
| [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 | 🔧 | |
|
|
93
96
|
| [markdown-preferences/no-text-backslash-linebreak](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html) | disallow text backslash at the end of a line. | | ⭐ |
|
|
94
97
|
| [markdown-preferences/prefer-inline-code-words](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-inline-code-words.html) | enforce the use of inline code for specific words. | 🔧 | |
|
|
95
98
|
| [markdown-preferences/prefer-linked-words](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-linked-words.html) | enforce the specified word to be a link. | 🔧 | |
|
|
@@ -98,14 +101,19 @@ The rules with the following star ⭐ are included in the configs.
|
|
|
98
101
|
|
|
99
102
|
| Rule ID | Description | Fixable | RECOMMENDED |
|
|
100
103
|
|:--------|:------------|:-------:|:-----------:|
|
|
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 | 🔧 | |
|
|
102
104
|
| [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 | 🔧 | |
|
|
103
105
|
| [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
106
|
| [markdown-preferences/heading-casing](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/heading-casing.html) | enforce consistent casing in headings. | 🔧 | |
|
|
107
|
+
| [markdown-preferences/no-laziness-blockquotes](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-laziness-blockquotes.html) | disallow laziness in blockquotes | | ⭐ |
|
|
108
|
+
| [markdown-preferences/no-multiple-empty-lines](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-multiple-empty-lines.html) | disallow multiple empty lines in Markdown files. | 🔧 | |
|
|
105
109
|
| [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. | 🔧 | |
|
|
110
|
+
| [markdown-preferences/prefer-autolinks](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-autolinks.html) | enforce the use of autolinks for URLs | 🔧 | ⭐ |
|
|
111
|
+
| [markdown-preferences/prefer-fenced-code-blocks](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-fenced-code-blocks.html) | enforce the use of fenced code blocks over indented code blocks | 🔧 | ⭐ |
|
|
106
112
|
| [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 | 🔧 | |
|
|
107
113
|
| [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 | 🔧 | |
|
|
108
114
|
|
|
115
|
+
<!-- prettier-ignore-end -->
|
|
116
|
+
|
|
109
117
|
<!--RULES_TABLE_END-->
|
|
110
118
|
<!--RULES_SECTION_END-->
|
|
111
119
|
<!--DOCS_IGNORE_START-->
|
|
@@ -123,7 +131,7 @@ Please use GitHub's Issues/PRs.
|
|
|
123
131
|
|
|
124
132
|
## 🔒 License
|
|
125
133
|
|
|
126
|
-
See the [LICENSE](LICENSE) file for license rights and limitations (MIT).
|
|
134
|
+
See the [LICENSE](./LICENSE) file for license rights and limitations (MIT).
|
|
127
135
|
|
|
128
136
|
[npm-package]: https://www.npmjs.com/package/eslint-plugin-markdown-preferences
|
|
129
137
|
[npmtrends]: http://www.npmtrends.com/eslint-plugin-markdown-preferences
|
package/lib/index.d.ts
CHANGED
|
@@ -30,6 +30,16 @@ interface RuleOptions {
|
|
|
30
30
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/heading-casing.html
|
|
31
31
|
*/
|
|
32
32
|
'markdown-preferences/heading-casing'?: Linter.RuleEntry<MarkdownPreferencesHeadingCasing>;
|
|
33
|
+
/**
|
|
34
|
+
* disallow laziness in blockquotes
|
|
35
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-laziness-blockquotes.html
|
|
36
|
+
*/
|
|
37
|
+
'markdown-preferences/no-laziness-blockquotes'?: Linter.RuleEntry<[]>;
|
|
38
|
+
/**
|
|
39
|
+
* disallow multiple empty lines in Markdown files.
|
|
40
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-multiple-empty-lines.html
|
|
41
|
+
*/
|
|
42
|
+
'markdown-preferences/no-multiple-empty-lines'?: Linter.RuleEntry<MarkdownPreferencesNoMultipleEmptyLines>;
|
|
33
43
|
/**
|
|
34
44
|
* disallow text backslash at the end of a line.
|
|
35
45
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html
|
|
@@ -40,6 +50,16 @@ interface RuleOptions {
|
|
|
40
50
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html
|
|
41
51
|
*/
|
|
42
52
|
'markdown-preferences/no-trailing-spaces'?: Linter.RuleEntry<MarkdownPreferencesNoTrailingSpaces>;
|
|
53
|
+
/**
|
|
54
|
+
* enforce the use of autolinks for URLs
|
|
55
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-autolinks.html
|
|
56
|
+
*/
|
|
57
|
+
'markdown-preferences/prefer-autolinks'?: Linter.RuleEntry<[]>;
|
|
58
|
+
/**
|
|
59
|
+
* enforce the use of fenced code blocks over indented code blocks
|
|
60
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-fenced-code-blocks.html
|
|
61
|
+
*/
|
|
62
|
+
'markdown-preferences/prefer-fenced-code-blocks'?: Linter.RuleEntry<[]>;
|
|
43
63
|
/**
|
|
44
64
|
* enforce the use of inline code for specific words.
|
|
45
65
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-inline-code-words.html
|
|
@@ -75,6 +95,11 @@ type MarkdownPreferencesHeadingCasing = [] | [{
|
|
|
75
95
|
ignorePatterns?: string[];
|
|
76
96
|
minorWords?: string[];
|
|
77
97
|
}];
|
|
98
|
+
type MarkdownPreferencesNoMultipleEmptyLines = [] | [{
|
|
99
|
+
max?: number;
|
|
100
|
+
maxEOF?: number;
|
|
101
|
+
maxBOF?: number;
|
|
102
|
+
}];
|
|
78
103
|
type MarkdownPreferencesNoTrailingSpaces = [] | [{
|
|
79
104
|
skipBlankLines?: boolean;
|
|
80
105
|
ignoreComments?: boolean;
|
|
@@ -114,11 +139,14 @@ type MarkdownPreferencesSortDefinitions = [] | [{
|
|
|
114
139
|
alphabetical?: boolean;
|
|
115
140
|
}];
|
|
116
141
|
declare namespace recommended_d_exports {
|
|
117
|
-
export { files, language, name$1 as name, plugins, rules$1 as rules };
|
|
142
|
+
export { files, language, languageOptions, name$1 as name, plugins, rules$1 as rules };
|
|
118
143
|
}
|
|
119
144
|
declare const name$1 = "markdown-preferences/recommended";
|
|
120
145
|
declare const files: string[];
|
|
121
|
-
declare const language = "markdown/
|
|
146
|
+
declare const language = "markdown/gfm";
|
|
147
|
+
declare const languageOptions: {
|
|
148
|
+
frontmatter: string;
|
|
149
|
+
};
|
|
122
150
|
declare const plugins: {
|
|
123
151
|
markdown: typeof markdown;
|
|
124
152
|
readonly "markdown-preferences": ESLint.Plugin;
|
|
@@ -128,7 +156,7 @@ declare namespace meta_d_exports {
|
|
|
128
156
|
export { name, version };
|
|
129
157
|
}
|
|
130
158
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
131
|
-
declare const version: "0.
|
|
159
|
+
declare const version: "0.11.0";
|
|
132
160
|
//#endregion
|
|
133
161
|
//#region src/index.d.ts
|
|
134
162
|
declare const configs: {
|
package/lib/index.js
CHANGED
|
@@ -56,7 +56,7 @@ var canonical_code_block_language_default = createRule("canonical-code-block-lan
|
|
|
56
56
|
docs: {
|
|
57
57
|
description: "enforce canonical language names in code blocks",
|
|
58
58
|
categories: [],
|
|
59
|
-
listCategory: "
|
|
59
|
+
listCategory: "Preference"
|
|
60
60
|
},
|
|
61
61
|
fixable: "code",
|
|
62
62
|
hasSuggestions: false,
|
|
@@ -978,6 +978,333 @@ var heading_casing_default = createRule("heading-casing", {
|
|
|
978
978
|
}
|
|
979
979
|
});
|
|
980
980
|
|
|
981
|
+
//#endregion
|
|
982
|
+
//#region src/utils/lines.ts
|
|
983
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
984
|
+
var ParsedLines = class {
|
|
985
|
+
lines;
|
|
986
|
+
constructor(codeText) {
|
|
987
|
+
let offset = 0;
|
|
988
|
+
this.lines = codeText.split(/(?<=\n)/u).map((lineText, index) => {
|
|
989
|
+
const start = offset;
|
|
990
|
+
offset += lineText.length;
|
|
991
|
+
const range = [start, offset];
|
|
992
|
+
let text = lineText;
|
|
993
|
+
let linebreak = "";
|
|
994
|
+
if (text.at(-1) === "\n") {
|
|
995
|
+
text = text.slice(0, -1);
|
|
996
|
+
linebreak = "\n";
|
|
997
|
+
}
|
|
998
|
+
if (text.at(-1) === "\r") {
|
|
999
|
+
text = text.slice(0, -1);
|
|
1000
|
+
linebreak = `\r${linebreak}`;
|
|
1001
|
+
}
|
|
1002
|
+
return {
|
|
1003
|
+
text,
|
|
1004
|
+
range,
|
|
1005
|
+
line: index + 1,
|
|
1006
|
+
linebreak
|
|
1007
|
+
};
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
[Symbol.iterator]() {
|
|
1011
|
+
return this.lines[Symbol.iterator]();
|
|
1012
|
+
}
|
|
1013
|
+
get length() {
|
|
1014
|
+
return this.lines.length;
|
|
1015
|
+
}
|
|
1016
|
+
get(lineNumber) {
|
|
1017
|
+
return this.lines[lineNumber - 1];
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Parse the lines of the source code.
|
|
1022
|
+
* @param sourceCode source code to parse
|
|
1023
|
+
* @returns parsed lines
|
|
1024
|
+
*/
|
|
1025
|
+
function parseLines(sourceCode) {
|
|
1026
|
+
const cached = cache.get(sourceCode);
|
|
1027
|
+
if (cached) return cached;
|
|
1028
|
+
const parsedLines = new ParsedLines(sourceCode.text);
|
|
1029
|
+
cache.set(sourceCode, parsedLines);
|
|
1030
|
+
return parsedLines;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
//#endregion
|
|
1034
|
+
//#region src/rules/no-laziness-blockquotes.ts
|
|
1035
|
+
/**
|
|
1036
|
+
* Helper function to get blockquote line information.
|
|
1037
|
+
*/
|
|
1038
|
+
function getBlockquoteLineInfo(line) {
|
|
1039
|
+
const regex = /^\s*(?:>\s*)*/u;
|
|
1040
|
+
const match = regex.exec(line.text);
|
|
1041
|
+
return {
|
|
1042
|
+
line,
|
|
1043
|
+
prefix: match[0],
|
|
1044
|
+
level: (match[0].match(/>/gu) || []).length
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
1048
|
+
meta: {
|
|
1049
|
+
type: "problem",
|
|
1050
|
+
docs: {
|
|
1051
|
+
description: "disallow laziness in blockquotes",
|
|
1052
|
+
categories: ["recommended"],
|
|
1053
|
+
listCategory: "Stylistic"
|
|
1054
|
+
},
|
|
1055
|
+
fixable: void 0,
|
|
1056
|
+
hasSuggestions: true,
|
|
1057
|
+
schema: [],
|
|
1058
|
+
messages: {
|
|
1059
|
+
lazyBlockquoteLine: "Expected {{level}} '>' marker(s), but found {{actualLevel}}. This line will be interpreted as part of level {{level}} blockquote.",
|
|
1060
|
+
addMarker: "Add {{missingMarkers}} '>' marker(s).",
|
|
1061
|
+
addLineBreak: "Add line break to separate from blockquote."
|
|
1062
|
+
}
|
|
1063
|
+
},
|
|
1064
|
+
create(context) {
|
|
1065
|
+
const sourceCode = context.sourceCode;
|
|
1066
|
+
const checkedLines = /* @__PURE__ */ new Set();
|
|
1067
|
+
const lines = parseLines(sourceCode);
|
|
1068
|
+
/**
|
|
1069
|
+
* Report invalid blockquote lines.
|
|
1070
|
+
*/
|
|
1071
|
+
function reportInvalidLines(invalidLines, base) {
|
|
1072
|
+
const invalidGroups = [];
|
|
1073
|
+
for (const invalidLine of invalidLines) {
|
|
1074
|
+
const currentGroup = invalidGroups.at(-1);
|
|
1075
|
+
if (!currentGroup || currentGroup.level < invalidLine.level) {
|
|
1076
|
+
invalidGroups.push({
|
|
1077
|
+
level: invalidLine.level,
|
|
1078
|
+
lines: [invalidLine]
|
|
1079
|
+
});
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
if (currentGroup.level === invalidLine.level) {
|
|
1083
|
+
currentGroup.lines.push(invalidLine);
|
|
1084
|
+
continue;
|
|
1085
|
+
}
|
|
1086
|
+
if (invalidLine.level < currentGroup.level) break;
|
|
1087
|
+
}
|
|
1088
|
+
for (const group of invalidGroups) {
|
|
1089
|
+
const first = group.lines[0];
|
|
1090
|
+
const last = group.lines.at(-1);
|
|
1091
|
+
context.report({
|
|
1092
|
+
loc: {
|
|
1093
|
+
start: {
|
|
1094
|
+
line: first.line.line,
|
|
1095
|
+
column: 1
|
|
1096
|
+
},
|
|
1097
|
+
end: {
|
|
1098
|
+
line: last.line.line,
|
|
1099
|
+
column: last.line.text.length + 1
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
messageId: "lazyBlockquoteLine",
|
|
1103
|
+
data: {
|
|
1104
|
+
level: `${base.level}`,
|
|
1105
|
+
actualLevel: `${group.level}`
|
|
1106
|
+
},
|
|
1107
|
+
suggest: [{
|
|
1108
|
+
messageId: "addMarker",
|
|
1109
|
+
data: { missingMarkers: `${base.level - group.level}` },
|
|
1110
|
+
*fix(fixer) {
|
|
1111
|
+
for (const invalidLine of group.lines) yield fixer.replaceTextRange([invalidLine.line.range[0], invalidLine.line.range[0] + invalidLine.prefix.length], base.prefix);
|
|
1112
|
+
}
|
|
1113
|
+
}, {
|
|
1114
|
+
messageId: "addLineBreak",
|
|
1115
|
+
fix: (fixer) => {
|
|
1116
|
+
return fixer.insertTextBeforeRange([first.line.range[0], first.line.range[0]], `${first.prefix.trimEnd()}\n`);
|
|
1117
|
+
}
|
|
1118
|
+
}]
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return { "blockquote:exit"(node) {
|
|
1123
|
+
const loc = sourceCode.getLoc(node);
|
|
1124
|
+
const startLine = loc.start.line;
|
|
1125
|
+
const endLine = loc.end.line;
|
|
1126
|
+
const base = getBlockquoteLineInfo(lines.get(startLine));
|
|
1127
|
+
const invalidLines = [];
|
|
1128
|
+
for (let lineNumber = startLine + 1; lineNumber <= endLine; lineNumber++) {
|
|
1129
|
+
if (checkedLines.has(lineNumber)) {
|
|
1130
|
+
reportInvalidLines(invalidLines, base);
|
|
1131
|
+
invalidLines.length = 0;
|
|
1132
|
+
continue;
|
|
1133
|
+
}
|
|
1134
|
+
checkedLines.add(lineNumber);
|
|
1135
|
+
const line = lines.get(lineNumber);
|
|
1136
|
+
const current = getBlockquoteLineInfo(line);
|
|
1137
|
+
if (base.level <= current.level) {
|
|
1138
|
+
reportInvalidLines(invalidLines, base);
|
|
1139
|
+
invalidLines.length = 0;
|
|
1140
|
+
continue;
|
|
1141
|
+
}
|
|
1142
|
+
invalidLines.push(current);
|
|
1143
|
+
}
|
|
1144
|
+
reportInvalidLines(invalidLines, base);
|
|
1145
|
+
} };
|
|
1146
|
+
}
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
//#endregion
|
|
1150
|
+
//#region src/rules/no-multiple-empty-lines.ts
|
|
1151
|
+
var no_multiple_empty_lines_default = createRule("no-multiple-empty-lines", {
|
|
1152
|
+
meta: {
|
|
1153
|
+
type: "layout",
|
|
1154
|
+
docs: {
|
|
1155
|
+
description: "disallow multiple empty lines in Markdown files.",
|
|
1156
|
+
categories: null,
|
|
1157
|
+
listCategory: "Stylistic"
|
|
1158
|
+
},
|
|
1159
|
+
fixable: "whitespace",
|
|
1160
|
+
hasSuggestions: false,
|
|
1161
|
+
schema: [{
|
|
1162
|
+
type: "object",
|
|
1163
|
+
properties: {
|
|
1164
|
+
max: {
|
|
1165
|
+
type: "integer",
|
|
1166
|
+
minimum: 0,
|
|
1167
|
+
default: 1
|
|
1168
|
+
},
|
|
1169
|
+
maxEOF: {
|
|
1170
|
+
type: "integer",
|
|
1171
|
+
minimum: 0,
|
|
1172
|
+
default: 0
|
|
1173
|
+
},
|
|
1174
|
+
maxBOF: {
|
|
1175
|
+
type: "integer",
|
|
1176
|
+
minimum: 0,
|
|
1177
|
+
default: 0
|
|
1178
|
+
}
|
|
1179
|
+
},
|
|
1180
|
+
additionalProperties: false
|
|
1181
|
+
}],
|
|
1182
|
+
messages: {
|
|
1183
|
+
blankBeginningOfFile: "Too many blank lines at the beginning of file. Max of {{max}} allowed.",
|
|
1184
|
+
blankEndOfFile: "Too many blank lines at the end of file. Max of {{max}} allowed.",
|
|
1185
|
+
consecutiveBlank: "More than {{max}} blank {{pluralizedLines}} not allowed."
|
|
1186
|
+
}
|
|
1187
|
+
},
|
|
1188
|
+
create(context) {
|
|
1189
|
+
const sourceCode = context.sourceCode;
|
|
1190
|
+
const option = context.options[0] || {};
|
|
1191
|
+
const max = typeof option.max === "number" ? option.max : 1;
|
|
1192
|
+
const maxEOF = typeof option.maxEOF === "number" ? option.maxEOF : 0;
|
|
1193
|
+
const maxBOF = typeof option.maxBOF === "number" ? option.maxBOF : 0;
|
|
1194
|
+
const ignoreLocs = [];
|
|
1195
|
+
/**
|
|
1196
|
+
* Register the range of nodes to ignore (code, html, yaml, toml, json)
|
|
1197
|
+
* @param node mdast node
|
|
1198
|
+
*/
|
|
1199
|
+
function addIgnoreLoc(node) {
|
|
1200
|
+
const loc = sourceCode.getLoc(node);
|
|
1201
|
+
ignoreLocs.push({
|
|
1202
|
+
startLine: loc.start.line,
|
|
1203
|
+
endLine: loc.end.line
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
return {
|
|
1207
|
+
code: addIgnoreLoc,
|
|
1208
|
+
html: addIgnoreLoc,
|
|
1209
|
+
yaml: addIgnoreLoc,
|
|
1210
|
+
toml: addIgnoreLoc,
|
|
1211
|
+
json: addIgnoreLoc,
|
|
1212
|
+
"root:exit"() {
|
|
1213
|
+
const lines = [...parseLines(sourceCode)];
|
|
1214
|
+
const bofEmptyLines = [];
|
|
1215
|
+
while (lines.length) {
|
|
1216
|
+
if (lines[0].text.trim()) break;
|
|
1217
|
+
bofEmptyLines.push(lines.shift());
|
|
1218
|
+
}
|
|
1219
|
+
const invalidBOFEmptyLines = bofEmptyLines.slice(maxBOF);
|
|
1220
|
+
if (invalidBOFEmptyLines.length > 0) {
|
|
1221
|
+
const first = invalidBOFEmptyLines[0];
|
|
1222
|
+
const last = invalidBOFEmptyLines[invalidBOFEmptyLines.length - 1];
|
|
1223
|
+
context.report({
|
|
1224
|
+
loc: {
|
|
1225
|
+
start: {
|
|
1226
|
+
line: first.line,
|
|
1227
|
+
column: 1
|
|
1228
|
+
},
|
|
1229
|
+
end: {
|
|
1230
|
+
line: last.line,
|
|
1231
|
+
column: last.text.length + 1
|
|
1232
|
+
}
|
|
1233
|
+
},
|
|
1234
|
+
messageId: "blankBeginningOfFile",
|
|
1235
|
+
data: { max: maxBOF },
|
|
1236
|
+
fix(fixer) {
|
|
1237
|
+
return fixer.removeRange([first.range[0], last.range[1]]);
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
const eofEmptyLines = [];
|
|
1242
|
+
while (lines.length) {
|
|
1243
|
+
if (lines[lines.length - 1].text.trim()) break;
|
|
1244
|
+
eofEmptyLines.unshift(lines.pop());
|
|
1245
|
+
}
|
|
1246
|
+
const invalidEOFEmptyLines = eofEmptyLines.slice(maxEOF);
|
|
1247
|
+
if (invalidEOFEmptyLines.length > 0) {
|
|
1248
|
+
const first = invalidEOFEmptyLines[0];
|
|
1249
|
+
const last = invalidEOFEmptyLines[invalidEOFEmptyLines.length - 1];
|
|
1250
|
+
context.report({
|
|
1251
|
+
loc: {
|
|
1252
|
+
start: {
|
|
1253
|
+
line: first.line,
|
|
1254
|
+
column: 1
|
|
1255
|
+
},
|
|
1256
|
+
end: {
|
|
1257
|
+
line: last.line,
|
|
1258
|
+
column: last.text.length + 1
|
|
1259
|
+
}
|
|
1260
|
+
},
|
|
1261
|
+
messageId: "blankEndOfFile",
|
|
1262
|
+
data: { max: maxEOF },
|
|
1263
|
+
fix(fixer) {
|
|
1264
|
+
return fixer.removeRange([first.range[0], last.range[1]]);
|
|
1265
|
+
}
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
const emptyLines = [];
|
|
1269
|
+
for (const lineInfo of lines) {
|
|
1270
|
+
if (!lineInfo.text.trim() && !ignoreLocs.some(({ startLine, endLine }) => {
|
|
1271
|
+
return lineInfo.line > startLine && lineInfo.line < endLine;
|
|
1272
|
+
})) {
|
|
1273
|
+
emptyLines.push(lineInfo);
|
|
1274
|
+
continue;
|
|
1275
|
+
}
|
|
1276
|
+
const invalidEmptyLines = emptyLines.slice(max);
|
|
1277
|
+
emptyLines.length = 0;
|
|
1278
|
+
if (invalidEmptyLines.length) {
|
|
1279
|
+
const first = invalidEmptyLines[0];
|
|
1280
|
+
const last = invalidEmptyLines[invalidEmptyLines.length - 1];
|
|
1281
|
+
context.report({
|
|
1282
|
+
loc: {
|
|
1283
|
+
start: {
|
|
1284
|
+
line: first.line,
|
|
1285
|
+
column: 1
|
|
1286
|
+
},
|
|
1287
|
+
end: {
|
|
1288
|
+
line: last.line,
|
|
1289
|
+
column: last.text.length + 1
|
|
1290
|
+
}
|
|
1291
|
+
},
|
|
1292
|
+
messageId: "consecutiveBlank",
|
|
1293
|
+
data: {
|
|
1294
|
+
max,
|
|
1295
|
+
pluralizedLines: max === 1 ? "line" : "lines"
|
|
1296
|
+
},
|
|
1297
|
+
fix(fixer) {
|
|
1298
|
+
return fixer.removeRange([first.range[0], last.range[1]]);
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
});
|
|
1307
|
+
|
|
981
1308
|
//#endregion
|
|
982
1309
|
//#region src/rules/no-text-backslash-linebreak.ts
|
|
983
1310
|
var no_text_backslash_linebreak_default = createRule("no-text-backslash-linebreak", {
|
|
@@ -1109,51 +1436,170 @@ var no_trailing_spaces_default = createRule("no-trailing-spaces", {
|
|
|
1109
1436
|
"root:exit"() {
|
|
1110
1437
|
const re = /[^\S\n\r]+$/u;
|
|
1111
1438
|
const skipMatch = /^[^\S\n\r]*$/u;
|
|
1112
|
-
const lines = sourceCode
|
|
1113
|
-
const linebreaks = sourceCode.text.match(/\r?\n/gu);
|
|
1439
|
+
const lines = parseLines(sourceCode);
|
|
1114
1440
|
const commentLineNumbers = getCommentLineNumbers();
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
|
|
1119
|
-
const lineLength = lines[i].length + linebreakLength;
|
|
1120
|
-
const matches = re.exec(lines[i]);
|
|
1121
|
-
if (!matches) {
|
|
1122
|
-
totalLength += lineLength;
|
|
1123
|
-
continue;
|
|
1124
|
-
}
|
|
1441
|
+
for (const lineInfo of lines) {
|
|
1442
|
+
const matches = re.exec(lineInfo.text);
|
|
1443
|
+
if (!matches) continue;
|
|
1125
1444
|
const location = {
|
|
1126
1445
|
start: {
|
|
1127
|
-
line:
|
|
1446
|
+
line: lineInfo.line,
|
|
1128
1447
|
column: matches.index + 1
|
|
1129
1448
|
},
|
|
1130
1449
|
end: {
|
|
1131
|
-
line:
|
|
1132
|
-
column:
|
|
1450
|
+
line: lineInfo.line,
|
|
1451
|
+
column: matches.index + 1 + matches[0].length
|
|
1133
1452
|
}
|
|
1134
1453
|
};
|
|
1135
|
-
const
|
|
1136
|
-
const rangeEnd = totalLength + location.end.column - 1;
|
|
1454
|
+
const range = [lineInfo.range[0] + location.start.column - 1, lineInfo.range[0] + location.end.column - 1];
|
|
1137
1455
|
if (ignoreNodes.some((node) => {
|
|
1138
|
-
const
|
|
1139
|
-
return
|
|
1140
|
-
}))
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
}
|
|
1144
|
-
if (skipBlankLines && skipMatch.test(lines[i])) {
|
|
1145
|
-
totalLength += lineLength;
|
|
1146
|
-
continue;
|
|
1147
|
-
}
|
|
1148
|
-
const fixRange = [rangeStart, rangeEnd];
|
|
1149
|
-
if (!ignoreComments || !commentLineNumbers.has(lineNumber)) report(location, fixRange);
|
|
1150
|
-
totalLength += lineLength;
|
|
1456
|
+
const nodeRange = sourceCode.getRange(node);
|
|
1457
|
+
return nodeRange[0] <= range[0] && range[1] <= nodeRange[1];
|
|
1458
|
+
})) continue;
|
|
1459
|
+
if (skipBlankLines && skipMatch.test(lineInfo.text)) continue;
|
|
1460
|
+
if (!ignoreComments || !commentLineNumbers.has(lineInfo.line)) report(location, range);
|
|
1151
1461
|
}
|
|
1152
1462
|
}
|
|
1153
1463
|
};
|
|
1154
1464
|
}
|
|
1155
1465
|
});
|
|
1156
1466
|
|
|
1467
|
+
//#endregion
|
|
1468
|
+
//#region src/utils/ast.ts
|
|
1469
|
+
/**
|
|
1470
|
+
* Get the kind of code block.
|
|
1471
|
+
*/
|
|
1472
|
+
function getCodeBlockKind(sourceCode, node) {
|
|
1473
|
+
const text = sourceCode.getText(node);
|
|
1474
|
+
return text.startsWith("```") ? "backtick-fenced" : text.startsWith("~~~") ? "tilde-fenced" : "indented";
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Get the kind of link.
|
|
1478
|
+
*/
|
|
1479
|
+
function getLinkKind(sourceCode, node) {
|
|
1480
|
+
const text = sourceCode.getText(node);
|
|
1481
|
+
return text.startsWith("[") ? "inline" : text.startsWith("<") && text.endsWith(">") ? "autolink" : "gfm-autolink";
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
//#endregion
|
|
1485
|
+
//#region src/rules/prefer-autolinks.ts
|
|
1486
|
+
var prefer_autolinks_default = createRule("prefer-autolinks", {
|
|
1487
|
+
meta: {
|
|
1488
|
+
type: "layout",
|
|
1489
|
+
docs: {
|
|
1490
|
+
description: "enforce the use of autolinks for URLs",
|
|
1491
|
+
categories: ["recommended"],
|
|
1492
|
+
listCategory: "Stylistic"
|
|
1493
|
+
},
|
|
1494
|
+
fixable: "code",
|
|
1495
|
+
hasSuggestions: false,
|
|
1496
|
+
schema: [],
|
|
1497
|
+
messages: {
|
|
1498
|
+
useAutolinkInsteadGFMAutolink: "Use an autolink instead of a GFM autolink (bare url).",
|
|
1499
|
+
useAutolinkInsteadInlineLink: "Use an autolink instead of an inline link with the same URL."
|
|
1500
|
+
}
|
|
1501
|
+
},
|
|
1502
|
+
create(context) {
|
|
1503
|
+
const sourceCode = context.sourceCode;
|
|
1504
|
+
return { link(node) {
|
|
1505
|
+
const kind = getLinkKind(sourceCode, node);
|
|
1506
|
+
if (kind === "autolink") return;
|
|
1507
|
+
if (node.title) return;
|
|
1508
|
+
if (node.children.some((child) => child.type !== "text")) return;
|
|
1509
|
+
const label = node.children.map((child) => child.value).join("");
|
|
1510
|
+
if (node.url !== label) return;
|
|
1511
|
+
context.report({
|
|
1512
|
+
node,
|
|
1513
|
+
messageId: kind === "inline" ? "useAutolinkInsteadInlineLink" : "useAutolinkInsteadGFMAutolink",
|
|
1514
|
+
fix(fixer) {
|
|
1515
|
+
return fixer.replaceText(node, `<${node.url}>`);
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
} };
|
|
1519
|
+
}
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1522
|
+
//#endregion
|
|
1523
|
+
//#region src/rules/prefer-fenced-code-blocks.ts
|
|
1524
|
+
var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks", {
|
|
1525
|
+
meta: {
|
|
1526
|
+
type: "layout",
|
|
1527
|
+
docs: {
|
|
1528
|
+
description: "enforce the use of fenced code blocks over indented code blocks",
|
|
1529
|
+
categories: ["recommended"],
|
|
1530
|
+
listCategory: "Stylistic"
|
|
1531
|
+
},
|
|
1532
|
+
fixable: "code",
|
|
1533
|
+
hasSuggestions: false,
|
|
1534
|
+
schema: [],
|
|
1535
|
+
messages: { useFencedCodeBlock: "Use a fenced code block instead of an indented code block." }
|
|
1536
|
+
},
|
|
1537
|
+
create(context) {
|
|
1538
|
+
const sourceCode = context.sourceCode;
|
|
1539
|
+
const lines = parseLines(sourceCode);
|
|
1540
|
+
return { code(node) {
|
|
1541
|
+
const kind = getCodeBlockKind(sourceCode, node);
|
|
1542
|
+
if (kind === "backtick-fenced" || kind === "tilde-fenced") return;
|
|
1543
|
+
const loc = sourceCode.getLoc(node);
|
|
1544
|
+
context.report({
|
|
1545
|
+
node,
|
|
1546
|
+
messageId: "useFencedCodeBlock",
|
|
1547
|
+
fix(fixer) {
|
|
1548
|
+
if (!isFixableIndentedCodeBlock(node)) return null;
|
|
1549
|
+
const startColumnOffset = loc.start.column - 1;
|
|
1550
|
+
const removeRanges = [];
|
|
1551
|
+
let prefixText = null;
|
|
1552
|
+
for (let line = loc.start.line; line <= loc.end.line; line++) {
|
|
1553
|
+
const parsedLine = lines.get(line);
|
|
1554
|
+
const currentPrefix = normalizePrefix(parsedLine.text.slice(0, startColumnOffset));
|
|
1555
|
+
if (!prefixText) prefixText = currentPrefix;
|
|
1556
|
+
else if (currentPrefix !== prefixText) return null;
|
|
1557
|
+
let removeRange = [parsedLine.range[0] + startColumnOffset, parsedLine.range[0] + startColumnOffset + 4];
|
|
1558
|
+
for (let index = removeRange[0]; index < removeRange[1]; index++) {
|
|
1559
|
+
const c = sourceCode.text[index];
|
|
1560
|
+
if (c === " ") continue;
|
|
1561
|
+
if (c === " ") {
|
|
1562
|
+
removeRange = [removeRange[0], index + 1];
|
|
1563
|
+
break;
|
|
1564
|
+
}
|
|
1565
|
+
return null;
|
|
1566
|
+
}
|
|
1567
|
+
removeRanges.push(removeRange);
|
|
1568
|
+
}
|
|
1569
|
+
const beginFenceInsertOffset = lines.get(loc.start.line).range[0];
|
|
1570
|
+
const endFenceInsertOffset = lines.get(loc.end.line).range[1];
|
|
1571
|
+
return [
|
|
1572
|
+
fixer.insertTextBeforeRange([beginFenceInsertOffset, beginFenceInsertOffset], `${prefixText}\`\`\`\n`),
|
|
1573
|
+
...removeRanges.map((removeRange) => fixer.removeRange(removeRange)),
|
|
1574
|
+
fixer.insertTextAfterRange([endFenceInsertOffset, endFenceInsertOffset], `${prefixText}\`\`\`\n`)
|
|
1575
|
+
];
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
} };
|
|
1579
|
+
/**
|
|
1580
|
+
* Determines whether the given indented code block is fixable or not.
|
|
1581
|
+
*/
|
|
1582
|
+
function isFixableIndentedCodeBlock(node) {
|
|
1583
|
+
if (!node.value.startsWith(" ")) return true;
|
|
1584
|
+
const loc = sourceCode.getLoc(node);
|
|
1585
|
+
const firstLine = lines.get(loc.start.line);
|
|
1586
|
+
const codeBlockFirstLine = normalizePrefix(node.value.split(/\r?\n/u)[0]);
|
|
1587
|
+
const startColumnOffset = loc.start.column - 1;
|
|
1588
|
+
const normalizedFirstLine = normalizePrefix(firstLine.text.slice(startColumnOffset));
|
|
1589
|
+
return normalizedFirstLine.startsWith(codeBlockFirstLine);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
/**
|
|
1594
|
+
* Normalize the prefix by removing tabs and replacing them with spaces.
|
|
1595
|
+
*/
|
|
1596
|
+
function normalizePrefix(prefix) {
|
|
1597
|
+
let result = "";
|
|
1598
|
+
for (const c of prefix) if (c !== " ") result += c;
|
|
1599
|
+
else result += " ".repeat(4 - result.length % 4);
|
|
1600
|
+
return result;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1157
1603
|
//#endregion
|
|
1158
1604
|
//#region src/utils/search-words.ts
|
|
1159
1605
|
const RE_BOUNDARY = /^[\s\p{Letter_Number}\p{Modifier_Letter}\p{Modifier_Symbol}\p{Nonspacing_Mark}\p{Other_Letter}\p{Other_Symbol}\p{Script=Han}!"#$%&'()*+,./:;<=>?\\{|}~\u{2ffc}-\u{303d}\u{30a0}-\u{30fb}\u{3192}-\u{32bf}\u{fe10}-\u{fe1f}\u{fe30}-\u{fe6f}\u{ff00}-\u{ffef}\u{2ebf0}-\u{2ee5d}]*$/u;
|
|
@@ -1488,25 +1934,6 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
|
|
|
1488
1934
|
}
|
|
1489
1935
|
});
|
|
1490
1936
|
|
|
1491
|
-
//#endregion
|
|
1492
|
-
//#region src/utils/url.ts
|
|
1493
|
-
/**
|
|
1494
|
-
* Utility function to check if a string is a valid URL.
|
|
1495
|
-
*/
|
|
1496
|
-
function isValidURL(url) {
|
|
1497
|
-
return Boolean(createURLSafe(url));
|
|
1498
|
-
}
|
|
1499
|
-
/**
|
|
1500
|
-
* Utility function to create a URL object safely.
|
|
1501
|
-
*/
|
|
1502
|
-
function createURLSafe(url) {
|
|
1503
|
-
try {
|
|
1504
|
-
return new URL(url);
|
|
1505
|
-
} catch {
|
|
1506
|
-
return null;
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
1937
|
//#endregion
|
|
1511
1938
|
//#region src/rules/prefer-linked-words.ts
|
|
1512
1939
|
var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
@@ -1608,7 +2035,7 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
1608
2035
|
* Adjust link to be relative to the file.
|
|
1609
2036
|
*/
|
|
1610
2037
|
function adjustLink(link) {
|
|
1611
|
-
if (
|
|
2038
|
+
if (URL.canParse(link)) return link;
|
|
1612
2039
|
if (link.startsWith("#")) return link;
|
|
1613
2040
|
const absoluteLink = path.isAbsolute(link) || path.posix.isAbsolute(link) ? link : path.join(context.cwd, link);
|
|
1614
2041
|
return `./${path.relative(path.dirname(context.filename), absoluteLink)}`;
|
|
@@ -1789,14 +2216,14 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
1789
2216
|
}
|
|
1790
2217
|
/** Compile order option */
|
|
1791
2218
|
function compileOption(orderOption) {
|
|
1792
|
-
const cache = /* @__PURE__ */ new Map();
|
|
2219
|
+
const cache$1 = /* @__PURE__ */ new Map();
|
|
1793
2220
|
const compiled = compileOptionWithoutCache(orderOption);
|
|
1794
2221
|
return {
|
|
1795
2222
|
match: (node) => {
|
|
1796
|
-
const cached = cache.get(node);
|
|
2223
|
+
const cached = cache$1.get(node);
|
|
1797
2224
|
if (cached != null) return cached;
|
|
1798
2225
|
const result = compiled.match(node);
|
|
1799
|
-
cache.set(node, result);
|
|
2226
|
+
cache$1.set(node, result);
|
|
1800
2227
|
return result;
|
|
1801
2228
|
},
|
|
1802
2229
|
sort: compiled.sort
|
|
@@ -1847,7 +2274,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
1847
2274
|
if (node.label === patternStr || node.identifier === patternStr) return true;
|
|
1848
2275
|
if (node.type === "definition") {
|
|
1849
2276
|
if (node.url === patternStr) return true;
|
|
1850
|
-
if (
|
|
2277
|
+
if (URL.canParse(patternStr) && URL.canParse(node.url)) {
|
|
1851
2278
|
const normalizedPattern = normalizedURL(patternStr);
|
|
1852
2279
|
const normalizedUrl = normalizedURL(node.url);
|
|
1853
2280
|
if (normalizedUrl.startsWith(normalizedPattern)) return true;
|
|
@@ -1894,7 +2321,7 @@ function getQuote(text) {
|
|
|
1894
2321
|
* Normalize a URL by ensuring it ends with a slash.
|
|
1895
2322
|
*/
|
|
1896
2323
|
function normalizedURL(url) {
|
|
1897
|
-
const urlObj =
|
|
2324
|
+
const urlObj = new URL(url);
|
|
1898
2325
|
if (!urlObj) return url;
|
|
1899
2326
|
return urlObj.href.endsWith("/") ? urlObj.href : `${urlObj.href}/`;
|
|
1900
2327
|
}
|
|
@@ -1906,8 +2333,12 @@ const rules$1 = [
|
|
|
1906
2333
|
definitions_last_default,
|
|
1907
2334
|
hard_linebreak_style_default,
|
|
1908
2335
|
heading_casing_default,
|
|
2336
|
+
no_laziness_blockquotes_default,
|
|
2337
|
+
no_multiple_empty_lines_default,
|
|
1909
2338
|
no_text_backslash_linebreak_default,
|
|
1910
2339
|
no_trailing_spaces_default,
|
|
2340
|
+
prefer_autolinks_default,
|
|
2341
|
+
prefer_fenced_code_blocks_default,
|
|
1911
2342
|
prefer_inline_code_words_default,
|
|
1912
2343
|
prefer_link_reference_definitions_default,
|
|
1913
2344
|
prefer_linked_words_default,
|
|
@@ -1920,13 +2351,15 @@ var recommended_exports = {};
|
|
|
1920
2351
|
__export(recommended_exports, {
|
|
1921
2352
|
files: () => files,
|
|
1922
2353
|
language: () => language,
|
|
2354
|
+
languageOptions: () => languageOptions,
|
|
1923
2355
|
name: () => name$1,
|
|
1924
2356
|
plugins: () => plugins,
|
|
1925
2357
|
rules: () => rules$2
|
|
1926
2358
|
});
|
|
1927
2359
|
const name$1 = "markdown-preferences/recommended";
|
|
1928
2360
|
const files = ["*.md", "**/*.md"];
|
|
1929
|
-
const language = "markdown/
|
|
2361
|
+
const language = "markdown/gfm";
|
|
2362
|
+
const languageOptions = { frontmatter: "yaml" };
|
|
1930
2363
|
const plugins = {
|
|
1931
2364
|
markdown,
|
|
1932
2365
|
get "markdown-preferences"() {
|
|
@@ -1935,7 +2368,10 @@ const plugins = {
|
|
|
1935
2368
|
};
|
|
1936
2369
|
const rules$2 = {
|
|
1937
2370
|
"markdown-preferences/hard-linebreak-style": "error",
|
|
1938
|
-
"markdown-preferences/no-
|
|
2371
|
+
"markdown-preferences/no-laziness-blockquotes": "error",
|
|
2372
|
+
"markdown-preferences/no-text-backslash-linebreak": "error",
|
|
2373
|
+
"markdown-preferences/prefer-autolinks": "error",
|
|
2374
|
+
"markdown-preferences/prefer-fenced-code-blocks": "error"
|
|
1939
2375
|
};
|
|
1940
2376
|
|
|
1941
2377
|
//#endregion
|
|
@@ -1946,7 +2382,7 @@ __export(meta_exports, {
|
|
|
1946
2382
|
version: () => version
|
|
1947
2383
|
});
|
|
1948
2384
|
const name = "eslint-plugin-markdown-preferences";
|
|
1949
|
-
const version = "0.
|
|
2385
|
+
const version = "0.11.0";
|
|
1950
2386
|
|
|
1951
2387
|
//#endregion
|
|
1952
2388
|
//#region src/index.ts
|