rubocop-prose 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/AGENTS.md +10 -2
- data/CHANGELOG.md +20 -0
- data/CONTRIBUTING.md +17 -7
- data/DESIGN.md +13 -5
- data/README.md +37 -20
- data/RELEASING.md +8 -8
- data/UPGRADING.md +16 -0
- data/assets/README.md +1 -1
- data/config/cops/markdown/code_block_style.yml +1 -1
- data/config/cops/markdown/emphasis_style.yml +4 -0
- data/config/cops/markdown/fence_style.yml +1 -1
- data/config/cops/markdown/first_heading.yml +1 -2
- data/config/cops/markdown/front_matter_keys.yml +5 -0
- data/config/cops/markdown/front_matter_syntax.yml +3 -0
- data/config/cops/markdown/hard_break_style.yml +3 -0
- data/config/cops/markdown/hard_tabs.yml +1 -1
- data/config/cops/markdown/heading_capitalization.yml +31 -0
- data/config/cops/markdown/heading_style.yml +1 -1
- data/config/cops/markdown/{syntax.yml → kramdown_syntax.yml} +1 -1
- data/config/cops/markdown/list_item_capitalization.yml +32 -0
- data/config/cops/markdown/list_item_punctuation.yml +13 -0
- data/config/cops/markdown/list_marker_spacing.yml +6 -5
- data/config/cops/markdown/ordered_list_numbering.yml +1 -1
- data/config/cops/markdown/reference_definitions.yml +2 -3
- data/config/cops/markdown/strong_style.yml +4 -0
- data/config/cops/markdown/structural_line_length.yml +1 -4
- data/config/cops/markdown/table_pipes.yml +6 -0
- data/config/cops/markdown/table_spacing.yml +4 -0
- data/config/cops/markdown/trailing_whitespace.yml +1 -0
- data/config/cops/markdown/unordered_list_marker.yml +1 -1
- data/config/cops/prose/sentence_capitalization.yml +9 -0
- data/config/cops/text/hard_tabs.yml +3 -0
- data/config/cops/text/proper_names.yml +4 -0
- data/config/obsoletion.yml +45 -0
- data/docs/cops/markdown/blockquote_spacing.md +2 -0
- data/docs/cops/markdown/code_block_style.md +11 -2
- data/docs/cops/markdown/duplicate_headings.md +51 -0
- data/docs/cops/markdown/emphasis_style.md +5 -1
- data/docs/cops/markdown/fence_style.md +11 -2
- data/docs/cops/markdown/first_heading.md +29 -3
- data/docs/cops/markdown/front_matter_keys.md +57 -0
- data/docs/cops/markdown/front_matter_syntax.md +32 -0
- data/docs/cops/markdown/hard_break_style.md +10 -5
- data/docs/cops/markdown/hard_tabs.md +3 -3
- data/docs/cops/markdown/heading_capitalization.md +176 -0
- data/docs/cops/markdown/heading_style.md +11 -2
- data/docs/cops/markdown/{syntax.md → kramdown_syntax.md} +6 -2
- data/docs/cops/markdown/list_item_capitalization.md +115 -0
- data/docs/cops/markdown/list_item_punctuation.md +70 -0
- data/docs/cops/markdown/list_marker_spacing.md +57 -7
- data/docs/cops/markdown/ordered_list_numbering.md +10 -1
- data/docs/cops/markdown/proper_names.md +3 -3
- data/docs/cops/markdown/raw_html.md +99 -6
- data/docs/cops/markdown/reference_definitions.md +30 -4
- data/docs/cops/markdown/strong_style.md +5 -1
- data/docs/cops/markdown/structural_line_length.md +31 -7
- data/docs/cops/markdown/table_pipes.md +7 -1
- data/docs/cops/markdown/table_spacing.md +5 -1
- data/docs/cops/markdown/thematic_break_style.md +2 -0
- data/docs/cops/markdown/trailing_whitespace.md +29 -0
- data/docs/cops/markdown/unordered_list_marker.md +11 -2
- data/docs/cops/prose/multiple_blank_lines.md +2 -0
- data/docs/cops/prose/sentence_capitalization.md +46 -0
- data/docs/cops/text/hard_tabs.md +28 -0
- data/docs/cops/text/proper_names.md +36 -0
- data/docs/settings/files.md +1 -1
- data/docs/settings/front_matter.md +2 -2
- data/lib/rubocop/cop/markdown/code_block_style.rb +1 -1
- data/lib/rubocop/cop/markdown/code_span_spacing.rb +2 -2
- data/lib/rubocop/cop/markdown/duplicate_headings.rb +55 -5
- data/lib/rubocop/cop/markdown/emphasis_spacing.rb +1 -1
- data/lib/rubocop/cop/markdown/emphasis_style.rb +7 -0
- data/lib/rubocop/cop/markdown/fence_style.rb +1 -1
- data/lib/rubocop/cop/markdown/first_heading.rb +13 -2
- data/lib/rubocop/cop/markdown/front_matter_keys.rb +70 -0
- data/lib/rubocop/cop/markdown/front_matter_syntax.rb +26 -0
- data/lib/rubocop/cop/markdown/hard_tabs.rb +11 -7
- data/lib/rubocop/cop/markdown/heading_capitalization.rb +43 -0
- data/lib/rubocop/cop/markdown/heading_style.rb +1 -1
- data/lib/rubocop/cop/markdown/{syntax.rb → kramdown_syntax.rb} +1 -1
- data/lib/rubocop/cop/markdown/list_item_capitalization.rb +90 -0
- data/lib/rubocop/cop/markdown/list_item_punctuation.rb +64 -0
- data/lib/rubocop/cop/markdown/list_marker_spacing.rb +13 -4
- data/lib/rubocop/cop/markdown/ordered_list_numbering.rb +1 -1
- data/lib/rubocop/cop/markdown/outside_spacing.rb +6 -6
- data/lib/rubocop/cop/markdown/proper_names.rb +20 -31
- data/lib/rubocop/cop/markdown/raw_html.rb +62 -7
- data/lib/rubocop/cop/markdown/reference_definitions.rb +15 -5
- data/lib/rubocop/cop/markdown/strong_style.rb +7 -0
- data/lib/rubocop/cop/markdown/structural_line_length.rb +7 -6
- data/lib/rubocop/cop/markdown/table_blank_lines.rb +1 -1
- data/lib/rubocop/cop/markdown/table_columns.rb +1 -1
- data/lib/rubocop/cop/markdown/table_pipes.rb +8 -1
- data/lib/rubocop/cop/markdown/table_spacing.rb +8 -1
- data/lib/rubocop/cop/markdown/thematic_break_style.rb +4 -0
- data/lib/rubocop/cop/markdown/trailing_whitespace.rb +6 -0
- data/lib/rubocop/cop/markdown/unordered_list_marker.rb +1 -1
- data/lib/rubocop/cop/prose/sentence_capitalization.rb +100 -0
- data/lib/rubocop/cop/text/hard_tabs.rb +21 -0
- data/lib/rubocop/cop/text/proper_names.rb +20 -0
- data/lib/rubocop/prose/capitalization_rules.rb +189 -0
- data/lib/rubocop/prose/inline_rules.rb +17 -10
- data/lib/rubocop/prose/link_rules.rb +34 -13
- data/lib/rubocop/prose/markdown_document.rb +30 -8
- data/lib/rubocop/prose/proper_name_rules.rb +31 -0
- data/lib/rubocop/prose/structural_blank_lines.rb +1 -1
- data/lib/rubocop/prose/table_rules.rb +1 -1
- data/lib/rubocop/prose/version.rb +1 -1
- data/lib/rubocop-prose.rb +3 -0
- metadata +32 -4
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Prose/SentenceCapitalization:
|
|
2
|
+
Description: Check capitalization of paragraph openings without rewriting literal terms.
|
|
3
|
+
Enabled: false
|
|
4
|
+
SafeAutoCorrect: false
|
|
5
|
+
Style: initial_capital
|
|
6
|
+
PreserveMixedCase: true
|
|
7
|
+
IgnoredWords: []
|
|
8
|
+
SupportedStyles:
|
|
9
|
+
- initial_capital
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
changed_parameters:
|
|
2
|
+
- cops: Markdown/StructuralLineLength
|
|
3
|
+
parameters:
|
|
4
|
+
- Max
|
|
5
|
+
- HeadingMax
|
|
6
|
+
- CodeBlockMax
|
|
7
|
+
reason: >-
|
|
8
|
+
Replace the shared limit and enable/value pairs with a positive integer width (or false) for each element:
|
|
9
|
+
Headings, CodeBlocks, and Tables. For example, use Headings: 120, CodeBlocks: false, and Tables: false.
|
|
10
|
+
- cops: Markdown/ReferenceDefinitions
|
|
11
|
+
parameters:
|
|
12
|
+
- CheckDuplicates
|
|
13
|
+
- AllowIdenticalDuplicates
|
|
14
|
+
reason: >-
|
|
15
|
+
Replace CheckDuplicates and AllowIdenticalDuplicates with Duplicates.
|
|
16
|
+
CheckDuplicates: false maps to Duplicates: allow, regardless of AllowIdenticalDuplicates.
|
|
17
|
+
CheckDuplicates: true (or omitted) with AllowIdenticalDuplicates: true maps to Duplicates: allow_identical.
|
|
18
|
+
Otherwise, the default maps to Duplicates: forbid.
|
|
19
|
+
Remove both legacy keys; combinations are not translated automatically.
|
|
20
|
+
- cops: Markdown/ReferenceDefinitions
|
|
21
|
+
parameters: CheckUnused
|
|
22
|
+
reason: 'Replace CheckUnused with Unused, preserving its boolean value (default: false).'
|
|
23
|
+
- cops:
|
|
24
|
+
- Markdown/CodeBlockStyle
|
|
25
|
+
- Markdown/FenceStyle
|
|
26
|
+
- Markdown/HeadingStyle
|
|
27
|
+
- Markdown/OrderedListNumbering
|
|
28
|
+
- Markdown/UnorderedListMarker
|
|
29
|
+
parameters: EnforcedStyle
|
|
30
|
+
alternative: Style
|
|
31
|
+
- cops: Markdown/ListMarkerSpacing
|
|
32
|
+
parameters:
|
|
33
|
+
- OrderedSingle
|
|
34
|
+
- OrderedMulti
|
|
35
|
+
- UnorderedSingle
|
|
36
|
+
- UnorderedMulti
|
|
37
|
+
reason: >-
|
|
38
|
+
Use Style (fixed or aligned) and MinSpaces instead.
|
|
39
|
+
These settings now apply to all list items, regardless of marker type or multiline content.
|
|
40
|
+
Different legacy spacing values cannot be preserved by a single policy; choose the desired shared spacing.
|
|
41
|
+
- cops: Markdown/FirstHeading
|
|
42
|
+
parameters:
|
|
43
|
+
- TitleKey
|
|
44
|
+
reason: >-
|
|
45
|
+
Set FrontMatterTitle to the desired metadata key, or false to disable the front-matter title exemption.
|
|
@@ -4,6 +4,8 @@ Requires one space after each nonempty blockquote marker, including nested marke
|
|
|
4
4
|
|
|
5
5
|
Empty quote lines and indentation inside quoted lists and code are preserved. Missing separators are autocorrected only when reparsing confirms the Markdown structure is unchanged; otherwise, the offense is report-only.
|
|
6
6
|
|
|
7
|
+
[Markdown/TrailingWhitespace](trailing_whitespace.md) independently trims trailing whitespace on empty quote lines; its opt-in `AllowEmptyBlockquoteSpace` permits one trailing space.
|
|
8
|
+
|
|
7
9
|
## Configuration
|
|
8
10
|
|
|
9
11
|
```yaml
|
|
@@ -9,7 +9,7 @@ Autocorrection is limited to standalone root-level blocks with blank boundaries.
|
|
|
9
9
|
```yaml
|
|
10
10
|
Markdown/CodeBlockStyle:
|
|
11
11
|
Enabled: false
|
|
12
|
-
|
|
12
|
+
Style: consistent # consistent, fenced or indented.
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Example
|
|
@@ -19,7 +19,7 @@ For this configuration:
|
|
|
19
19
|
```yaml
|
|
20
20
|
Markdown/CodeBlockStyle:
|
|
21
21
|
Enabled: true
|
|
22
|
-
|
|
22
|
+
Style: fenced
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### Bad
|
|
@@ -35,3 +35,12 @@ Markdown/CodeBlockStyle:
|
|
|
35
35
|
puts 'hello'
|
|
36
36
|
```
|
|
37
37
|
````
|
|
38
|
+
|
|
39
|
+
## Migrating From 0.1.0
|
|
40
|
+
|
|
41
|
+
Replace `EnforcedStyle` with `Style`:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
Markdown/CodeBlockStyle:
|
|
45
|
+
Style: fenced
|
|
46
|
+
```
|
|
@@ -12,6 +12,57 @@ Markdown/DuplicateHeadings:
|
|
|
12
12
|
Scope: siblings # Or document to compare headings across the entire document.
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Level-Specific Scopes
|
|
16
|
+
|
|
17
|
+
`Scope` accepts `document`, `siblings`, or `false` (disable duplicate checks). It also accepts a mapping with a required `Default` and level selectors. Unlisted levels inherit `Default`. Every value accepts the same three choices.
|
|
18
|
+
|
|
19
|
+
Selectors can be integer levels from 1 through 6, quoted inclusive ranges such as `"4-6"`, or quoted strict comparisons such as `">4"` (levels five and six) and `"<3"` (levels one and two). Overlapping selectors, reversed or empty ranges, missing defaults, and invalid scopes are configuration errors; there is no selector precedence.
|
|
20
|
+
|
|
21
|
+
For this configuration:
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
Markdown/DuplicateHeadings:
|
|
25
|
+
Scope:
|
|
26
|
+
Default: document
|
|
27
|
+
4: siblings
|
|
28
|
+
5: siblings
|
|
29
|
+
6: siblings
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Levels one through three require document-wide uniqueness. Deeper headings require uniqueness only among siblings:
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+
# Guide
|
|
36
|
+
|
|
37
|
+
## Services
|
|
38
|
+
|
|
39
|
+
### Service Overview
|
|
40
|
+
|
|
41
|
+
#### Details
|
|
42
|
+
|
|
43
|
+
## Clients
|
|
44
|
+
|
|
45
|
+
### Client Overview
|
|
46
|
+
|
|
47
|
+
#### Details
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Both `Details` headings are allowed because they have different parents. Replacing `Client Overview` with `Service Overview` is reported because level three uses document scope. Repeating `Details` under the same parent is still reported.
|
|
51
|
+
|
|
52
|
+
Each heading's effective scope determines which earlier headings it is compared against, including headings at other levels or with different configured scopes. This preserves existing cross-level comparison semantics: document scope compares against all earlier headings, while sibling scope compares against earlier headings sharing the same parent, including skipped levels.
|
|
53
|
+
|
|
54
|
+
To disable checks for deeper headings:
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
Markdown/DuplicateHeadings:
|
|
58
|
+
Scope:
|
|
59
|
+
Default: document
|
|
60
|
+
4: siblings
|
|
61
|
+
">4": false
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Alternatively, `"4-6": false` disables levels four through six. Disabled headings still establish parent ancestry and remain available for comparison when a later heading's effective scope checks them; they simply do not receive duplicate diagnostics themselves.
|
|
65
|
+
|
|
15
66
|
## Example
|
|
16
67
|
|
|
17
68
|
### Bad
|
|
@@ -9,7 +9,11 @@ Autocorrection preserves content. Intraword asterisks are not changed to undersc
|
|
|
9
9
|
```yaml
|
|
10
10
|
Markdown/EmphasisStyle:
|
|
11
11
|
Enabled: true
|
|
12
|
-
Style: consistent
|
|
12
|
+
Style: consistent
|
|
13
|
+
SupportedStyles:
|
|
14
|
+
- consistent
|
|
15
|
+
- asterisk
|
|
16
|
+
- underscore
|
|
13
17
|
```
|
|
14
18
|
|
|
15
19
|
## Example
|
|
@@ -9,7 +9,7 @@ Autocorrection preserves contents, language metadata, and nesting. Conversion to
|
|
|
9
9
|
```yaml
|
|
10
10
|
Markdown/FenceStyle:
|
|
11
11
|
Enabled: true
|
|
12
|
-
|
|
12
|
+
Style: consistent # consistent, backtick or tilde.
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Example
|
|
@@ -18,7 +18,7 @@ For this configuration:
|
|
|
18
18
|
|
|
19
19
|
```yaml
|
|
20
20
|
Markdown/FenceStyle:
|
|
21
|
-
|
|
21
|
+
Style: backtick
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
### Bad
|
|
@@ -36,3 +36,12 @@ puts 1
|
|
|
36
36
|
puts 1
|
|
37
37
|
```
|
|
38
38
|
````
|
|
39
|
+
|
|
40
|
+
## Migrating From 0.1.0
|
|
41
|
+
|
|
42
|
+
Replace `EnforcedStyle` with `Style`:
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
Markdown/FenceStyle:
|
|
46
|
+
Style: backtick
|
|
47
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Markdown/FirstHeading
|
|
2
2
|
|
|
3
|
-
Requires the first content line to be a heading at the configured level, unless
|
|
3
|
+
Requires the first content line to be a heading at the configured level, unless the configured front-matter metadata key contains a nonempty string. The default key is `title`; set `FrontMatterTitle: false` to require a heading even when front matter contains a title. Empty documents are accepted.
|
|
4
4
|
|
|
5
5
|
Front-matter titles must be strings; YAML aliases are not accepted. Report-only: adding or moving a heading changes structure.
|
|
6
6
|
|
|
@@ -10,8 +10,7 @@ Front-matter titles must be strings; YAML aliases are not accepted. Report-only:
|
|
|
10
10
|
Markdown/FirstHeading:
|
|
11
11
|
Enabled: false
|
|
12
12
|
Level: 1
|
|
13
|
-
FrontMatterTitle:
|
|
14
|
-
TitleKey: title # Exact top-level YAML key, not a regular expression.
|
|
13
|
+
FrontMatterTitle: title # Exact top-level YAML key, or false to disable the exemption.
|
|
15
14
|
```
|
|
16
15
|
|
|
17
16
|
## Example
|
|
@@ -29,3 +28,30 @@ An introduction to the project.
|
|
|
29
28
|
|
|
30
29
|
An introduction to the project.
|
|
31
30
|
```
|
|
31
|
+
|
|
32
|
+
### Good Front Matter Title
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+
---
|
|
36
|
+
title: Introduction
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
An introduction to the project.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Migrating From 0.1.0
|
|
43
|
+
|
|
44
|
+
In 0.1.0, `FrontMatterTitle: true` enabled the exemption and `TitleKey` selected the metadata key. Replace that pair with one setting: a nonempty key string, or `false` to disable the exemption. For example, migrate a custom `name` key as follows:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# Before
|
|
48
|
+
Markdown/FirstHeading:
|
|
49
|
+
FrontMatterTitle: true
|
|
50
|
+
TitleKey: name
|
|
51
|
+
|
|
52
|
+
# After
|
|
53
|
+
Markdown/FirstHeading:
|
|
54
|
+
FrontMatterTitle: name
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`TitleKey` is obsolete and causes a configuration error with migration guidance. Use `FrontMatterTitle: false` when the front matter should not satisfy this cop.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Markdown/FrontMatterKeys
|
|
2
|
+
|
|
3
|
+
Checks allowed and required top-level keys in a closed leading YAML front-matter block. Key names are exact and case-sensitive. Nested keys and values are not checked. Required keys must be present, but may have empty values.
|
|
4
|
+
|
|
5
|
+
`AllowedKeys: null` permits any key; `[]` permits none. `RequiredKeys` lists keys that must appear and must be included in `AllowedKeys` when that allowlist is configured. A document without front matter is skipped; an empty front-matter block is checked for missing keys.
|
|
6
|
+
|
|
7
|
+
Checks run even when `Markdown/IgnoreFrontMatter` is true. Malformed YAML is skipped so `Markdown/FrontMatterSyntax` can report syntax errors separately. Non-mapping YAML and complex or alias keys are reported. YAML merge keys (`<<`) are treated as literal keys, not expanded; quoted scalar keys are compared by their decoded text. Parsing uses the YAML syntax tree and never instantiates tagged Ruby objects.
|
|
8
|
+
|
|
9
|
+
Report-only: removing unknown metadata or inventing required values could lose data or change behavior.
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
Markdown/FrontMatterKeys:
|
|
15
|
+
Enabled: false
|
|
16
|
+
AllowedKeys: null
|
|
17
|
+
RequiredKeys: []
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
For this configuration:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
Markdown/FrontMatterKeys:
|
|
26
|
+
Enabled: true
|
|
27
|
+
AllowedKeys:
|
|
28
|
+
- title
|
|
29
|
+
- date
|
|
30
|
+
- tags
|
|
31
|
+
RequiredKeys:
|
|
32
|
+
- title
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Bad
|
|
36
|
+
|
|
37
|
+
```markdown
|
|
38
|
+
---
|
|
39
|
+
titel: Getting Started
|
|
40
|
+
date: 2026-11-05
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
# Getting Started
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Good
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
---
|
|
50
|
+
title: Getting Started
|
|
51
|
+
date: 2026-11-05
|
|
52
|
+
tags:
|
|
53
|
+
- ruby
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
# Getting Started
|
|
57
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Markdown/FrontMatterSyntax
|
|
2
|
+
|
|
3
|
+
Reports YAML syntax errors in closed leading Markdown front matter. The cop is enabled by default and report-only. It parses YAML syntax without constructing Ruby objects or validating metadata against a schema; valid scalar values such as dates and custom-tagged nodes are accepted.
|
|
4
|
+
|
|
5
|
+
The cop checks only a closed leading header and reports the YAML parser's line and column in the original Markdown source. It works independently of `Markdown: IgnoreFrontMatter`, which controls how other Markdown cops handle metadata.
|
|
6
|
+
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
Markdown/FrontMatterSyntax:
|
|
11
|
+
Enabled: true
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Example
|
|
15
|
+
|
|
16
|
+
### Bad
|
|
17
|
+
|
|
18
|
+
```markdown
|
|
19
|
+
---
|
|
20
|
+
title: [Unclosed list
|
|
21
|
+
---
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Good
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
---
|
|
28
|
+
title: A valid title
|
|
29
|
+
date: 2026-11-04
|
|
30
|
+
tags: [ruby, markdown]
|
|
31
|
+
---
|
|
32
|
+
```
|
|
@@ -4,24 +4,29 @@ Requires Markdown paragraph hard breaks to use the configured backslash or trail
|
|
|
4
4
|
|
|
5
5
|
On files whose line endings cannot be preserved by RuboCop's source buffer, this cop reports style violations without autocorrecting them.
|
|
6
6
|
|
|
7
|
+
Trailing whitespace cleanup honors this style.
|
|
8
|
+
|
|
7
9
|
## Configuration
|
|
8
10
|
|
|
9
11
|
```yaml
|
|
10
12
|
Markdown/HardBreakStyle:
|
|
11
13
|
Enabled: true
|
|
12
|
-
Style: backslash
|
|
14
|
+
Style: backslash
|
|
15
|
+
SupportedStyles:
|
|
16
|
+
- backslash
|
|
17
|
+
- spaces
|
|
13
18
|
```
|
|
14
19
|
|
|
15
20
|
## Example
|
|
16
21
|
|
|
17
|
-
### Bad:
|
|
22
|
+
### Bad: Trailing Spaces
|
|
18
23
|
|
|
19
24
|
```markdown
|
|
20
25
|
First line.
|
|
21
26
|
Second line.
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
### Good:
|
|
29
|
+
### Good: Backslash
|
|
25
30
|
|
|
26
31
|
```markdown
|
|
27
32
|
First line.\
|
|
@@ -35,14 +40,14 @@ Markdown/HardBreakStyle:
|
|
|
35
40
|
Style: spaces
|
|
36
41
|
```
|
|
37
42
|
|
|
38
|
-
### Bad:
|
|
43
|
+
### Bad: Backslash
|
|
39
44
|
|
|
40
45
|
```markdown
|
|
41
46
|
First line.\
|
|
42
47
|
Second line.
|
|
43
48
|
```
|
|
44
49
|
|
|
45
|
-
### Good:
|
|
50
|
+
### Good: Trailing Spaces
|
|
46
51
|
|
|
47
52
|
```markdown
|
|
48
53
|
First line.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Markdown/HardTabs
|
|
2
2
|
|
|
3
|
-
Reports hard tabs
|
|
3
|
+
Reports hard tabs in Markdown. Front matter and code-block contents are ignored by default. Enable `CodeBlocks` to inspect code contents; `AllowedCodeLanguages` exempts configured fenced languages.
|
|
4
4
|
|
|
5
|
-
Report-only:
|
|
5
|
+
Report-only: tabs may be intentional for alignment, Makefiles, or embedded code. Use [Text/HardTabs](../text/hard_tabs.md) for literal plain-text files.
|
|
6
6
|
|
|
7
7
|
## Configuration
|
|
8
8
|
|
|
9
9
|
```yaml
|
|
10
10
|
Markdown/HardTabs:
|
|
11
11
|
Enabled: true
|
|
12
|
-
CodeBlocks: false #
|
|
12
|
+
CodeBlocks: false # Set true to inspect code-block contents.
|
|
13
13
|
AllowedCodeLanguages: [] # Case-insensitive fenced languages to exempt, such as make.
|
|
14
14
|
```
|
|
15
15
|
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Markdown/HeadingCapitalization
|
|
2
|
+
|
|
3
|
+
Checks ATX and Setext headings, ignoring emphasis delimiters, link syntax, and leading punctuation or numbers. `Style: title_case` (the default) checks each word, keeping internal minor words lowercase. `initial_capital` checks only the first prose letter; remaining words retain their capitalization. Neither style enforces strict sentence case.
|
|
4
|
+
|
|
5
|
+
Lowercase openings inside inline code or quoted terms are reported, including ``## `excalc` usage`` and `## "excalc" usage`; neither their literal contents nor later words are changed. Opaque leading content such as HTML or images is conservatively skipped. `PreserveMixedCase: true` (the default) preserves mixed-case words such as `eBay`, `iOS`, and `macOS` where an initial capital is required, in either style. Set it to `false` to require uppercase initials even for those words. `IgnoredWords` still takes precedence.
|
|
6
|
+
|
|
7
|
+
Use native RuboCop suppression directives for intentional lowercase headings. [Markdown/ProperNames](proper_names.md) independently enforces configured canonical spellings; its configuration does not exempt headings from this cop.
|
|
8
|
+
|
|
9
|
+
`IgnoredWords` skips exact, case-sensitive whole words in either style without exempting the rest of the heading. Mixed-case brands such as `macOS` already pass; use this option for additional spellings such as `npm`.
|
|
10
|
+
|
|
11
|
+
Supports unsafe autocorrection (`rubocop -A`): capitalization may express proper-name intent, and changing a heading can change its generated link anchor. Corrections preserve prefixes, closing markers, and Setext underlines. They are offered only when the rendered heading text maps to one contiguous, unique source span outside protected inline syntax. Split formatting, links, encoded entities, multiline headings, and other ambiguous mappings remain report-only.
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
Markdown/HeadingCapitalization:
|
|
17
|
+
Enabled: false
|
|
18
|
+
Style: title_case
|
|
19
|
+
PreserveMixedCase: true
|
|
20
|
+
IgnoredWords: []
|
|
21
|
+
MinorWords:
|
|
22
|
+
- a
|
|
23
|
+
- an
|
|
24
|
+
- and
|
|
25
|
+
- as
|
|
26
|
+
- at
|
|
27
|
+
- but
|
|
28
|
+
- by
|
|
29
|
+
- for
|
|
30
|
+
- from
|
|
31
|
+
- in
|
|
32
|
+
- nor
|
|
33
|
+
- of
|
|
34
|
+
- 'on'
|
|
35
|
+
- or
|
|
36
|
+
- per
|
|
37
|
+
- the
|
|
38
|
+
- to
|
|
39
|
+
- via
|
|
40
|
+
- vs
|
|
41
|
+
- with
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Initial Capital
|
|
45
|
+
|
|
46
|
+
For this configuration:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
Markdown/HeadingCapitalization:
|
|
50
|
+
Enabled: true
|
|
51
|
+
Style: initial_capital
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Bad
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
## installing the package
|
|
58
|
+
|
|
59
|
+
*getting* started
|
|
60
|
+
-----------------
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Good
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
## Installing the package
|
|
67
|
+
|
|
68
|
+
*Getting* started
|
|
69
|
+
-----------------
|
|
70
|
+
|
|
71
|
+
## `Excalc` usage
|
|
72
|
+
|
|
73
|
+
## eBay integration
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Title Case
|
|
77
|
+
|
|
78
|
+
For this configuration:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
Markdown/HeadingCapitalization:
|
|
82
|
+
Enabled: true
|
|
83
|
+
Style: title_case
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Bad
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
## Getting started with the API
|
|
90
|
+
|
|
91
|
+
## Getting Started With The API
|
|
92
|
+
|
|
93
|
+
## the API and
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Good
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
## Getting Started with the API
|
|
100
|
+
|
|
101
|
+
## The API And
|
|
102
|
+
|
|
103
|
+
## Getting Started with macOS and the API
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The minor words are `a`, `an`, `and`, `as`, `at`, `but`, `by`, `for`, `from`, `in`, `nor`, `of`, `on`, `or`, `per`, `the`, `to`, `via`, `vs`, and `with`. They must be lowercase except as the first or last word. Other words must start uppercase, with mixed-case words also accepted when `PreserveMixedCase` is enabled. Acronyms with uppercase initials and uncased scripts are accepted regardless of that option. Apostrophes stay within words; hyphens separate words, as in `Don't Re-enter the API`.
|
|
107
|
+
|
|
108
|
+
This is a word-based policy, not grammatical analysis or a publishing style manual. Title case skips the entire heading when it contains inline code, HTML, images, or other opaque content rather than guessing word boundaries, except that a lowercase literal opening is reported without correction.
|
|
109
|
+
|
|
110
|
+
### Customize Minor Words
|
|
111
|
+
|
|
112
|
+
`MinorWords` replaces the default list and matches case-insensitively. It affects only `title_case`; first and last words still require capitals. Set it to `[]` to capitalize every word. `IgnoredWords` takes precedence over minor-word rules.
|
|
113
|
+
|
|
114
|
+
For this configuration:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
Markdown/HeadingCapitalization:
|
|
118
|
+
Enabled: true
|
|
119
|
+
Style: title_case
|
|
120
|
+
MinorWords:
|
|
121
|
+
- and
|
|
122
|
+
- the
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### Bad
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
## Getting Started with the API
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Good
|
|
132
|
+
|
|
133
|
+
```markdown
|
|
134
|
+
## Getting Started With the API
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Ignore Specific Words
|
|
138
|
+
|
|
139
|
+
For example, with `PreserveMixedCase: false`, `## Using macOS` is reported in title-case style unless `macOS` is included in `IgnoredWords`.
|
|
140
|
+
|
|
141
|
+
For this configuration:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
Markdown/HeadingCapitalization:
|
|
145
|
+
Enabled: true
|
|
146
|
+
Style: title_case
|
|
147
|
+
IgnoredWords:
|
|
148
|
+
- macOS
|
|
149
|
+
- npm
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Bad
|
|
153
|
+
|
|
154
|
+
```markdown
|
|
155
|
+
## Getting started with macOS
|
|
156
|
+
|
|
157
|
+
## Using npmlike on macOS
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Good
|
|
161
|
+
|
|
162
|
+
```markdown
|
|
163
|
+
## Getting Started with macOS
|
|
164
|
+
|
|
165
|
+
## Using npm on macOS
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Entries are individual words, not phrases or patterns. Ignoring `npm` does not ignore `npmlike` or exempt other lowercase words.
|
|
169
|
+
|
|
170
|
+
### Suppress an Intentional Lowercase Heading
|
|
171
|
+
|
|
172
|
+
```markdown
|
|
173
|
+
<!-- # rubocop:disable Markdown/HeadingCapitalization -->
|
|
174
|
+
## npm usage
|
|
175
|
+
<!-- # rubocop:enable Markdown/HeadingCapitalization -->
|
|
176
|
+
```
|