eslint-plugin-markdown-preferences 0.28.0 β 0.29.1
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 +29 -30
- package/lib/index.d.ts +10 -2
- package/lib/index.js +508 -380
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,17 +13,15 @@ A specialized ESLint plugin that helps enforce consistent writing style and form
|
|
|
13
13
|
|
|
14
14
|
## π Features
|
|
15
15
|
|
|
16
|
-
- π **Comprehensive style enforcement
|
|
17
|
-
|
|
18
|
-
- π§© **
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
- π§ **Auto-fix support
|
|
23
|
-
Most rules support ESLint's `--fix` option for
|
|
24
|
-
-
|
|
25
|
-
Provides both "recommended" and "standard" configs, and allows you to finely customize formatting and rules to suit your preferences and Markdown style.
|
|
26
|
-
- π **Live demo & documentation**\
|
|
16
|
+
- π **Comprehensive style enforcement**
|
|
17
|
+
Enforces consistent heading casing, table header casing, inline code/link usage, emoji notation, and more for unified document style.
|
|
18
|
+
- π§© **Powerful formatting consistency**
|
|
19
|
+
Strongly standardizes Markdown formatting: whitespace, indentation, spacing, line breaks, list markers, code fences, links, references, thematic breaks, tables, and decorative elementsβensuring documents are clean and uniform.
|
|
20
|
+
- π **Extended Markdown syntax support**
|
|
21
|
+
Supports custom containers, mathematical expressions, and other extended syntax for high compatibility with VitePress.
|
|
22
|
+
- π§ **Auto-fix support**
|
|
23
|
+
Most rules support ESLint's `--fix` option for automatic correction.
|
|
24
|
+
- π **Online Demo & Documentation**
|
|
27
25
|
Try it instantly in the [Online Demo](https://eslint-online-playground.netlify.app/#eslint-plugin-markdown-preferences) and see [full documentation][documentation site].
|
|
28
26
|
|
|
29
27
|
<!--DOCS_IGNORE_START-->
|
|
@@ -164,25 +162,25 @@ The rules with the following π are included in the `standard` config.
|
|
|
164
162
|
|
|
165
163
|
<!-- prettier-ignore-start -->
|
|
166
164
|
|
|
167
|
-
| Rule ID | Description
|
|
168
|
-
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
169
|
-
| [markdown-preferences/bullet-list-marker-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/bullet-list-marker-style.html) | enforce consistent bullet list (unordered list) marker style
|
|
170
|
-
| [markdown-preferences/code-fence-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/code-fence-style.html) | enforce a consistent code fence style (backtick or tilde) in Markdown fenced code blocks.
|
|
171
|
-
| [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
|
|
172
|
-
| [markdown-preferences/emphasis-delimiters-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/emphasis-delimiters-style.html) | enforce a consistent delimiter style for emphasis and strong emphasis
|
|
173
|
-
| [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style.
|
|
174
|
-
| [markdown-preferences/level1-heading-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/level1-heading-style.html) | enforce consistent style for level 1 headings
|
|
175
|
-
| [markdown-preferences/level2-heading-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/level2-heading-style.html) | enforce consistent style for level 2 headings
|
|
176
|
-
| [markdown-preferences/link-destination-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/link-destination-style.html) | enforce a consistent style for link destinations
|
|
177
|
-
| [markdown-preferences/link-title-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/link-title-style.html) | enforce a consistent style for link titles
|
|
178
|
-
| [markdown-preferences/no-implicit-block-closing](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-implicit-block-closing.html) | disallow implicit block closing for fenced code blocks, math blocks, and custom
|
|
179
|
-
| [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.
|
|
180
|
-
| [markdown-preferences/ordered-list-marker-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/ordered-list-marker-style.html) | enforce consistent ordered list marker style
|
|
181
|
-
| [markdown-preferences/prefer-autolinks](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-autolinks.html) | enforce the use of autolinks for URLs
|
|
182
|
-
| [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
|
|
183
|
-
| [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
|
|
184
|
-
| [markdown-preferences/strikethrough-delimiters-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/strikethrough-delimiters-style.html) | enforce a consistent delimiter style for strikethrough
|
|
185
|
-
| [markdown-preferences/thematic-break-character-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/thematic-break-character-style.html) | enforce consistent character style for thematic breaks (horizontal rules) in Markdown.
|
|
165
|
+
| Rule ID | Description | Fixable | Config |
|
|
166
|
+
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :-----: | :----: |
|
|
167
|
+
| [markdown-preferences/bullet-list-marker-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/bullet-list-marker-style.html) | enforce consistent bullet list (unordered list) marker style | π§ | π |
|
|
168
|
+
| [markdown-preferences/code-fence-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/code-fence-style.html) | enforce a consistent code fence style (backtick or tilde) in Markdown fenced code blocks. | π§ | π |
|
|
169
|
+
| [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 | π§ | |
|
|
170
|
+
| [markdown-preferences/emphasis-delimiters-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/emphasis-delimiters-style.html) | enforce a consistent delimiter style for emphasis and strong emphasis | π§ | π |
|
|
171
|
+
| [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style. | π§ | βπ |
|
|
172
|
+
| [markdown-preferences/level1-heading-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/level1-heading-style.html) | enforce consistent style for level 1 headings | π§ | π |
|
|
173
|
+
| [markdown-preferences/level2-heading-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/level2-heading-style.html) | enforce consistent style for level 2 headings | π§ | π |
|
|
174
|
+
| [markdown-preferences/link-destination-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/link-destination-style.html) | enforce a consistent style for link destinations | π§ | π |
|
|
175
|
+
| [markdown-preferences/link-title-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/link-title-style.html) | enforce a consistent style for link titles | π§ | π |
|
|
176
|
+
| [markdown-preferences/no-implicit-block-closing](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-implicit-block-closing.html) | disallow implicit block closing for fenced code blocks, math blocks, and custom containers | π§ | βπ |
|
|
177
|
+
| [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. | | βπ |
|
|
178
|
+
| [markdown-preferences/ordered-list-marker-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/ordered-list-marker-style.html) | enforce consistent ordered list marker style | π§ | π |
|
|
179
|
+
| [markdown-preferences/prefer-autolinks](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-autolinks.html) | enforce the use of autolinks for URLs | π§ | βπ |
|
|
180
|
+
| [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 | π§ | βπ |
|
|
181
|
+
| [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 | π§ | |
|
|
182
|
+
| [markdown-preferences/strikethrough-delimiters-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/strikethrough-delimiters-style.html) | enforce a consistent delimiter style for strikethrough | π§ | π |
|
|
183
|
+
| [markdown-preferences/thematic-break-character-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/thematic-break-character-style.html) | enforce consistent character style for thematic breaks (horizontal rules) in Markdown. | π§ | π |
|
|
186
184
|
|
|
187
185
|
<!-- prettier-ignore-end -->
|
|
188
186
|
|
|
@@ -204,6 +202,7 @@ The rules with the following π are included in the `standard` config.
|
|
|
204
202
|
| [markdown-preferences/no-multi-spaces](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-multi-spaces.html) | disallow multiple spaces | π§ | π |
|
|
205
203
|
| [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. | π§ | π |
|
|
206
204
|
| [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. | π§ | π |
|
|
205
|
+
| [markdown-preferences/padded-custom-containers](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/padded-custom-containers.html) | disallow or require padding inside custom containers | π§ | π |
|
|
207
206
|
| [markdown-preferences/padding-line-between-blocks](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/padding-line-between-blocks.html) | require or disallow padding lines between blocks | π§ | π |
|
|
208
207
|
| [markdown-preferences/table-pipe-spacing](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/table-pipe-spacing.html) | enforce consistent spacing around table pipes | π§ | π |
|
|
209
208
|
|
package/lib/index.d.ts
CHANGED
|
@@ -126,7 +126,7 @@ interface RuleOptions {
|
|
|
126
126
|
*/
|
|
127
127
|
'markdown-preferences/list-marker-alignment'?: Linter.RuleEntry<MarkdownPreferencesListMarkerAlignment>;
|
|
128
128
|
/**
|
|
129
|
-
* disallow implicit block closing for fenced code blocks, math blocks, and custom
|
|
129
|
+
* disallow implicit block closing for fenced code blocks, math blocks, and custom containers
|
|
130
130
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-implicit-block-closing.html
|
|
131
131
|
*/
|
|
132
132
|
'markdown-preferences/no-implicit-block-closing'?: Linter.RuleEntry<[]>;
|
|
@@ -170,6 +170,11 @@ interface RuleOptions {
|
|
|
170
170
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/ordered-list-marker-style.html
|
|
171
171
|
*/
|
|
172
172
|
'markdown-preferences/ordered-list-marker-style'?: Linter.RuleEntry<MarkdownPreferencesOrderedListMarkerStyle>;
|
|
173
|
+
/**
|
|
174
|
+
* disallow or require padding inside custom containers
|
|
175
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/padded-custom-containers.html
|
|
176
|
+
*/
|
|
177
|
+
'markdown-preferences/padded-custom-containers'?: Linter.RuleEntry<MarkdownPreferencesPaddedCustomContainers>;
|
|
173
178
|
/**
|
|
174
179
|
* require or disallow padding lines between blocks
|
|
175
180
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/padding-line-between-blocks.html
|
|
@@ -389,6 +394,9 @@ type MarkdownPreferencesOrderedListMarkerStyle = [] | [{
|
|
|
389
394
|
prefer?: ("n." | "n)");
|
|
390
395
|
}[];
|
|
391
396
|
}];
|
|
397
|
+
type MarkdownPreferencesPaddedCustomContainers = [] | [{
|
|
398
|
+
padding?: ("always" | "never");
|
|
399
|
+
}];
|
|
392
400
|
type MarkdownPreferencesPaddingLineBetweenBlocks = {
|
|
393
401
|
prev: (("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*") | [("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*"), ...(("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*"))[]] | {
|
|
394
402
|
type: (("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*") | [("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*"), ...(("blockquote" | "code" | "heading" | "html" | "list" | "paragraph" | "thematic-break" | "table" | "link-definition" | "footnote-definition" | "frontmatter" | "custom-container" | "math" | "import-code-snippet" | "*"))[]]);
|
|
@@ -508,7 +516,7 @@ declare namespace meta_d_exports {
|
|
|
508
516
|
export { name, version };
|
|
509
517
|
}
|
|
510
518
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
511
|
-
declare const version: "0.
|
|
519
|
+
declare const version: "0.29.1";
|
|
512
520
|
//#endregion
|
|
513
521
|
//#region src/language/ast-types.d.ts
|
|
514
522
|
type Node = mdast.Node;
|
package/lib/index.js
CHANGED
|
@@ -7617,7 +7617,7 @@ var no_implicit_block_closing_default = createRule("no-implicit-block-closing",
|
|
|
7617
7617
|
meta: {
|
|
7618
7618
|
type: "suggestion",
|
|
7619
7619
|
docs: {
|
|
7620
|
-
description: "disallow implicit block closing for fenced code blocks, math blocks, and custom
|
|
7620
|
+
description: "disallow implicit block closing for fenced code blocks, math blocks, and custom containers",
|
|
7621
7621
|
categories: ["recommended", "standard"],
|
|
7622
7622
|
listCategory: "Notation"
|
|
7623
7623
|
},
|
|
@@ -7636,7 +7636,8 @@ var no_implicit_block_closing_default = createRule("no-implicit-block-closing",
|
|
|
7636
7636
|
code(node) {
|
|
7637
7637
|
const parsed = parseFencedCodeBlock(sourceCode, node);
|
|
7638
7638
|
if (!parsed) return;
|
|
7639
|
-
if (
|
|
7639
|
+
if (parsed.closingFence) return;
|
|
7640
|
+
context.report({
|
|
7640
7641
|
node,
|
|
7641
7642
|
loc: parsed.openingFence.loc,
|
|
7642
7643
|
messageId: "missingClosingFence",
|
|
@@ -7651,7 +7652,8 @@ var no_implicit_block_closing_default = createRule("no-implicit-block-closing",
|
|
|
7651
7652
|
math(node) {
|
|
7652
7653
|
const parsed = parseMathBlock(sourceCode, node);
|
|
7653
7654
|
if (!parsed) return;
|
|
7654
|
-
if (
|
|
7655
|
+
if (parsed.closingSequence) return;
|
|
7656
|
+
context.report({
|
|
7655
7657
|
node,
|
|
7656
7658
|
loc: parsed.openingSequence.loc,
|
|
7657
7659
|
messageId: "missingClosingMath",
|
|
@@ -7666,11 +7668,13 @@ var no_implicit_block_closing_default = createRule("no-implicit-block-closing",
|
|
|
7666
7668
|
customContainer(node) {
|
|
7667
7669
|
const parsed = parseCustomContainer(sourceCode, node);
|
|
7668
7670
|
if (!parsed) return;
|
|
7669
|
-
if (
|
|
7671
|
+
if (parsed.closingSequence) return;
|
|
7672
|
+
context.report({
|
|
7670
7673
|
node,
|
|
7671
7674
|
loc: parsed.openingSequence.loc,
|
|
7672
7675
|
messageId: "missingClosingContainer",
|
|
7673
7676
|
fix(fixer) {
|
|
7677
|
+
if (withinSameLengthOpeningCustomContainer(sourceCode, node, parsed.openingSequence.text.length)) return null;
|
|
7674
7678
|
const openingLoc = parsed.openingSequence.loc;
|
|
7675
7679
|
const prefix = sourceCode.lines[openingLoc.start.line - 1].slice(0, openingLoc.start.column - 1).replace(/[^\s>]/gu, " ");
|
|
7676
7680
|
const closingSequence = parsed.openingSequence.text;
|
|
@@ -7681,6 +7685,23 @@ var no_implicit_block_closing_default = createRule("no-implicit-block-closing",
|
|
|
7681
7685
|
};
|
|
7682
7686
|
}
|
|
7683
7687
|
});
|
|
7688
|
+
/**
|
|
7689
|
+
* Check if the given custom container node is within another custom container
|
|
7690
|
+
* that has the same length of opening sequence.
|
|
7691
|
+
*
|
|
7692
|
+
*/
|
|
7693
|
+
function withinSameLengthOpeningCustomContainer(sourceCode, node, openingLength) {
|
|
7694
|
+
let current = getParent(sourceCode, node);
|
|
7695
|
+
while (current) {
|
|
7696
|
+
if (current.type === "customContainer") {
|
|
7697
|
+
const parsed = parseCustomContainer(sourceCode, current);
|
|
7698
|
+
if (!parsed) return true;
|
|
7699
|
+
if (parsed.openingSequence.text.length === openingLength) return true;
|
|
7700
|
+
}
|
|
7701
|
+
current = getParent(sourceCode, current);
|
|
7702
|
+
}
|
|
7703
|
+
return false;
|
|
7704
|
+
}
|
|
7684
7705
|
|
|
7685
7706
|
//#endregion
|
|
7686
7707
|
//#region src/rules/no-laziness-blockquotes.ts
|
|
@@ -8922,6 +8943,101 @@ var ordered_list_marker_style_default = createRule("ordered-list-marker-style",
|
|
|
8922
8943
|
}
|
|
8923
8944
|
});
|
|
8924
8945
|
|
|
8946
|
+
//#endregion
|
|
8947
|
+
//#region src/rules/padded-custom-containers.ts
|
|
8948
|
+
var padded_custom_containers_default = createRule("padded-custom-containers", {
|
|
8949
|
+
meta: {
|
|
8950
|
+
type: "layout",
|
|
8951
|
+
docs: {
|
|
8952
|
+
description: "disallow or require padding inside custom containers",
|
|
8953
|
+
categories: ["standard"],
|
|
8954
|
+
listCategory: "Whitespace"
|
|
8955
|
+
},
|
|
8956
|
+
fixable: "whitespace",
|
|
8957
|
+
hasSuggestions: false,
|
|
8958
|
+
schema: [{
|
|
8959
|
+
type: "object",
|
|
8960
|
+
properties: { padding: {
|
|
8961
|
+
type: "string",
|
|
8962
|
+
enum: ["always", "never"],
|
|
8963
|
+
default: "never"
|
|
8964
|
+
} },
|
|
8965
|
+
additionalProperties: false
|
|
8966
|
+
}],
|
|
8967
|
+
messages: {
|
|
8968
|
+
expectedPaddingAfterOpeningMarker: "Expected padding after opening marker.",
|
|
8969
|
+
expectedPaddingBeforeClosingMarker: "Expected padding before closing marker.",
|
|
8970
|
+
unexpectedPaddingAfterOpeningMarker: "Unexpected padding after opening marker.",
|
|
8971
|
+
unexpectedPaddingBeforeClosingMarker: "Unexpected padding before closing marker."
|
|
8972
|
+
}
|
|
8973
|
+
},
|
|
8974
|
+
create(context) {
|
|
8975
|
+
const sourceCode = context.sourceCode;
|
|
8976
|
+
const padding = (context.options[0] || {}).padding || "never";
|
|
8977
|
+
return { customContainer(node) {
|
|
8978
|
+
if (node.children.length === 0) return;
|
|
8979
|
+
const parsed = parseCustomContainer(sourceCode, node);
|
|
8980
|
+
if (!parsed) return;
|
|
8981
|
+
const { openingSequence, closingSequence } = parsed;
|
|
8982
|
+
const firstChild = node.children[0];
|
|
8983
|
+
const lastChild = node.children[node.children.length - 1];
|
|
8984
|
+
const firstChildLoc = sourceCode.getLoc(firstChild);
|
|
8985
|
+
const lastChildLoc = sourceCode.getLoc(lastChild);
|
|
8986
|
+
const paddingAfterOpeningLines = firstChildLoc.start.line - openingSequence.loc.end.line - 1;
|
|
8987
|
+
const paddingBeforeClosingLines = closingSequence ? closingSequence.loc.start.line - lastChildLoc.end.line - 1 : null;
|
|
8988
|
+
if (padding === "always") {
|
|
8989
|
+
if (paddingAfterOpeningLines <= 0) {
|
|
8990
|
+
const reportEndToken = parsed.info ?? openingSequence;
|
|
8991
|
+
const reportRange = [openingSequence.range[0], reportEndToken.range[1]];
|
|
8992
|
+
context.report({
|
|
8993
|
+
messageId: "expectedPaddingAfterOpeningMarker",
|
|
8994
|
+
loc: getSourceLocationFromRange(sourceCode, node, reportRange),
|
|
8995
|
+
fix(fixer) {
|
|
8996
|
+
return fixer.insertTextAfterRange(reportRange, "\n");
|
|
8997
|
+
}
|
|
8998
|
+
});
|
|
8999
|
+
}
|
|
9000
|
+
if (closingSequence && paddingBeforeClosingLines !== null && paddingBeforeClosingLines <= 0) context.report({
|
|
9001
|
+
messageId: "expectedPaddingBeforeClosingMarker",
|
|
9002
|
+
loc: getSourceLocationFromRange(sourceCode, node, closingSequence.range),
|
|
9003
|
+
fix(fixer) {
|
|
9004
|
+
return fixer.insertTextBeforeRange([closingSequence.range[0] - closingSequence.loc.start.column + 1, closingSequence.range[1]], "\n");
|
|
9005
|
+
}
|
|
9006
|
+
});
|
|
9007
|
+
} else if (padding === "never") {
|
|
9008
|
+
if (paddingAfterOpeningLines > 0) {
|
|
9009
|
+
const firstChildRange = sourceCode.getRange(firstChild);
|
|
9010
|
+
context.report({
|
|
9011
|
+
messageId: "unexpectedPaddingAfterOpeningMarker",
|
|
9012
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingSequence.range[1], firstChildRange[0]]),
|
|
9013
|
+
*fix(fixer) {
|
|
9014
|
+
const lines = getParsedLines(sourceCode);
|
|
9015
|
+
for (let lineNumber = openingSequence.loc.end.line + 1; lineNumber < firstChildLoc.start.line; lineNumber++) {
|
|
9016
|
+
const line = lines.get(lineNumber);
|
|
9017
|
+
yield fixer.removeRange(line.range);
|
|
9018
|
+
}
|
|
9019
|
+
}
|
|
9020
|
+
});
|
|
9021
|
+
}
|
|
9022
|
+
if (closingSequence && paddingBeforeClosingLines !== null && paddingBeforeClosingLines > 0) {
|
|
9023
|
+
const lastChildRange = sourceCode.getRange(lastChild);
|
|
9024
|
+
context.report({
|
|
9025
|
+
messageId: "unexpectedPaddingBeforeClosingMarker",
|
|
9026
|
+
loc: getSourceLocationFromRange(sourceCode, node, [lastChildRange[1], closingSequence.range[0]]),
|
|
9027
|
+
*fix(fixer) {
|
|
9028
|
+
const lines = getParsedLines(sourceCode);
|
|
9029
|
+
for (let lineNumber = lastChildLoc.end.line + 1; lineNumber < closingSequence.loc.start.line; lineNumber++) {
|
|
9030
|
+
const line = lines.get(lineNumber);
|
|
9031
|
+
yield fixer.removeRange(line.range);
|
|
9032
|
+
}
|
|
9033
|
+
}
|
|
9034
|
+
});
|
|
9035
|
+
}
|
|
9036
|
+
}
|
|
9037
|
+
} };
|
|
9038
|
+
}
|
|
9039
|
+
});
|
|
9040
|
+
|
|
8925
9041
|
//#endregion
|
|
8926
9042
|
//#region src/rules/padding-line-between-blocks.ts
|
|
8927
9043
|
/**
|
|
@@ -10580,397 +10696,157 @@ var table_leading_trailing_pipes_default = createRule("table-leading-trailing-pi
|
|
|
10580
10696
|
});
|
|
10581
10697
|
|
|
10582
10698
|
//#endregion
|
|
10583
|
-
//#region src/rules/table-pipe-
|
|
10584
|
-
|
|
10699
|
+
//#region src/rules/table-pipe-spacing.ts
|
|
10700
|
+
const currentOption = /* @__PURE__ */ new WeakMap();
|
|
10701
|
+
/**
|
|
10702
|
+
* Get the current options for the given source code.
|
|
10703
|
+
* This is a method that allows you to access the configuration of this rule from another rule.
|
|
10704
|
+
*/
|
|
10705
|
+
function getCurrentTablePipeSpacingOption(sourceCode) {
|
|
10706
|
+
return currentOption.get(sourceCode) ?? null;
|
|
10707
|
+
}
|
|
10708
|
+
/**
|
|
10709
|
+
* Parsed options
|
|
10710
|
+
*/
|
|
10711
|
+
function parseOptions(options) {
|
|
10712
|
+
const spaceOption = options?.space;
|
|
10713
|
+
const leadingSpace = (typeof spaceOption === "object" ? spaceOption.leading : spaceOption) || "always";
|
|
10714
|
+
const trailingSpace = (typeof spaceOption === "object" ? spaceOption.trailing : spaceOption) || "always";
|
|
10715
|
+
const cellAlignOption = options?.cellAlign;
|
|
10716
|
+
const defaultDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.defaultDelimiter : cellAlignOption) || "left";
|
|
10717
|
+
const leftAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.leftAlignmentDelimiter : cellAlignOption) || "left";
|
|
10718
|
+
const centerAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.centerAlignmentDelimiter : cellAlignOption) || "center";
|
|
10719
|
+
const rightAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.rightAlignmentDelimiter : cellAlignOption) || "right";
|
|
10720
|
+
return {
|
|
10721
|
+
leadingSpace,
|
|
10722
|
+
trailingSpace,
|
|
10723
|
+
cellAlignByDelimiter: {
|
|
10724
|
+
none: adjustAlign(defaultDelimiterCellAlign),
|
|
10725
|
+
left: adjustAlign(leftAlignmentDelimiterCellAlign),
|
|
10726
|
+
center: adjustAlign(centerAlignmentDelimiterCellAlign),
|
|
10727
|
+
right: adjustAlign(rightAlignmentDelimiterCellAlign)
|
|
10728
|
+
}
|
|
10729
|
+
};
|
|
10730
|
+
/**
|
|
10731
|
+
* Adjust the alignment option based on the spacing options.
|
|
10732
|
+
*/
|
|
10733
|
+
function adjustAlign(align) {
|
|
10734
|
+
if (align === "left") {
|
|
10735
|
+
if (trailingSpace === "always") return "left";
|
|
10736
|
+
return "ignore";
|
|
10737
|
+
}
|
|
10738
|
+
if (align === "center") {
|
|
10739
|
+
if (leadingSpace === "always" && trailingSpace === "always") return "center";
|
|
10740
|
+
return "ignore";
|
|
10741
|
+
}
|
|
10742
|
+
if (align === "right") {
|
|
10743
|
+
if (leadingSpace === "always") return "right";
|
|
10744
|
+
return "ignore";
|
|
10745
|
+
}
|
|
10746
|
+
return align;
|
|
10747
|
+
}
|
|
10748
|
+
}
|
|
10749
|
+
var table_pipe_spacing_default = createRule("table-pipe-spacing", {
|
|
10585
10750
|
meta: {
|
|
10586
10751
|
type: "layout",
|
|
10587
10752
|
docs: {
|
|
10588
|
-
description: "enforce consistent
|
|
10753
|
+
description: "enforce consistent spacing around table pipes",
|
|
10589
10754
|
categories: ["standard"],
|
|
10590
|
-
listCategory: "
|
|
10755
|
+
listCategory: "Whitespace"
|
|
10591
10756
|
},
|
|
10592
|
-
fixable: "
|
|
10757
|
+
fixable: "whitespace",
|
|
10593
10758
|
hasSuggestions: false,
|
|
10594
10759
|
schema: [{
|
|
10595
10760
|
type: "object",
|
|
10596
|
-
properties: {
|
|
10761
|
+
properties: {
|
|
10762
|
+
space: { anyOf: [{ enum: ["always", "never"] }, {
|
|
10763
|
+
type: "object",
|
|
10764
|
+
properties: {
|
|
10765
|
+
leading: { enum: ["always", "never"] },
|
|
10766
|
+
trailing: { enum: ["always", "never"] }
|
|
10767
|
+
},
|
|
10768
|
+
additionalProperties: false
|
|
10769
|
+
}] },
|
|
10770
|
+
cellAlign: { anyOf: [{ enum: [
|
|
10771
|
+
"left",
|
|
10772
|
+
"center",
|
|
10773
|
+
"right"
|
|
10774
|
+
] }, {
|
|
10775
|
+
type: "object",
|
|
10776
|
+
properties: {
|
|
10777
|
+
defaultDelimiter: { enum: [
|
|
10778
|
+
"left",
|
|
10779
|
+
"center",
|
|
10780
|
+
"right",
|
|
10781
|
+
"ignore"
|
|
10782
|
+
] },
|
|
10783
|
+
leftAlignmentDelimiter: { enum: [
|
|
10784
|
+
"left",
|
|
10785
|
+
"center",
|
|
10786
|
+
"right",
|
|
10787
|
+
"ignore"
|
|
10788
|
+
] },
|
|
10789
|
+
centerAlignmentDelimiter: { enum: [
|
|
10790
|
+
"left",
|
|
10791
|
+
"center",
|
|
10792
|
+
"right",
|
|
10793
|
+
"ignore"
|
|
10794
|
+
] },
|
|
10795
|
+
rightAlignmentDelimiter: { enum: [
|
|
10796
|
+
"left",
|
|
10797
|
+
"center",
|
|
10798
|
+
"right",
|
|
10799
|
+
"ignore"
|
|
10800
|
+
] }
|
|
10801
|
+
},
|
|
10802
|
+
additionalProperties: false
|
|
10803
|
+
}] }
|
|
10804
|
+
},
|
|
10597
10805
|
additionalProperties: false
|
|
10598
10806
|
}],
|
|
10599
10807
|
messages: {
|
|
10600
|
-
|
|
10601
|
-
|
|
10808
|
+
expectedSpaceBefore: "Expected 1 space before \"|\".",
|
|
10809
|
+
expectedNoSpaceBefore: "Expected no space before \"|\".",
|
|
10810
|
+
expectedSpaceAfter: "Expected 1 space after \"|\".",
|
|
10811
|
+
expectedNoSpaceAfter: "Expected no space after \"|\".",
|
|
10812
|
+
expectedAlignLeft: "Expected 1 space after \"|\" for left-aligned column.",
|
|
10813
|
+
expectedNoSpaceAlignLeft: "Expected no space after \"|\" for left-aligned column.",
|
|
10814
|
+
expectedAlignRight: "Expected 1 space before \"|\" for right-aligned column.",
|
|
10815
|
+
expectedNoSpaceAlignRight: "Expected no space before \"|\" for right-aligned column.",
|
|
10816
|
+
expectedAlignCenter: "Expected the number of spaces before and after the content to be the same or differ by 1 at most for center-aligned column."
|
|
10602
10817
|
}
|
|
10603
10818
|
},
|
|
10604
10819
|
create(context) {
|
|
10605
10820
|
const sourceCode = context.sourceCode;
|
|
10606
|
-
const
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10612
|
-
|
|
10613
|
-
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
}
|
|
10620
|
-
/**
|
|
10621
|
-
* Get the expected pipe position for the index
|
|
10622
|
-
*/
|
|
10623
|
-
getExpectedPipePosition(pipeIndex) {
|
|
10624
|
-
let v = this._cacheExpectedPipePosition.get(pipeIndex);
|
|
10625
|
-
if (v !== void 0) return v;
|
|
10626
|
-
v = this._computeExpectedPipePositionWithoutCache(pipeIndex);
|
|
10627
|
-
this._cacheExpectedPipePosition.set(pipeIndex, v);
|
|
10628
|
-
return v;
|
|
10629
|
-
}
|
|
10630
|
-
/**
|
|
10631
|
-
* Check if there is at least one space between content and trailing pipe
|
|
10632
|
-
* for the index
|
|
10633
|
-
*
|
|
10634
|
-
* This is used to determine if the pipe should be aligned with a space before it.
|
|
10635
|
-
*/
|
|
10636
|
-
hasSpaceBetweenContentAndTrailingPipe(pipeIndex) {
|
|
10637
|
-
if (pipeIndex === 0) return false;
|
|
10638
|
-
let v = this._cacheHasSpaceBetweenContentAndTrailingPipe.get(pipeIndex);
|
|
10639
|
-
if (v != null) return v;
|
|
10640
|
-
v = this._hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex);
|
|
10641
|
-
this._cacheHasSpaceBetweenContentAndTrailingPipe.set(pipeIndex, v);
|
|
10642
|
-
return v;
|
|
10643
|
-
}
|
|
10644
|
-
/**
|
|
10645
|
-
* Get the expected pipe position for the index
|
|
10646
|
-
*/
|
|
10647
|
-
_computeExpectedPipePositionWithoutCache(pipeIndex) {
|
|
10648
|
-
if (pipeIndex === 0) {
|
|
10649
|
-
const firstCell = this.rows[0].cells[0];
|
|
10650
|
-
const firstToken = firstCell.leadingPipe ?? firstCell.content;
|
|
10651
|
-
if (!firstToken) return null;
|
|
10652
|
-
return getTextWidth(sourceCode.lines[firstToken.loc.start.line - 1].slice(0, firstToken.loc.start.column - 1));
|
|
10653
|
-
}
|
|
10654
|
-
if (columnOption === "minimum") return this.getMinimumPipePosition(pipeIndex);
|
|
10655
|
-
else if (columnOption === "consistent") {
|
|
10656
|
-
const columnIndex = pipeIndex - 1;
|
|
10657
|
-
for (const row of this.rows) {
|
|
10658
|
-
if (row.cells.length <= columnIndex) continue;
|
|
10659
|
-
const cell = row.cells[columnIndex];
|
|
10660
|
-
if (cell.type === "delimiter" || !cell.trailingPipe) continue;
|
|
10661
|
-
const width = getTextWidth(sourceCode.lines[cell.trailingPipe.loc.start.line - 1].slice(0, cell.trailingPipe.loc.start.column - 1));
|
|
10662
|
-
return Math.max(width, this.getMinimumPipePosition(pipeIndex) || 0);
|
|
10821
|
+
const options = parseOptions(context.options[0]);
|
|
10822
|
+
currentOption.set(sourceCode, options);
|
|
10823
|
+
/**
|
|
10824
|
+
* Verify for the leading pipe.
|
|
10825
|
+
*/
|
|
10826
|
+
function verifyLeadingPipe(pipe, nextToken) {
|
|
10827
|
+
if (options.leadingSpace === "always") {
|
|
10828
|
+
if (pipe.range[1] < nextToken.range[0]) return true;
|
|
10829
|
+
context.report({
|
|
10830
|
+
loc: pipe.loc,
|
|
10831
|
+
messageId: "expectedSpaceAfter",
|
|
10832
|
+
fix(fixer) {
|
|
10833
|
+
return fixer.insertTextAfterRange(pipe.range, " ");
|
|
10663
10834
|
}
|
|
10664
|
-
}
|
|
10665
|
-
return
|
|
10666
|
-
}
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
|
|
10680
|
-
width = getTextWidth(sourceCode.lines[cell.delimiter.loc.start.line - 1].slice(0, cell.delimiter.loc.start.column - 1)) + minimumDelimiterLength;
|
|
10681
|
-
} else {
|
|
10682
|
-
if (!cell.content) continue;
|
|
10683
|
-
width = getTextWidth(sourceCode.lines[cell.content.loc.end.line - 1].slice(0, cell.content.loc.end.column - 1));
|
|
10684
|
-
}
|
|
10685
|
-
if (needSpaceBeforePipe) width += 1;
|
|
10686
|
-
maxWidth = Math.max(maxWidth, width);
|
|
10687
|
-
}
|
|
10688
|
-
return maxWidth;
|
|
10689
|
-
}
|
|
10690
|
-
/**
|
|
10691
|
-
* Check if there is at least one space between content and trailing pipe
|
|
10692
|
-
*/
|
|
10693
|
-
_hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex) {
|
|
10694
|
-
const columnIndex = pipeIndex - 1;
|
|
10695
|
-
for (const row of this.rows) {
|
|
10696
|
-
if (row.cells.length <= columnIndex) continue;
|
|
10697
|
-
const cell = row.cells[columnIndex];
|
|
10698
|
-
if (!cell.trailingPipe) continue;
|
|
10699
|
-
let content;
|
|
10700
|
-
if (cell.type === "delimiter") content = cell.delimiter;
|
|
10701
|
-
else {
|
|
10702
|
-
if (!cell.content) continue;
|
|
10703
|
-
content = cell.content;
|
|
10704
|
-
}
|
|
10705
|
-
if (content.range[1] < cell.trailingPipe.range[0]) continue;
|
|
10706
|
-
return false;
|
|
10707
|
-
}
|
|
10708
|
-
return true;
|
|
10709
|
-
}
|
|
10710
|
-
}
|
|
10711
|
-
/**
|
|
10712
|
-
* Verify the table pipes
|
|
10713
|
-
*/
|
|
10714
|
-
function verifyTablePipes(table) {
|
|
10715
|
-
const targetRows = [...table.rows];
|
|
10716
|
-
for (const row of targetRows) for (let pipeIndex = 0; pipeIndex <= table.columnCount; pipeIndex++) if (!verifyRowPipe(row, pipeIndex, table)) break;
|
|
10717
|
-
}
|
|
10718
|
-
/**
|
|
10719
|
-
* Verify the pipe in the row
|
|
10720
|
-
*/
|
|
10721
|
-
function verifyRowPipe(row, pipeIndex, table) {
|
|
10722
|
-
let cellIndex;
|
|
10723
|
-
let pipe;
|
|
10724
|
-
if (pipeIndex === 0) {
|
|
10725
|
-
cellIndex = 0;
|
|
10726
|
-
pipe = "leadingPipe";
|
|
10727
|
-
} else {
|
|
10728
|
-
cellIndex = pipeIndex - 1;
|
|
10729
|
-
pipe = "trailingPipe";
|
|
10730
|
-
}
|
|
10731
|
-
if (row.cells.length <= cellIndex) return true;
|
|
10732
|
-
const cell = row.cells[cellIndex];
|
|
10733
|
-
const pipeToken = cell[pipe];
|
|
10734
|
-
if (!pipeToken) return true;
|
|
10735
|
-
return verifyPipe(pipeToken, pipeIndex, table, cell);
|
|
10736
|
-
}
|
|
10737
|
-
/**
|
|
10738
|
-
* Verify the pipe position
|
|
10739
|
-
*/
|
|
10740
|
-
function verifyPipe(pipe, pipeIndex, table, cell) {
|
|
10741
|
-
const expected = table.getExpectedPipePosition(pipeIndex);
|
|
10742
|
-
if (expected == null) return true;
|
|
10743
|
-
const actual = getTextWidth(sourceCode.lines[pipe.loc.start.line - 1].slice(0, pipe.loc.start.column - 1));
|
|
10744
|
-
const diff = expected - actual;
|
|
10745
|
-
if (diff === 0) return true;
|
|
10746
|
-
context.report({
|
|
10747
|
-
loc: pipe.loc,
|
|
10748
|
-
messageId: diff > 0 ? "addSpaces" : "removeSpaces",
|
|
10749
|
-
data: {
|
|
10750
|
-
expected: String(expected),
|
|
10751
|
-
count: String(Math.abs(diff)),
|
|
10752
|
-
plural: Math.abs(diff) === 1 ? "" : "s"
|
|
10753
|
-
},
|
|
10754
|
-
fix(fixer) {
|
|
10755
|
-
if (diff > 0) {
|
|
10756
|
-
if (pipeIndex === 0 || cell.type === "cell") return fixer.insertTextBeforeRange(pipe.range, " ".repeat(diff));
|
|
10757
|
-
return fixer.insertTextAfterRange([cell.delimiter.range[0], cell.delimiter.range[0] + 1], "-".repeat(diff));
|
|
10758
|
-
}
|
|
10759
|
-
const baseEdit = fixRemoveSpaces();
|
|
10760
|
-
if (baseEdit) return baseEdit;
|
|
10761
|
-
if (pipeIndex === 0 || cell.type === "cell") return null;
|
|
10762
|
-
const beforeDelimiter = sourceCode.lines[cell.delimiter.loc.start.line - 1].slice(0, cell.delimiter.loc.start.column - 1);
|
|
10763
|
-
const widthBeforeDelimiter = getTextWidth(beforeDelimiter);
|
|
10764
|
-
const newLength = expected - widthBeforeDelimiter;
|
|
10765
|
-
const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
|
|
10766
|
-
const spaceAfter = table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? " " : "";
|
|
10767
|
-
if (newLength < minimumDelimiterLength + spaceAfter.length) return null;
|
|
10768
|
-
const delimiterPrefix = cell.align === "left" || cell.align === "center" ? ":" : "";
|
|
10769
|
-
const delimiterSuffix = (cell.align === "right" || cell.align === "center" ? ":" : "") + spaceAfter;
|
|
10770
|
-
const newDelimiter = "-".repeat(newLength - delimiterPrefix.length - delimiterSuffix.length);
|
|
10771
|
-
return fixer.replaceTextRange([cell.delimiter.range[0], pipe.range[0]], delimiterPrefix + newDelimiter + delimiterSuffix);
|
|
10772
|
-
/**
|
|
10773
|
-
* Fixer to remove spaces before the pipe
|
|
10774
|
-
*/
|
|
10775
|
-
function fixRemoveSpaces() {
|
|
10776
|
-
const beforePipe = sourceCode.lines[pipe.loc.start.line - 1].slice(0, pipe.loc.start.column - 1);
|
|
10777
|
-
const trimmedBeforePipe = beforePipe.trimEnd();
|
|
10778
|
-
const spacesBeforePipeLength = beforePipe.length - trimmedBeforePipe.length;
|
|
10779
|
-
const widthBeforePipe = getTextWidth(trimmedBeforePipe);
|
|
10780
|
-
const newSpacesLength = expected - widthBeforePipe;
|
|
10781
|
-
if (newSpacesLength < (table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? 1 : 0)) return null;
|
|
10782
|
-
return fixer.replaceTextRange([pipe.range[0] - spacesBeforePipeLength, pipe.range[0]], " ".repeat(newSpacesLength));
|
|
10783
|
-
}
|
|
10784
|
-
}
|
|
10785
|
-
});
|
|
10786
|
-
return false;
|
|
10787
|
-
}
|
|
10788
|
-
/**
|
|
10789
|
-
* Get the minimum delimiter length based on alignment
|
|
10790
|
-
*/
|
|
10791
|
-
function getMinimumDelimiterLength(align) {
|
|
10792
|
-
return align === "none" ? 1 : align === "center" ? 3 : 2;
|
|
10793
|
-
}
|
|
10794
|
-
return { table(node) {
|
|
10795
|
-
const parsed = parseTable(sourceCode, node);
|
|
10796
|
-
if (!parsed) return;
|
|
10797
|
-
verifyTablePipes(new TableContext(parsed));
|
|
10798
|
-
} };
|
|
10799
|
-
}
|
|
10800
|
-
});
|
|
10801
|
-
/**
|
|
10802
|
-
* Convert a parsed table row to row data
|
|
10803
|
-
*/
|
|
10804
|
-
function parsedTableRowToRowData(parsedRow) {
|
|
10805
|
-
return { cells: parsedRow.cells.map((cell, index) => {
|
|
10806
|
-
const nextCell = index + 1 < parsedRow.cells.length ? parsedRow.cells[index + 1] : null;
|
|
10807
|
-
return {
|
|
10808
|
-
type: "cell",
|
|
10809
|
-
leadingPipe: cell.leadingPipe,
|
|
10810
|
-
content: cell.cell,
|
|
10811
|
-
trailingPipe: nextCell ? nextCell.leadingPipe : parsedRow.trailingPipe
|
|
10812
|
-
};
|
|
10813
|
-
}) };
|
|
10814
|
-
}
|
|
10815
|
-
/**
|
|
10816
|
-
* Convert a parsed table delimiter row to row data
|
|
10817
|
-
*/
|
|
10818
|
-
function parsedTableDelimiterRowToRowData(parsedDelimiterRow) {
|
|
10819
|
-
return { cells: parsedDelimiterRow.delimiters.map((cell, index) => {
|
|
10820
|
-
const nextCell = index + 1 < parsedDelimiterRow.delimiters.length ? parsedDelimiterRow.delimiters[index + 1] : null;
|
|
10821
|
-
return {
|
|
10822
|
-
type: "delimiter",
|
|
10823
|
-
leadingPipe: cell.leadingPipe,
|
|
10824
|
-
delimiter: cell.delimiter,
|
|
10825
|
-
align: cell.delimiter.align,
|
|
10826
|
-
trailingPipe: nextCell ? nextCell.leadingPipe : parsedDelimiterRow.trailingPipe
|
|
10827
|
-
};
|
|
10828
|
-
}) };
|
|
10829
|
-
}
|
|
10830
|
-
|
|
10831
|
-
//#endregion
|
|
10832
|
-
//#region src/rules/table-pipe-spacing.ts
|
|
10833
|
-
/**
|
|
10834
|
-
* Parsed options
|
|
10835
|
-
*/
|
|
10836
|
-
function parseOptions(options) {
|
|
10837
|
-
const spaceOption = options?.space;
|
|
10838
|
-
const leadingSpace = (typeof spaceOption === "object" ? spaceOption.leading : spaceOption) || "always";
|
|
10839
|
-
const trailingSpace = (typeof spaceOption === "object" ? spaceOption.trailing : spaceOption) || "always";
|
|
10840
|
-
const cellAlignOption = options?.cellAlign;
|
|
10841
|
-
const defaultDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.defaultDelimiter : cellAlignOption) || "left";
|
|
10842
|
-
const leftAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.leftAlignmentDelimiter : cellAlignOption) || "left";
|
|
10843
|
-
const centerAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.centerAlignmentDelimiter : cellAlignOption) || "center";
|
|
10844
|
-
const rightAlignmentDelimiterCellAlign = (typeof cellAlignOption === "object" ? cellAlignOption.rightAlignmentDelimiter : cellAlignOption) || "right";
|
|
10845
|
-
return {
|
|
10846
|
-
leadingSpace,
|
|
10847
|
-
trailingSpace,
|
|
10848
|
-
cellAlignByDelimiter: {
|
|
10849
|
-
none: adjustAlign(defaultDelimiterCellAlign),
|
|
10850
|
-
left: adjustAlign(leftAlignmentDelimiterCellAlign),
|
|
10851
|
-
center: adjustAlign(centerAlignmentDelimiterCellAlign),
|
|
10852
|
-
right: adjustAlign(rightAlignmentDelimiterCellAlign)
|
|
10853
|
-
}
|
|
10854
|
-
};
|
|
10855
|
-
/**
|
|
10856
|
-
* Adjust the alignment option based on the spacing options.
|
|
10857
|
-
*/
|
|
10858
|
-
function adjustAlign(align) {
|
|
10859
|
-
if (align === "left") {
|
|
10860
|
-
if (trailingSpace === "always") return "left";
|
|
10861
|
-
return "ignore";
|
|
10862
|
-
}
|
|
10863
|
-
if (align === "center") {
|
|
10864
|
-
if (leadingSpace === "always" && trailingSpace === "always") return "center";
|
|
10865
|
-
return "ignore";
|
|
10866
|
-
}
|
|
10867
|
-
if (align === "right") {
|
|
10868
|
-
if (leadingSpace === "always") return "right";
|
|
10869
|
-
return "ignore";
|
|
10870
|
-
}
|
|
10871
|
-
return align;
|
|
10872
|
-
}
|
|
10873
|
-
}
|
|
10874
|
-
var table_pipe_spacing_default = createRule("table-pipe-spacing", {
|
|
10875
|
-
meta: {
|
|
10876
|
-
type: "layout",
|
|
10877
|
-
docs: {
|
|
10878
|
-
description: "enforce consistent spacing around table pipes",
|
|
10879
|
-
categories: ["standard"],
|
|
10880
|
-
listCategory: "Whitespace"
|
|
10881
|
-
},
|
|
10882
|
-
fixable: "whitespace",
|
|
10883
|
-
hasSuggestions: false,
|
|
10884
|
-
schema: [{
|
|
10885
|
-
type: "object",
|
|
10886
|
-
properties: {
|
|
10887
|
-
space: { anyOf: [{ enum: ["always", "never"] }, {
|
|
10888
|
-
type: "object",
|
|
10889
|
-
properties: {
|
|
10890
|
-
leading: { enum: ["always", "never"] },
|
|
10891
|
-
trailing: { enum: ["always", "never"] }
|
|
10892
|
-
},
|
|
10893
|
-
additionalProperties: false
|
|
10894
|
-
}] },
|
|
10895
|
-
cellAlign: { anyOf: [{ enum: [
|
|
10896
|
-
"left",
|
|
10897
|
-
"center",
|
|
10898
|
-
"right"
|
|
10899
|
-
] }, {
|
|
10900
|
-
type: "object",
|
|
10901
|
-
properties: {
|
|
10902
|
-
defaultDelimiter: { enum: [
|
|
10903
|
-
"left",
|
|
10904
|
-
"center",
|
|
10905
|
-
"right",
|
|
10906
|
-
"ignore"
|
|
10907
|
-
] },
|
|
10908
|
-
leftAlignmentDelimiter: { enum: [
|
|
10909
|
-
"left",
|
|
10910
|
-
"center",
|
|
10911
|
-
"right",
|
|
10912
|
-
"ignore"
|
|
10913
|
-
] },
|
|
10914
|
-
centerAlignmentDelimiter: { enum: [
|
|
10915
|
-
"left",
|
|
10916
|
-
"center",
|
|
10917
|
-
"right",
|
|
10918
|
-
"ignore"
|
|
10919
|
-
] },
|
|
10920
|
-
rightAlignmentDelimiter: { enum: [
|
|
10921
|
-
"left",
|
|
10922
|
-
"center",
|
|
10923
|
-
"right",
|
|
10924
|
-
"ignore"
|
|
10925
|
-
] }
|
|
10926
|
-
},
|
|
10927
|
-
additionalProperties: false
|
|
10928
|
-
}] }
|
|
10929
|
-
},
|
|
10930
|
-
additionalProperties: false
|
|
10931
|
-
}],
|
|
10932
|
-
messages: {
|
|
10933
|
-
expectedSpaceBefore: "Expected 1 space before \"|\".",
|
|
10934
|
-
expectedNoSpaceBefore: "Expected no space before \"|\".",
|
|
10935
|
-
expectedSpaceAfter: "Expected 1 space after \"|\".",
|
|
10936
|
-
expectedNoSpaceAfter: "Expected no space after \"|\".",
|
|
10937
|
-
expectedAlignLeft: "Expected 1 space after \"|\" for left-aligned column.",
|
|
10938
|
-
expectedNoSpaceAlignLeft: "Expected no space after \"|\" for left-aligned column.",
|
|
10939
|
-
expectedAlignRight: "Expected 1 space before \"|\" for right-aligned column.",
|
|
10940
|
-
expectedNoSpaceAlignRight: "Expected no space before \"|\" for right-aligned column.",
|
|
10941
|
-
expectedAlignCenter: "Expected the number of spaces before and after the content to be the same or differ by 1 at most for center-aligned column."
|
|
10942
|
-
}
|
|
10943
|
-
},
|
|
10944
|
-
create(context) {
|
|
10945
|
-
const sourceCode = context.sourceCode;
|
|
10946
|
-
const options = parseOptions(context.options[0]);
|
|
10947
|
-
/**
|
|
10948
|
-
* Verify for the leading pipe.
|
|
10949
|
-
*/
|
|
10950
|
-
function verifyLeadingPipe(pipe, nextToken) {
|
|
10951
|
-
if (options.leadingSpace === "always") {
|
|
10952
|
-
if (pipe.range[1] < nextToken.range[0]) return true;
|
|
10953
|
-
context.report({
|
|
10954
|
-
loc: pipe.loc,
|
|
10955
|
-
messageId: "expectedSpaceAfter",
|
|
10956
|
-
fix(fixer) {
|
|
10957
|
-
return fixer.insertTextAfterRange(pipe.range, " ");
|
|
10958
|
-
}
|
|
10959
|
-
});
|
|
10960
|
-
return false;
|
|
10961
|
-
} else if (options.leadingSpace === "never") {
|
|
10962
|
-
if (pipe.range[1] === nextToken.range[0]) return true;
|
|
10963
|
-
context.report({
|
|
10964
|
-
loc: {
|
|
10965
|
-
start: pipe.loc.end,
|
|
10966
|
-
end: nextToken.loc.start
|
|
10967
|
-
},
|
|
10968
|
-
messageId: "expectedNoSpaceAfter",
|
|
10969
|
-
fix(fixer) {
|
|
10970
|
-
return fixer.removeRange([pipe.range[1], nextToken.range[0]]);
|
|
10971
|
-
}
|
|
10972
|
-
});
|
|
10973
|
-
return false;
|
|
10835
|
+
});
|
|
10836
|
+
return false;
|
|
10837
|
+
} else if (options.leadingSpace === "never") {
|
|
10838
|
+
if (pipe.range[1] === nextToken.range[0]) return true;
|
|
10839
|
+
context.report({
|
|
10840
|
+
loc: {
|
|
10841
|
+
start: pipe.loc.end,
|
|
10842
|
+
end: nextToken.loc.start
|
|
10843
|
+
},
|
|
10844
|
+
messageId: "expectedNoSpaceAfter",
|
|
10845
|
+
fix(fixer) {
|
|
10846
|
+
return fixer.removeRange([pipe.range[1], nextToken.range[0]]);
|
|
10847
|
+
}
|
|
10848
|
+
});
|
|
10849
|
+
return false;
|
|
10974
10850
|
}
|
|
10975
10851
|
return true;
|
|
10976
10852
|
}
|
|
@@ -11201,6 +11077,256 @@ var table_pipe_spacing_default = createRule("table-pipe-spacing", {
|
|
|
11201
11077
|
}
|
|
11202
11078
|
});
|
|
11203
11079
|
|
|
11080
|
+
//#endregion
|
|
11081
|
+
//#region src/rules/table-pipe-alignment.ts
|
|
11082
|
+
var table_pipe_alignment_default = createRule("table-pipe-alignment", {
|
|
11083
|
+
meta: {
|
|
11084
|
+
type: "layout",
|
|
11085
|
+
docs: {
|
|
11086
|
+
description: "enforce consistent alignment of table pipes",
|
|
11087
|
+
categories: ["standard"],
|
|
11088
|
+
listCategory: "Decorative"
|
|
11089
|
+
},
|
|
11090
|
+
fixable: "code",
|
|
11091
|
+
hasSuggestions: false,
|
|
11092
|
+
schema: [{
|
|
11093
|
+
type: "object",
|
|
11094
|
+
properties: { column: { enum: ["minimum", "consistent"] } },
|
|
11095
|
+
additionalProperties: false
|
|
11096
|
+
}],
|
|
11097
|
+
messages: {
|
|
11098
|
+
addSpaces: "Table pipe should be aligned at column {{expected}} (add {{count}} character{{plural}}).",
|
|
11099
|
+
removeSpaces: "Table pipe should be aligned at column {{expected}} (remove {{count}} character{{plural}})."
|
|
11100
|
+
}
|
|
11101
|
+
},
|
|
11102
|
+
create(context) {
|
|
11103
|
+
const sourceCode = context.sourceCode;
|
|
11104
|
+
const columnOption = (context.options[0] || {}).column || "minimum";
|
|
11105
|
+
class TableContext {
|
|
11106
|
+
rows;
|
|
11107
|
+
columnCount;
|
|
11108
|
+
_cacheHasSpaceBetweenContentAndTrailingPipe = /* @__PURE__ */ new Map();
|
|
11109
|
+
_cacheExpectedPipePosition = /* @__PURE__ */ new Map();
|
|
11110
|
+
constructor(parsed) {
|
|
11111
|
+
const rows = [parsedTableRowToRowData(parsed.headerRow), parsedTableDelimiterRowToRowData(parsed.delimiterRow)];
|
|
11112
|
+
for (const bodyRow of parsed.bodyRows) rows.push(parsedTableRowToRowData(bodyRow));
|
|
11113
|
+
this.rows = rows;
|
|
11114
|
+
let columnCount = 0;
|
|
11115
|
+
for (const row of rows) columnCount = Math.max(columnCount, row.cells.length);
|
|
11116
|
+
this.columnCount = columnCount;
|
|
11117
|
+
}
|
|
11118
|
+
/**
|
|
11119
|
+
* Get the expected pipe position for the index
|
|
11120
|
+
*/
|
|
11121
|
+
getExpectedPipePosition(pipeIndex) {
|
|
11122
|
+
let v = this._cacheExpectedPipePosition.get(pipeIndex);
|
|
11123
|
+
if (v !== void 0) return v;
|
|
11124
|
+
v = this._computeExpectedPipePositionWithoutCache(pipeIndex);
|
|
11125
|
+
this._cacheExpectedPipePosition.set(pipeIndex, v);
|
|
11126
|
+
return v;
|
|
11127
|
+
}
|
|
11128
|
+
/**
|
|
11129
|
+
* Check if there is at least one space between content and trailing pipe
|
|
11130
|
+
* for the index
|
|
11131
|
+
*
|
|
11132
|
+
* This is used to determine if the pipe should be aligned with a space before it.
|
|
11133
|
+
*/
|
|
11134
|
+
hasSpaceBetweenContentAndTrailingPipe(pipeIndex) {
|
|
11135
|
+
if (pipeIndex === 0) return false;
|
|
11136
|
+
let v = this._cacheHasSpaceBetweenContentAndTrailingPipe.get(pipeIndex);
|
|
11137
|
+
if (v != null) return v;
|
|
11138
|
+
v = this._hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex);
|
|
11139
|
+
this._cacheHasSpaceBetweenContentAndTrailingPipe.set(pipeIndex, v);
|
|
11140
|
+
return v;
|
|
11141
|
+
}
|
|
11142
|
+
/**
|
|
11143
|
+
* Get the expected pipe position for the index
|
|
11144
|
+
*/
|
|
11145
|
+
_computeExpectedPipePositionWithoutCache(pipeIndex) {
|
|
11146
|
+
if (pipeIndex === 0) {
|
|
11147
|
+
const firstCell = this.rows[0].cells[0];
|
|
11148
|
+
const firstToken = firstCell.leadingPipe ?? firstCell.content;
|
|
11149
|
+
if (!firstToken) return null;
|
|
11150
|
+
return getTextWidth(sourceCode.lines[firstToken.loc.start.line - 1].slice(0, firstToken.loc.start.column - 1));
|
|
11151
|
+
}
|
|
11152
|
+
if (columnOption === "minimum") return this.getMinimumPipePosition(pipeIndex);
|
|
11153
|
+
else if (columnOption === "consistent") {
|
|
11154
|
+
const columnIndex = pipeIndex - 1;
|
|
11155
|
+
for (const row of this.rows) {
|
|
11156
|
+
if (row.cells.length <= columnIndex) continue;
|
|
11157
|
+
const cell = row.cells[columnIndex];
|
|
11158
|
+
if (cell.type === "delimiter" || !cell.trailingPipe) continue;
|
|
11159
|
+
const width = getTextWidth(sourceCode.lines[cell.trailingPipe.loc.start.line - 1].slice(0, cell.trailingPipe.loc.start.column - 1));
|
|
11160
|
+
return Math.max(width, this.getMinimumPipePosition(pipeIndex) || 0);
|
|
11161
|
+
}
|
|
11162
|
+
}
|
|
11163
|
+
return null;
|
|
11164
|
+
}
|
|
11165
|
+
/**
|
|
11166
|
+
* Get the minimum pipe position for the index
|
|
11167
|
+
*/
|
|
11168
|
+
getMinimumPipePosition(pipeIndex) {
|
|
11169
|
+
const spacingRuleOptions = getCurrentTablePipeSpacingOption(sourceCode);
|
|
11170
|
+
const needSpaceBeforePipe = spacingRuleOptions ? spacingRuleOptions.trailingSpace === "always" : this.hasSpaceBetweenContentAndTrailingPipe(pipeIndex);
|
|
11171
|
+
let maxWidth = 0;
|
|
11172
|
+
const columnIndex = pipeIndex - 1;
|
|
11173
|
+
for (const row of this.rows) {
|
|
11174
|
+
if (row.cells.length <= columnIndex) continue;
|
|
11175
|
+
const cell = row.cells[columnIndex];
|
|
11176
|
+
let width;
|
|
11177
|
+
if (cell.type === "delimiter") {
|
|
11178
|
+
const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
|
|
11179
|
+
width = getTextWidth(sourceCode.lines[cell.delimiter.loc.start.line - 1].slice(0, cell.delimiter.loc.start.column - 1)) + minimumDelimiterLength;
|
|
11180
|
+
} else {
|
|
11181
|
+
if (!cell.content) continue;
|
|
11182
|
+
width = getTextWidth(sourceCode.lines[cell.content.loc.end.line - 1].slice(0, cell.content.loc.end.column - 1));
|
|
11183
|
+
}
|
|
11184
|
+
if (needSpaceBeforePipe) width += 1;
|
|
11185
|
+
maxWidth = Math.max(maxWidth, width);
|
|
11186
|
+
}
|
|
11187
|
+
return maxWidth;
|
|
11188
|
+
}
|
|
11189
|
+
/**
|
|
11190
|
+
* Check if there is at least one space between content and trailing pipe
|
|
11191
|
+
*/
|
|
11192
|
+
_hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex) {
|
|
11193
|
+
const columnIndex = pipeIndex - 1;
|
|
11194
|
+
for (const row of this.rows) {
|
|
11195
|
+
if (row.cells.length <= columnIndex) continue;
|
|
11196
|
+
const cell = row.cells[columnIndex];
|
|
11197
|
+
if (!cell.trailingPipe) continue;
|
|
11198
|
+
let content;
|
|
11199
|
+
if (cell.type === "delimiter") content = cell.delimiter;
|
|
11200
|
+
else {
|
|
11201
|
+
if (!cell.content) continue;
|
|
11202
|
+
content = cell.content;
|
|
11203
|
+
}
|
|
11204
|
+
if (content.range[1] < cell.trailingPipe.range[0]) continue;
|
|
11205
|
+
return false;
|
|
11206
|
+
}
|
|
11207
|
+
return true;
|
|
11208
|
+
}
|
|
11209
|
+
}
|
|
11210
|
+
/**
|
|
11211
|
+
* Verify the table pipes
|
|
11212
|
+
*/
|
|
11213
|
+
function verifyTablePipes(table) {
|
|
11214
|
+
const targetRows = [...table.rows];
|
|
11215
|
+
for (const row of targetRows) for (let pipeIndex = 0; pipeIndex <= table.columnCount; pipeIndex++) if (!verifyRowPipe(row, pipeIndex, table)) break;
|
|
11216
|
+
}
|
|
11217
|
+
/**
|
|
11218
|
+
* Verify the pipe in the row
|
|
11219
|
+
*/
|
|
11220
|
+
function verifyRowPipe(row, pipeIndex, table) {
|
|
11221
|
+
let cellIndex;
|
|
11222
|
+
let pipe;
|
|
11223
|
+
if (pipeIndex === 0) {
|
|
11224
|
+
cellIndex = 0;
|
|
11225
|
+
pipe = "leadingPipe";
|
|
11226
|
+
} else {
|
|
11227
|
+
cellIndex = pipeIndex - 1;
|
|
11228
|
+
pipe = "trailingPipe";
|
|
11229
|
+
}
|
|
11230
|
+
if (row.cells.length <= cellIndex) return true;
|
|
11231
|
+
const cell = row.cells[cellIndex];
|
|
11232
|
+
const pipeToken = cell[pipe];
|
|
11233
|
+
if (!pipeToken) return true;
|
|
11234
|
+
return verifyPipe(pipeToken, pipeIndex, table, cell);
|
|
11235
|
+
}
|
|
11236
|
+
/**
|
|
11237
|
+
* Verify the pipe position
|
|
11238
|
+
*/
|
|
11239
|
+
function verifyPipe(pipe, pipeIndex, table, cell) {
|
|
11240
|
+
const expected = table.getExpectedPipePosition(pipeIndex);
|
|
11241
|
+
if (expected == null) return true;
|
|
11242
|
+
const actual = getTextWidth(sourceCode.lines[pipe.loc.start.line - 1].slice(0, pipe.loc.start.column - 1));
|
|
11243
|
+
const diff = expected - actual;
|
|
11244
|
+
if (diff === 0) return true;
|
|
11245
|
+
context.report({
|
|
11246
|
+
loc: pipe.loc,
|
|
11247
|
+
messageId: diff > 0 ? "addSpaces" : "removeSpaces",
|
|
11248
|
+
data: {
|
|
11249
|
+
expected: String(expected),
|
|
11250
|
+
count: String(Math.abs(diff)),
|
|
11251
|
+
plural: Math.abs(diff) === 1 ? "" : "s"
|
|
11252
|
+
},
|
|
11253
|
+
fix(fixer) {
|
|
11254
|
+
if (diff > 0) {
|
|
11255
|
+
if (pipeIndex === 0 || cell.type === "cell") return fixer.insertTextBeforeRange(pipe.range, " ".repeat(diff));
|
|
11256
|
+
return fixer.insertTextAfterRange([cell.delimiter.range[0], cell.delimiter.range[0] + 1], "-".repeat(diff));
|
|
11257
|
+
}
|
|
11258
|
+
const baseEdit = fixRemoveSpaces();
|
|
11259
|
+
if (baseEdit) return baseEdit;
|
|
11260
|
+
if (pipeIndex === 0 || cell.type === "cell") return null;
|
|
11261
|
+
const beforeDelimiter = sourceCode.lines[cell.delimiter.loc.start.line - 1].slice(0, cell.delimiter.loc.start.column - 1);
|
|
11262
|
+
const widthBeforeDelimiter = getTextWidth(beforeDelimiter);
|
|
11263
|
+
const newLength = expected - widthBeforeDelimiter;
|
|
11264
|
+
const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
|
|
11265
|
+
const spaceAfter = table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? " " : "";
|
|
11266
|
+
if (newLength < minimumDelimiterLength + spaceAfter.length) return null;
|
|
11267
|
+
const delimiterPrefix = cell.align === "left" || cell.align === "center" ? ":" : "";
|
|
11268
|
+
const delimiterSuffix = (cell.align === "right" || cell.align === "center" ? ":" : "") + spaceAfter;
|
|
11269
|
+
const newDelimiter = "-".repeat(newLength - delimiterPrefix.length - delimiterSuffix.length);
|
|
11270
|
+
return fixer.replaceTextRange([cell.delimiter.range[0], pipe.range[0]], delimiterPrefix + newDelimiter + delimiterSuffix);
|
|
11271
|
+
/**
|
|
11272
|
+
* Fixer to remove spaces before the pipe
|
|
11273
|
+
*/
|
|
11274
|
+
function fixRemoveSpaces() {
|
|
11275
|
+
const beforePipe = sourceCode.lines[pipe.loc.start.line - 1].slice(0, pipe.loc.start.column - 1);
|
|
11276
|
+
const trimmedBeforePipe = beforePipe.trimEnd();
|
|
11277
|
+
const spacesBeforePipeLength = beforePipe.length - trimmedBeforePipe.length;
|
|
11278
|
+
const widthBeforePipe = getTextWidth(trimmedBeforePipe);
|
|
11279
|
+
const newSpacesLength = expected - widthBeforePipe;
|
|
11280
|
+
if (newSpacesLength < (table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? 1 : 0)) return null;
|
|
11281
|
+
return fixer.replaceTextRange([pipe.range[0] - spacesBeforePipeLength, pipe.range[0]], " ".repeat(newSpacesLength));
|
|
11282
|
+
}
|
|
11283
|
+
}
|
|
11284
|
+
});
|
|
11285
|
+
return false;
|
|
11286
|
+
}
|
|
11287
|
+
/**
|
|
11288
|
+
* Get the minimum delimiter length based on alignment
|
|
11289
|
+
*/
|
|
11290
|
+
function getMinimumDelimiterLength(align) {
|
|
11291
|
+
return align === "none" ? 1 : align === "center" ? 3 : 2;
|
|
11292
|
+
}
|
|
11293
|
+
return { table(node) {
|
|
11294
|
+
const parsed = parseTable(sourceCode, node);
|
|
11295
|
+
if (!parsed) return;
|
|
11296
|
+
verifyTablePipes(new TableContext(parsed));
|
|
11297
|
+
} };
|
|
11298
|
+
}
|
|
11299
|
+
});
|
|
11300
|
+
/**
|
|
11301
|
+
* Convert a parsed table row to row data
|
|
11302
|
+
*/
|
|
11303
|
+
function parsedTableRowToRowData(parsedRow) {
|
|
11304
|
+
return { cells: parsedRow.cells.map((cell, index) => {
|
|
11305
|
+
const nextCell = index + 1 < parsedRow.cells.length ? parsedRow.cells[index + 1] : null;
|
|
11306
|
+
return {
|
|
11307
|
+
type: "cell",
|
|
11308
|
+
leadingPipe: cell.leadingPipe,
|
|
11309
|
+
content: cell.cell,
|
|
11310
|
+
trailingPipe: nextCell ? nextCell.leadingPipe : parsedRow.trailingPipe
|
|
11311
|
+
};
|
|
11312
|
+
}) };
|
|
11313
|
+
}
|
|
11314
|
+
/**
|
|
11315
|
+
* Convert a parsed table delimiter row to row data
|
|
11316
|
+
*/
|
|
11317
|
+
function parsedTableDelimiterRowToRowData(parsedDelimiterRow) {
|
|
11318
|
+
return { cells: parsedDelimiterRow.delimiters.map((cell, index) => {
|
|
11319
|
+
const nextCell = index + 1 < parsedDelimiterRow.delimiters.length ? parsedDelimiterRow.delimiters[index + 1] : null;
|
|
11320
|
+
return {
|
|
11321
|
+
type: "delimiter",
|
|
11322
|
+
leadingPipe: cell.leadingPipe,
|
|
11323
|
+
delimiter: cell.delimiter,
|
|
11324
|
+
align: cell.delimiter.align,
|
|
11325
|
+
trailingPipe: nextCell ? nextCell.leadingPipe : parsedDelimiterRow.trailingPipe
|
|
11326
|
+
};
|
|
11327
|
+
}) };
|
|
11328
|
+
}
|
|
11329
|
+
|
|
11204
11330
|
//#endregion
|
|
11205
11331
|
//#region src/rules/thematic-break-character-style.ts
|
|
11206
11332
|
var thematic_break_character_style_default = createRule("thematic-break-character-style", {
|
|
@@ -11442,6 +11568,7 @@ const rules$1 = [
|
|
|
11442
11568
|
ordered_list_marker_sequence_default,
|
|
11443
11569
|
ordered_list_marker_start_default,
|
|
11444
11570
|
ordered_list_marker_style_default,
|
|
11571
|
+
padded_custom_containers_default,
|
|
11445
11572
|
padding_line_between_blocks_default,
|
|
11446
11573
|
prefer_autolinks_default,
|
|
11447
11574
|
prefer_fenced_code_blocks_default,
|
|
@@ -11539,6 +11666,7 @@ const rules$2 = {
|
|
|
11539
11666
|
"markdown-preferences/ordered-list-marker-sequence": "error",
|
|
11540
11667
|
"markdown-preferences/ordered-list-marker-start": "error",
|
|
11541
11668
|
"markdown-preferences/ordered-list-marker-style": "error",
|
|
11669
|
+
"markdown-preferences/padded-custom-containers": "error",
|
|
11542
11670
|
"markdown-preferences/padding-line-between-blocks": "error",
|
|
11543
11671
|
"markdown-preferences/prefer-autolinks": "error",
|
|
11544
11672
|
"markdown-preferences/prefer-fenced-code-blocks": "error",
|
|
@@ -11560,7 +11688,7 @@ var meta_exports = /* @__PURE__ */ __export({
|
|
|
11560
11688
|
version: () => version
|
|
11561
11689
|
});
|
|
11562
11690
|
const name = "eslint-plugin-markdown-preferences";
|
|
11563
|
-
const version = "0.
|
|
11691
|
+
const version = "0.29.1";
|
|
11564
11692
|
|
|
11565
11693
|
//#endregion
|
|
11566
11694
|
//#region src/language/extensions/micromark-custom-container.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-markdown-preferences",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.1",
|
|
4
4
|
"description": "ESLint plugin that enforces our markdown preferences",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"markdownlint": "npx -y markdownlint-cli2 .",
|
|
26
26
|
"test": "npm run mocha -- \"tests/src/**/*.ts\" --reporter=dot --timeout=60000",
|
|
27
27
|
"test:debug": "node --experimental-strip-types --experimental-transform-types ./node_modules/mocha/bin/mocha.js \"tests/src/**/*.ts\" --reporter=dot --timeout=60000",
|
|
28
|
-
"cover": "c8 --reporter=lcov npm run test",
|
|
28
|
+
"cover": "c8 --reporter=lcov --reporter=text npm run test:debug",
|
|
29
29
|
"test:update": "npm run mocha -- \"tests/src/**/*.ts\" --reporter=dot --update",
|
|
30
30
|
"update": "npm run ts -- ./tools/update.ts && npm run eslint-fix",
|
|
31
31
|
"update:resources": "npm run ts -- ./tools/update-resources.ts && npm run eslint-fix",
|