rubocop-prose 0.1.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.
Files changed (228) hide show
  1. checksums.yaml +7 -0
  2. data/AGENTS.md +13 -0
  3. data/CHANGELOG.md +82 -0
  4. data/CONTRIBUTING.md +77 -0
  5. data/DESIGN.md +51 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +152 -0
  8. data/RELEASING.md +32 -0
  9. data/assets/README.md +3 -0
  10. data/assets/RUBOCOP-LICENSE +20 -0
  11. data/assets/logo.gif +0 -0
  12. data/assets/logo.png +0 -0
  13. data/assets/logo.svg +80 -0
  14. data/assets/rubocop-logo.svg +1 -0
  15. data/config/cops/markdown/atx_heading_space.yml +3 -0
  16. data/config/cops/markdown/atx_heading_spacing.yml +3 -0
  17. data/config/cops/markdown/bare_url.yml +7 -0
  18. data/config/cops/markdown/blockquote_blank_lines.yml +3 -0
  19. data/config/cops/markdown/blockquote_spacing.yml +3 -0
  20. data/config/cops/markdown/closed_heading_space.yml +3 -0
  21. data/config/cops/markdown/closed_heading_spacing.yml +3 -0
  22. data/config/cops/markdown/code_block_style.yml +8 -0
  23. data/config/cops/markdown/code_span_spacing.yml +3 -0
  24. data/config/cops/markdown/compact_lists.yml +3 -0
  25. data/config/cops/markdown/descriptive_link_text.yml +8 -0
  26. data/config/cops/markdown/duplicate_headings.yml +4 -0
  27. data/config/cops/markdown/emphasis_heading.yml +3 -0
  28. data/config/cops/markdown/emphasis_spacing.yml +3 -0
  29. data/config/cops/markdown/emphasis_style.yml +4 -0
  30. data/config/cops/markdown/empty_link.yml +3 -0
  31. data/config/cops/markdown/fence_blank_lines.yml +6 -0
  32. data/config/cops/markdown/fence_language.yml +4 -0
  33. data/config/cops/markdown/fence_style.yml +8 -0
  34. data/config/cops/markdown/first_heading.yml +6 -0
  35. data/config/cops/markdown/front_matter.yml +2 -0
  36. data/config/cops/markdown/hard_break_style.yml +4 -0
  37. data/config/cops/markdown/hard_tabs.yml +5 -0
  38. data/config/cops/markdown/heading_blank_lines.yml +5 -0
  39. data/config/cops/markdown/heading_increment.yml +3 -0
  40. data/config/cops/markdown/heading_indentation.yml +3 -0
  41. data/config/cops/markdown/heading_punctuation.yml +4 -0
  42. data/config/cops/markdown/heading_structure.yml +4 -0
  43. data/config/cops/markdown/heading_style.yml +9 -0
  44. data/config/cops/markdown/image_alt_text.yml +3 -0
  45. data/config/cops/markdown/image_path_separators.yml +3 -0
  46. data/config/cops/markdown/link_fragment.yml +6 -0
  47. data/config/cops/markdown/link_style.yml +10 -0
  48. data/config/cops/markdown/link_text_spacing.yml +3 -0
  49. data/config/cops/markdown/list_blank_lines.yml +3 -0
  50. data/config/cops/markdown/list_continuation_indentation.yml +3 -0
  51. data/config/cops/markdown/list_indentation.yml +3 -0
  52. data/config/cops/markdown/list_marker_spacing.yml +7 -0
  53. data/config/cops/markdown/ordered_list_numbering.yml +7 -0
  54. data/config/cops/markdown/outside_spacing.yml +3 -0
  55. data/config/cops/markdown/proper_names.yml +5 -0
  56. data/config/cops/markdown/raw_html.yml +4 -0
  57. data/config/cops/markdown/reference_definitions.yml +8 -0
  58. data/config/cops/markdown/reversed_link.yml +3 -0
  59. data/config/cops/markdown/shell_prompts.yml +13 -0
  60. data/config/cops/markdown/single_top_level_heading.yml +4 -0
  61. data/config/cops/markdown/strong_style.yml +4 -0
  62. data/config/cops/markdown/structural_line_length.yml +9 -0
  63. data/config/cops/markdown/syntax.yml +3 -0
  64. data/config/cops/markdown/table_blank_lines.yml +3 -0
  65. data/config/cops/markdown/table_columns.yml +3 -0
  66. data/config/cops/markdown/table_pipes.yml +4 -0
  67. data/config/cops/markdown/table_spacing.yml +4 -0
  68. data/config/cops/markdown/thematic_break_blank_lines.yml +5 -0
  69. data/config/cops/markdown/thematic_break_style.yml +4 -0
  70. data/config/cops/markdown/trailing_whitespace.yml +5 -0
  71. data/config/cops/markdown/unclosed_fenced_code_block.yml +3 -0
  72. data/config/cops/markdown/undefined_reference.yml +4 -0
  73. data/config/cops/markdown/unordered_list_indentation.yml +4 -0
  74. data/config/cops/markdown/unordered_list_marker.yml +9 -0
  75. data/config/cops/prose/max_length.yml +5 -0
  76. data/config/cops/prose/multiple_blank_lines.yml +4 -0
  77. data/config/cops/prose/trailing_newline.yml +3 -0
  78. data/config/cops/text/trailing_whitespace.yml +3 -0
  79. data/config/default.yml +16 -0
  80. data/docs/cops/markdown/atx_heading_space.md +26 -0
  81. data/docs/cops/markdown/atx_heading_spacing.md +24 -0
  82. data/docs/cops/markdown/bare_url.md +30 -0
  83. data/docs/cops/markdown/blockquote_blank_lines.md +30 -0
  84. data/docs/cops/markdown/blockquote_spacing.md +30 -0
  85. data/docs/cops/markdown/closed_heading_space.md +26 -0
  86. data/docs/cops/markdown/closed_heading_spacing.md +24 -0
  87. data/docs/cops/markdown/code_block_style.md +37 -0
  88. data/docs/cops/markdown/code_span_spacing.md +26 -0
  89. data/docs/cops/markdown/compact_lists.md +29 -0
  90. data/docs/cops/markdown/descriptive_link_text.md +31 -0
  91. data/docs/cops/markdown/duplicate_headings.md +35 -0
  92. data/docs/cops/markdown/emphasis_heading.md +26 -0
  93. data/docs/cops/markdown/emphasis_spacing.md +24 -0
  94. data/docs/cops/markdown/emphasis_style.md +34 -0
  95. data/docs/cops/markdown/empty_link.md +26 -0
  96. data/docs/cops/markdown/fence_blank_lines.md +43 -0
  97. data/docs/cops/markdown/fence_language.md +31 -0
  98. data/docs/cops/markdown/fence_style.md +38 -0
  99. data/docs/cops/markdown/first_heading.md +31 -0
  100. data/docs/cops/markdown/hard_break_style.md +50 -0
  101. data/docs/cops/markdown/hard_tabs.md +30 -0
  102. data/docs/cops/markdown/heading_blank_lines.md +36 -0
  103. data/docs/cops/markdown/heading_increment.md +30 -0
  104. data/docs/cops/markdown/heading_indentation.md +26 -0
  105. data/docs/cops/markdown/heading_punctuation.md +27 -0
  106. data/docs/cops/markdown/heading_structure.md +41 -0
  107. data/docs/cops/markdown/heading_style.md +36 -0
  108. data/docs/cops/markdown/image_alt_text.md +26 -0
  109. data/docs/cops/markdown/image_path_separators.md +32 -0
  110. data/docs/cops/markdown/link_fragment.md +35 -0
  111. data/docs/cops/markdown/link_style.md +49 -0
  112. data/docs/cops/markdown/link_text_spacing.md +26 -0
  113. data/docs/cops/markdown/list_blank_lines.md +31 -0
  114. data/docs/cops/markdown/list_continuation_indentation.md +28 -0
  115. data/docs/cops/markdown/list_indentation.md +28 -0
  116. data/docs/cops/markdown/list_marker_spacing.md +32 -0
  117. data/docs/cops/markdown/ordered_list_numbering.md +29 -0
  118. data/docs/cops/markdown/outside_spacing.md +26 -0
  119. data/docs/cops/markdown/proper_names.md +39 -0
  120. data/docs/cops/markdown/raw_html.md +27 -0
  121. data/docs/cops/markdown/reference_definitions.md +36 -0
  122. data/docs/cops/markdown/reversed_link.md +26 -0
  123. data/docs/cops/markdown/shell_prompts.md +57 -0
  124. data/docs/cops/markdown/single_top_level_heading.md +31 -0
  125. data/docs/cops/markdown/strong_style.md +34 -0
  126. data/docs/cops/markdown/structural_line_length.md +40 -0
  127. data/docs/cops/markdown/syntax.md +28 -0
  128. data/docs/cops/markdown/table_blank_lines.md +34 -0
  129. data/docs/cops/markdown/table_columns.md +30 -0
  130. data/docs/cops/markdown/table_pipes.md +38 -0
  131. data/docs/cops/markdown/table_spacing.md +38 -0
  132. data/docs/cops/markdown/thematic_break_blank_lines.md +31 -0
  133. data/docs/cops/markdown/thematic_break_style.md +48 -0
  134. data/docs/cops/markdown/trailing_whitespace.md +30 -0
  135. data/docs/cops/markdown/unclosed_fenced_code_block.md +29 -0
  136. data/docs/cops/markdown/undefined_reference.md +29 -0
  137. data/docs/cops/markdown/unordered_list_indentation.md +45 -0
  138. data/docs/cops/markdown/unordered_list_marker.md +36 -0
  139. data/docs/cops/prose/max_length.md +33 -0
  140. data/docs/cops/prose/multiple_blank_lines.md +50 -0
  141. data/docs/cops/prose/trailing_newline.md +26 -0
  142. data/docs/cops/text/trailing_whitespace.md +26 -0
  143. data/docs/settings/files.md +33 -0
  144. data/docs/settings/front_matter.md +12 -0
  145. data/lib/rubocop/cop/markdown/atx_heading_space.rb +22 -0
  146. data/lib/rubocop/cop/markdown/atx_heading_spacing.rb +27 -0
  147. data/lib/rubocop/cop/markdown/bare_url.rb +22 -0
  148. data/lib/rubocop/cop/markdown/base.rb +17 -0
  149. data/lib/rubocop/cop/markdown/blockquote_blank_lines.rb +49 -0
  150. data/lib/rubocop/cop/markdown/blockquote_spacing.rb +76 -0
  151. data/lib/rubocop/cop/markdown/closed_heading_space.rb +26 -0
  152. data/lib/rubocop/cop/markdown/closed_heading_spacing.rb +27 -0
  153. data/lib/rubocop/cop/markdown/code_block_style.rb +80 -0
  154. data/lib/rubocop/cop/markdown/code_span_spacing.rb +51 -0
  155. data/lib/rubocop/cop/markdown/compact_lists.rb +43 -0
  156. data/lib/rubocop/cop/markdown/descriptive_link_text.rb +27 -0
  157. data/lib/rubocop/cop/markdown/duplicate_headings.rb +28 -0
  158. data/lib/rubocop/cop/markdown/emphasis_heading.rb +18 -0
  159. data/lib/rubocop/cop/markdown/emphasis_spacing.rb +30 -0
  160. data/lib/rubocop/cop/markdown/emphasis_style.rb +34 -0
  161. data/lib/rubocop/cop/markdown/empty_link.rb +25 -0
  162. data/lib/rubocop/cop/markdown/fence_blank_lines.rb +72 -0
  163. data/lib/rubocop/cop/markdown/fence_language.rb +32 -0
  164. data/lib/rubocop/cop/markdown/fence_style.rb +39 -0
  165. data/lib/rubocop/cop/markdown/first_heading.rb +44 -0
  166. data/lib/rubocop/cop/markdown/hard_break_style.rb +65 -0
  167. data/lib/rubocop/cop/markdown/hard_tabs.rb +32 -0
  168. data/lib/rubocop/cop/markdown/heading_blank_lines.rb +37 -0
  169. data/lib/rubocop/cop/markdown/heading_increment.rb +23 -0
  170. data/lib/rubocop/cop/markdown/heading_indentation.rb +37 -0
  171. data/lib/rubocop/cop/markdown/heading_punctuation.rb +23 -0
  172. data/lib/rubocop/cop/markdown/heading_structure.rb +33 -0
  173. data/lib/rubocop/cop/markdown/heading_style.rb +24 -0
  174. data/lib/rubocop/cop/markdown/image_alt_text.rb +24 -0
  175. data/lib/rubocop/cop/markdown/image_path_separators.rb +32 -0
  176. data/lib/rubocop/cop/markdown/link_fragment.rb +36 -0
  177. data/lib/rubocop/cop/markdown/link_style.rb +29 -0
  178. data/lib/rubocop/cop/markdown/link_text_spacing.rb +34 -0
  179. data/lib/rubocop/cop/markdown/list_blank_lines.rb +38 -0
  180. data/lib/rubocop/cop/markdown/list_continuation_indentation.rb +59 -0
  181. data/lib/rubocop/cop/markdown/list_indentation.rb +28 -0
  182. data/lib/rubocop/cop/markdown/list_marker_spacing.rb +44 -0
  183. data/lib/rubocop/cop/markdown/ordered_list_numbering.rb +35 -0
  184. data/lib/rubocop/cop/markdown/outside_spacing.rb +88 -0
  185. data/lib/rubocop/cop/markdown/proper_names.rb +51 -0
  186. data/lib/rubocop/cop/markdown/raw_html.rb +60 -0
  187. data/lib/rubocop/cop/markdown/reference_definitions.rb +37 -0
  188. data/lib/rubocop/cop/markdown/reversed_link.rb +20 -0
  189. data/lib/rubocop/cop/markdown/shell_prompts.rb +72 -0
  190. data/lib/rubocop/cop/markdown/single_top_level_heading.rb +19 -0
  191. data/lib/rubocop/cop/markdown/strong_style.rb +33 -0
  192. data/lib/rubocop/cop/markdown/structural_line_length.rb +51 -0
  193. data/lib/rubocop/cop/markdown/syntax.rb +33 -0
  194. data/lib/rubocop/cop/markdown/table_blank_lines.rb +46 -0
  195. data/lib/rubocop/cop/markdown/table_columns.rb +23 -0
  196. data/lib/rubocop/cop/markdown/table_pipes.rb +45 -0
  197. data/lib/rubocop/cop/markdown/table_spacing.rb +62 -0
  198. data/lib/rubocop/cop/markdown/thematic_break_blank_lines.rb +115 -0
  199. data/lib/rubocop/cop/markdown/thematic_break_style.rb +74 -0
  200. data/lib/rubocop/cop/markdown/trailing_whitespace.rb +55 -0
  201. data/lib/rubocop/cop/markdown/unclosed_fenced_code_block.rb +82 -0
  202. data/lib/rubocop/cop/markdown/undefined_reference.rb +25 -0
  203. data/lib/rubocop/cop/markdown/unordered_list_indentation.rb +37 -0
  204. data/lib/rubocop/cop/markdown/unordered_list_marker.rb +45 -0
  205. data/lib/rubocop/cop/prose/base.rb +55 -0
  206. data/lib/rubocop/cop/prose/max_length.rb +93 -0
  207. data/lib/rubocop/cop/prose/multiple_blank_lines.rb +96 -0
  208. data/lib/rubocop/cop/prose/trailing_newline.rb +26 -0
  209. data/lib/rubocop/cop/text/base.rb +17 -0
  210. data/lib/rubocop/cop/text/trailing_whitespace.rb +25 -0
  211. data/lib/rubocop/prose/code_rules.rb +79 -0
  212. data/lib/rubocop/prose/document.rb +62 -0
  213. data/lib/rubocop/prose/file_types.rb +56 -0
  214. data/lib/rubocop/prose/heading_rules.rb +54 -0
  215. data/lib/rubocop/prose/inline_rules.rb +213 -0
  216. data/lib/rubocop/prose/link_rules.rb +630 -0
  217. data/lib/rubocop/prose/list_rules.rb +65 -0
  218. data/lib/rubocop/prose/markdown_document.rb +167 -0
  219. data/lib/rubocop/prose/parser.rb +80 -0
  220. data/lib/rubocop/prose/plugin.rb +30 -0
  221. data/lib/rubocop/prose/runner.rb +63 -0
  222. data/lib/rubocop/prose/source.rb +82 -0
  223. data/lib/rubocop/prose/structural_blank_lines.rb +90 -0
  224. data/lib/rubocop/prose/table_rules.rb +71 -0
  225. data/lib/rubocop/prose/text_document.rb +54 -0
  226. data/lib/rubocop/prose/version.rb +7 -0
  227. data/lib/rubocop-prose.rb +30 -0
  228. metadata +335 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df5161ee5df2bb5e5b642b3baefb5f95ec038cea286de98c177c317af2ed8115
4
+ data.tar.gz: 2dde6ed1646ce551227eed6465856616056972e520ccc2830d65c2e035b7d74f
5
+ SHA512:
6
+ metadata.gz: dcd9ff6b678a0ddcb11c07ec164a5f047f333bd656afe88f0f36eb80fac561c83ef5014de712ee08f212ea2a3f3cb1a291ee76ec70b8078462296538ba119b57
7
+ data.tar.gz: 52279ff43345beeda93aebd8b718c66a5dc2dea1fcc801c9aab57a4ba467f0ae1d52d4ef1d180d128fc5c8cca9d5153e694980a05984f91583ea7080b9b73fdd
data/AGENTS.md ADDED
@@ -0,0 +1,13 @@
1
+ # Contributor instructions
2
+
3
+ Read [CONTRIBUTING.md](CONTRIBUTING.md) for setup, tests, and pull-request conventions. Read [DESIGN.md](DESIGN.md) before changing parsing, source mapping, or correction behavior.
4
+
5
+ Keep user guidance in the README and cop guides, contributor workflow in CONTRIBUTING, architecture and rationale in DESIGN, and this file focused on high-value agent guidance. Link to the authoritative documentation instead of duplicating it.
6
+
7
+ Preserve original source buffers and character-based locations, Markdown container prefixes and hard breaks, and atomic inline syntax. Plain text must remain literal; format-specific cops must not inspect the other format. Withhold corrections when a safe rewrite cannot be established.
8
+
9
+ Keep common cleanup enabled by default and project-specific, editorial, or renderer-dependent policies opt-in. Do not add an external preprocessor dependency. Preserve functional dependency loading and compatibility settings.
10
+
11
+ When adding a cop, follow the checklist in [CONTRIBUTING.md](CONTRIBUTING.md#adding-a-cop); document its user-visible behavior and meaningful limits without repeating shared exclusions.
12
+
13
+ Do not edit historical changelog entries or add one for documentation, tooling, refactoring, or unreleased functionality. Preserve the vendored helmet SVG and its license; follow CONTRIBUTING for artwork changes.
data/CHANGELOG.md ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
+
5
+ ## 0.1.0 (2026/11/03)
6
+
7
+ - [#120](https://github.com/dblock/rubocop-prose/pull/120): Add a default-enabled Markdown hard-break style policy with backslash and trailing-space syntax options - [@dblock](https://github.com/dblock).
8
+ - [#110](https://github.com/dblock/rubocop-prose/pull/110): Add enabled-by-default `Markdown/ListContinuationIndentation` to report lazy list continuation text outside its item's content column - [@dblock](https://github.com/dblock).
9
+ - [#114](https://github.com/dblock/rubocop-prose/pull/114): Add the default-enabled `Markdown/UnclosedFencedCodeBlock` report for EOF-terminated fenced code blocks - [@dblock](https://github.com/dblock).
10
+ - [#108](https://github.com/dblock/rubocop-prose/pull/108): Allow multiple explicit thematic-break spellings with report-only handling for ambiguous corrections - [@dblock](https://github.com/dblock).
11
+ - [#107](https://github.com/dblock/rubocop-prose/pull/107): Apply the configured blank-line limit inside Markdown blockquotes while preserving quote markers and paragraph separation - [@dblock](https://github.com/dblock).
12
+ - [#109](https://github.com/dblock/rubocop-prose/pull/109): Add default-enabled compact-list spacing checks with safe correction for simple items - [@dblock](https://github.com/dblock).
13
+ - [#112](https://github.com/dblock/rubocop-prose/pull/112): Detect and safely correct missing separators after blockquote markers - [@dblock](https://github.com/dblock).
14
+ - [#111](https://github.com/dblock/rubocop-prose/pull/111): Add default-enabled `Markdown/OutsideSpacing` for inline formatting adjacent to prose - [@dblock](https://github.com/dblock).
15
+ - [#113](https://github.com/dblock/rubocop-prose/pull/113): Add `Markdown/ThematicBreakBlankLines` for default-enabled, container-aware spacing around parsed thematic breaks - [@dblock](https://github.com/dblock).
16
+ - [#115](https://github.com/dblock/rubocop-prose/pull/115): Add a default-enabled check for backslash separators in local Markdown image paths - [@dblock](https://github.com/dblock).
17
+ - [#106](https://github.com/dblock/rubocop-prose/pull/106): Enable dollar and percent shell-prompt cleanup with configurable markers and report-only handling of ambiguous shell comments - [@dblock](https://github.com/dblock).
18
+ - [#75](https://github.com/dblock/rubocop-prose/pull/75): Configure independent blank-line counts above and below fenced code blocks - [@dblock](https://github.com/dblock).
19
+ - [#72](https://github.com/dblock/rubocop-prose/pull/72): Allow identical reference definitions while retaining conflict and unused checks - [@dblock](https://github.com/dblock).
20
+ - [#69](https://github.com/dblock/rubocop-prose/pull/69): Add reproducible prose benchmarks and share Markdown document analysis across cops - [@dblock](https://github.com/dblock).
21
+ - [#66](https://github.com/dblock/rubocop-prose/pull/66): Enable common-sense Markdown and text checks and unwrapped paragraphs by default, with conservative heading, tab, and reference policies - [@dblock](https://github.com/dblock).
22
+ - [#65](https://github.com/dblock/rubocop-prose/pull/65): Configure Markdown and text Include patterns with per-file discovery, source dispatch, and a README settings catalog - [@dblock](https://github.com/dblock).
23
+ - [#63](https://github.com/dblock/rubocop-prose/pull/63): Add plain-text support with shared Prose, Markdown, and Text departments, format-specific policies, and grouped integration tests - [@dblock](https://github.com/dblock).
24
+ - [#60](https://github.com/dblock/rubocop-prose/pull/60): Add a RuboCop-inspired logo with a parchment scroll, editable SVG artwork, and a README image - [@dblock](https://github.com/dblock).
25
+ - [#58](https://github.com/dblock/rubocop-prose/pull/58): Add `Prose/TableSpacing` for table cell spacing - [@dblock](https://github.com/dblock).
26
+ - [#57](https://github.com/dblock/rubocop-prose/pull/57): Add `Prose/TableBlankLines` for blank lines around tables - [@dblock](https://github.com/dblock).
27
+ - [#56](https://github.com/dblock/rubocop-prose/pull/56): Add `Prose/TableColumns` for consistent table column counts - [@dblock](https://github.com/dblock).
28
+ - [#55](https://github.com/dblock/rubocop-prose/pull/55): Add `Prose/TablePipes` for table pipe style - [@dblock](https://github.com/dblock).
29
+ - [#54](https://github.com/dblock/rubocop-prose/pull/54): Add `Prose/StrongStyle` for consistent strong-emphasis delimiters - [@dblock](https://github.com/dblock).
30
+ - [#53](https://github.com/dblock/rubocop-prose/pull/53): Add `Prose/EmphasisStyle` for consistent emphasis delimiters - [@dblock](https://github.com/dblock).
31
+ - [#52](https://github.com/dblock/rubocop-prose/pull/52): Add `Prose/ProperNames` for configured proper-name capitalization - [@dblock](https://github.com/dblock).
32
+ - [#51](https://github.com/dblock/rubocop-prose/pull/51): Add `Prose/CodeSpanSpacing` for spacing inside inline code spans - [@dblock](https://github.com/dblock).
33
+ - [#50](https://github.com/dblock/rubocop-prose/pull/50): Add `Prose/EmphasisSpacing` for spacing inside emphasis markers - [@dblock](https://github.com/dblock).
34
+ - [#49](https://github.com/dblock/rubocop-prose/pull/49): Add `Prose/ThematicBreakStyle` for consistent thematic breaks - [@dblock](https://github.com/dblock).
35
+ - [#48](https://github.com/dblock/rubocop-prose/pull/48): Add `Prose/RawHtml` for configurable inline HTML restrictions - [@dblock](https://github.com/dblock).
36
+ - [#47](https://github.com/dblock/rubocop-prose/pull/47): Add `Prose/DescriptiveLinkText` for descriptive link labels - [@dblock](https://github.com/dblock).
37
+ - [#46](https://github.com/dblock/rubocop-prose/pull/46): Add `Prose/LinkStyle` for allowed link and image styles - [@dblock](https://github.com/dblock).
38
+ - [#45](https://github.com/dblock/rubocop-prose/pull/45): Add `Prose/ReferenceDefinitions` for duplicate and unused reference definitions - [@dblock](https://github.com/dblock).
39
+ - [#44](https://github.com/dblock/rubocop-prose/pull/44): Add `Prose/UndefinedReference` for undefined link and image references - [@dblock](https://github.com/dblock).
40
+ - [#43](https://github.com/dblock/rubocop-prose/pull/43): Add `Prose/LinkFragment` for local heading-fragment targets - [@dblock](https://github.com/dblock).
41
+ - [#42](https://github.com/dblock/rubocop-prose/pull/42): Add `Prose/ImageAltText` for missing image alternative text - [@dblock](https://github.com/dblock).
42
+ - [#41](https://github.com/dblock/rubocop-prose/pull/41): Add `Prose/EmptyLink` for empty link destinations - [@dblock](https://github.com/dblock).
43
+ - [#40](https://github.com/dblock/rubocop-prose/pull/40): Add `Prose/LinkTextSpacing` for spacing inside link text - [@dblock](https://github.com/dblock).
44
+ - [#39](https://github.com/dblock/rubocop-prose/pull/39): Add `Prose/BareUrl` for bare URLs outside code and other protected spans - [@dblock](https://github.com/dblock).
45
+ - [#38](https://github.com/dblock/rubocop-prose/pull/38): Add `Prose/ReversedLink` for reversed link syntax - [@dblock](https://github.com/dblock).
46
+ - [#37](https://github.com/dblock/rubocop-prose/pull/37): Add `Prose/FenceStyle` for consistent code-fence markers - [@dblock](https://github.com/dblock).
47
+ - [#36](https://github.com/dblock/rubocop-prose/pull/36): Add `Prose/CodeBlockStyle` for fenced or indented code-block style - [@dblock](https://github.com/dblock).
48
+ - [#35](https://github.com/dblock/rubocop-prose/pull/35): Add `Prose/FenceLanguage` for code-fence language identifiers - [@dblock](https://github.com/dblock).
49
+ - [#34](https://github.com/dblock/rubocop-prose/pull/34): Add `Prose/FenceBlankLines` for blank lines around fenced code blocks - [@dblock](https://github.com/dblock).
50
+ - [#33](https://github.com/dblock/rubocop-prose/pull/33): Add `Prose/ShellPrompts` for unnecessary shell prompts in command examples - [@dblock](https://github.com/dblock).
51
+ - [#32](https://github.com/dblock/rubocop-prose/pull/32): Add `Prose/ListBlankLines` for blank lines around lists - [@dblock](https://github.com/dblock).
52
+ - [#31](https://github.com/dblock/rubocop-prose/pull/31): Add `Prose/ListMarkerSpacing` for spacing after list markers - [@dblock](https://github.com/dblock).
53
+ - [#30](https://github.com/dblock/rubocop-prose/pull/30): Add `Prose/OrderedListNumbering` for ordered-list numbering styles - [@dblock](https://github.com/dblock).
54
+ - [#29](https://github.com/dblock/rubocop-prose/pull/29): Add `Prose/BlockquoteBlankLines` for blank lines within blockquotes - [@dblock](https://github.com/dblock).
55
+ - [#28](https://github.com/dblock/rubocop-prose/pull/28): Add `Prose/BlockquoteSpacing` for spacing after blockquote markers - [@dblock](https://github.com/dblock).
56
+ - [#27](https://github.com/dblock/rubocop-prose/pull/27): Add `Prose/UnorderedListIndentation` for nested unordered-list indentation - [@dblock](https://github.com/dblock).
57
+ - [#26](https://github.com/dblock/rubocop-prose/pull/26): Add `Prose/ListIndentation` for consistent list-item indentation - [@dblock](https://github.com/dblock).
58
+ - [#25](https://github.com/dblock/rubocop-prose/pull/25): Add `Prose/UnorderedListMarker` for unordered-list marker styles - [@dblock](https://github.com/dblock).
59
+ - [#24](https://github.com/dblock/rubocop-prose/pull/24): Add `Prose/HeadingStructure` for a configured heading outline - [@dblock](https://github.com/dblock).
60
+ - [#23](https://github.com/dblock/rubocop-prose/pull/23): Add `Prose/FirstHeading` for the initial heading level and optional front-matter title exemption - [@dblock](https://github.com/dblock).
61
+ - [#22](https://github.com/dblock/rubocop-prose/pull/22): Add `Prose/EmphasisHeading` for emphasis-only paragraphs used as headings - [@dblock](https://github.com/dblock).
62
+ - [#21](https://github.com/dblock/rubocop-prose/pull/21): Add `Prose/HeadingPunctuation` for trailing heading punctuation - [@dblock](https://github.com/dblock).
63
+ - [#20](https://github.com/dblock/rubocop-prose/pull/20): Add `Prose/SingleTopLevelHeading` for multiple top-level headings - [@dblock](https://github.com/dblock).
64
+ - [#19](https://github.com/dblock/rubocop-prose/pull/19): Add `Prose/DuplicateHeadings` for duplicate headings in document or sibling scope - [@dblock](https://github.com/dblock).
65
+ - [#18](https://github.com/dblock/rubocop-prose/pull/18): Add `Prose/HeadingIndentation` for leading heading indentation - [@dblock](https://github.com/dblock).
66
+ - [#17](https://github.com/dblock/rubocop-prose/pull/17): Add `Prose/HeadingBlankLines` for blank lines around headings - [@dblock](https://github.com/dblock).
67
+ - [#16](https://github.com/dblock/rubocop-prose/pull/16): Add `Prose/ClosedHeadingSpacing` for excess spacing before closing heading hashes - [@dblock](https://github.com/dblock).
68
+ - [#15](https://github.com/dblock/rubocop-prose/pull/15): Add `Prose/ClosedHeadingSpace` for missing spacing before closing heading hashes - [@dblock](https://github.com/dblock).
69
+ - [#14](https://github.com/dblock/rubocop-prose/pull/14): Add `Prose/AtxHeadingSpacing` for excess spacing after opening heading hashes - [@dblock](https://github.com/dblock).
70
+ - [#13](https://github.com/dblock/rubocop-prose/pull/13): Add `Prose/AtxHeadingSpace` for missing spacing after opening heading hashes - [@dblock](https://github.com/dblock).
71
+ - [#12](https://github.com/dblock/rubocop-prose/pull/12): Add `Prose/HeadingStyle` for consistent ATX, closed ATX, or Setext headings - [@dblock](https://github.com/dblock).
72
+ - [#11](https://github.com/dblock/rubocop-prose/pull/11): Add `Prose/HeadingIncrement` for skipped heading levels - [@dblock](https://github.com/dblock).
73
+ - [#10](https://github.com/dblock/rubocop-prose/pull/10): Add `Prose/TrailingNewline` to normalize the final document newline - [@dblock](https://github.com/dblock).
74
+ - [#9](https://github.com/dblock/rubocop-prose/pull/9): Add `Prose/MultipleBlankLines` to limit consecutive blank lines without merging paragraphs - [@dblock](https://github.com/dblock).
75
+ - [#8](https://github.com/dblock/rubocop-prose/pull/8): Add `Prose/HardTabs` with code-language exceptions - [@dblock](https://github.com/dblock).
76
+ - [#7](https://github.com/dblock/rubocop-prose/pull/7): Add `Prose/TrailingWhitespace`, preserving Markdown hard breaks - [@dblock](https://github.com/dblock).
77
+ - [#6](https://github.com/dblock/rubocop-prose/pull/6): Extend line-length policies to headings, code blocks, and tables - [@dblock](https://github.com/dblock).
78
+ - [#5](https://github.com/dblock/rubocop-prose/pull/5): Add shared configurable front-matter exclusion - [@dblock](https://github.com/dblock).
79
+ - [#4](https://github.com/dblock/rubocop-prose/pull/4): Add `Prose/Syntax` to report parser diagnostics without duplicate reference reports - [@dblock](https://github.com/dblock).
80
+ - [#3](https://github.com/dblock/rubocop-prose/pull/3): Add single-line paragraph unwrapping and CLI integration - [@dblock](https://github.com/dblock).
81
+ - [#2](https://github.com/dblock/rubocop-prose/pull/2): Add `Prose/MaxLength` for safe Markdown paragraph wrapping - [@dblock](https://github.com/dblock).
82
+ - [#1](https://github.com/dblock/rubocop-prose/pull/1): Add the parser-backed RuboCop plugin foundation with original-source ranges and opt-in document cops - [@dblock](https://github.com/dblock).
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,77 @@
1
+ # Contributing
2
+
3
+ ## Setup and validation
4
+
5
+ Use Ruby 3.2 or newer. Supported RuboCop versions are 1.72.1 and newer within 1.x.
6
+
7
+ ```sh
8
+ bundle install
9
+ bundle exec rake
10
+ bundle exec rake build
11
+ ```
12
+
13
+ The default Rake task runs RuboCop and the full test suite. For focused changes, use `bundle exec rspec spec/path_to_spec.rb` and `bundle exec rubocop`. Run unit or standalone integration tests separately with `bundle exec rake spec:unit` or `bundle exec rake spec:integration`. To install the minimum supported RuboCop, use `RUBOCOP_VERSION=1.72.1 bundle install`.
14
+
15
+ CI covers Ruby 3.2 and 4.0, gem packaging, and optional Markdown-preprocessor interoperability. See the [workflows](.github/workflows) for suite selection and dependency versions.
16
+
17
+ The lint configuration loads this checkout's plugin alongside rubocop-rspec and rubocop-rake; intentionally invalid fixtures are excluded.
18
+
19
+ ### Benchmarks
20
+
21
+ Run `bundle exec rake benchmark`; set `ITERATIONS` and `SECTIONS` to override sample counts and corpus sizes, for example `ITERATIONS=5 SECTIONS=10,50,100 bundle exec rake benchmark`.
22
+
23
+ The benchmark compares document analysis, cop investigation, and in-memory autocorrection on Markdown and text corpora. Each operation constructs a fresh document; compare results only across revisions using the same Ruby, RuboCop, and corpus settings. Timings are machine-dependent, not CI thresholds.
24
+
25
+ ## Tests
26
+
27
+ Keep focused cop tests in `spec/<name>_spec.rb`. Cover offenses, exclusions, Unicode source locations, safe corrections, and ambiguous rewrites that must remain report-only. Document adapters and file selection have dedicated specs; format-specific cops must not investigate the other format, even when explicitly selected.
28
+
29
+ Exercise the real CLI when changing plugin loading, stdin, suppression directives, or cross-cop corrections. Test both CLI-option and YAML plugin loading. Interoperability changes also need both preprocessor loading orders, simultaneous prose/Ruby corrections, repeated runs, and stdin.
30
+
31
+ ### Integration fixtures
32
+
33
+ Scenarios live under `spec/fixtures/{prose,markdown,text,markdown_interoperability}/`, with specs in `spec/integration/` and `spec/interoperability/`. Each contains an `input` document, a `case.yml` declaring `offenses` and `remaining_offenses` counts (empty maps for clean results), and an `expected` document when correction changes the input.
34
+
35
+ Content fixtures call `RuboCop::CLI` in-process with fresh configuration state, checking explicit files, discovery, corrections, repeated runs, and stdin with both plugin-loading configurations. Fixtures with explicit `Enabled: true` cop entries run with `--only`; others exercise configured defaults. Mark whitespace-sensitive fixtures using the existing Git attributes.
36
+
37
+ Fresh-process smoke tests in `spec/integration/cli_spec.rb` check YAML and CLI-option plugin boot for Markdown and text, standard and custom-extension discovery, stdin without disk mutation, and stable corrections. Interoperability keeps a combined Ruby/Markdown scenario across both loading orders and plugin-loading mechanisms; edge cases check reporting, correction, and stability under both loading orders using YAML plugin loading.
38
+
39
+ Mixed default-cop scenarios in `spec/fixtures/markdown_stability/` check content and document structure after every correction, convergence without cycles, and byte-identical output after stabilization.
40
+
41
+ For optional interoperability, set `RUBOCOP_MD_PATH` to a checkout supporting the [original-buffer mapping API](DESIGN.md#preprocessor-interoperability) and run `bundle exec rake spec:interoperability`. Without that variable, the suite is skipped. Its separate CI workflow runs only on Ruby 4.0; update the rubocop-md ref when the required API is released.
42
+
43
+ ## Adding a cop
44
+
45
+ Add implementations under `lib/rubocop/cop/prose`, `lib/rubocop/cop/markdown`, or `lib/rubocop/cop/text`, inheriting from the corresponding department `Base`. Add a per-cop YAML file under `config/cops/<department>/` with an explicit `Enabled` value, supported options, correction policy, and applicable file patterns. The loader discovers implementations and merges their configuration files.
46
+
47
+ Add focused specs, a guide under `docs/cops/<department>/` with complete default configuration and meaningful bad/good examples, and a linked one-line entry in the [README cops catalog](README.md#cops). Introduce example-specific settings with “For this configuration:” followed by a YAML block. Keep user-visible behavior and meaningful limits in the guide, implementation rationale in [DESIGN.md](DESIGN.md), and shared exclusions in the README. Use the native cop name; do not add numeric aliases or comparisons with other plugins.
48
+
49
+ Validate defaults, packaging, and the affected tests. Enable broadly applicable cleanup by default; keep project-specific, editorial, and renderer-dependent policies opt-in. Preserve functional dependency loading and compatibility CI settings.
50
+
51
+ ## Pull requests
52
+
53
+ See [RELEASING.md](RELEASING.md) for the maintainer release procedure.
54
+
55
+ Keep each pull request focused, with one coherent commit, and use squash merges. Include behavior and configuration documentation. Preserve unrelated worktree changes.
56
+
57
+ Add a linked unreleased changelog entry only for a notable user-facing change, using the actual pull-request number. Do not add entries for documentation, tooling, refactoring, or unreleased functionality; update an existing feature entry when appropriate.
58
+
59
+ ```markdown
60
+ - [#123](https://github.com/dblock/rubocop-prose/pull/123): Describe the change - [@dblock](https://github.com/dblock).
61
+ ```
62
+
63
+ Keep each Markdown paragraph on one source line. Do not duplicate developer instructions in the README, cop guides, or asset notes.
64
+
65
+ ## Artwork
66
+
67
+ Edit `assets/logo.svg`, leaving the upstream `assets/rubocop-logo.svg` unchanged and retaining the notice in `assets/RUBOCOP-LICENSE`. The composition and attribution are documented in [DESIGN.md](DESIGN.md#artwork).
68
+
69
+ Inspect the animation and reduced-motion rendering in a browser. Keep the PNG a static, fully unrolled fallback; the README uses the GIF because GitHub does not reliably preserve SVG animation. When changing the animation, regenerate the GIF from a full six-second SVG cycle at 15 frames per second, with the fully unrolled first frame and infinite looping.
70
+
71
+ With `rsvg-convert` installed, regenerate the 512px PNG from the repository root:
72
+
73
+ ```sh
74
+ rsvg-convert assets/logo.svg -o assets/logo.png
75
+ ```
76
+
77
+ Check the full-size PNG and 160px README rendering for clipping, legibility, scroll orientation, and separation from the helmet. Keep the opaque white background and package all artwork sources, rendered images, and the upstream notice together.
data/DESIGN.md ADDED
@@ -0,0 +1,51 @@
1
+ # Design
2
+
3
+ ## Scope and file selection
4
+
5
+ The plugin checks Markdown and plain-text prose without evaluating Ruby snippets. `Prose/*` policies apply to both formats; `Markdown/*` and `Text/*` are format-specific. Common cleanup is enabled by default, while project-specific, editorial, and renderer-dependent policies remain opt-in. User-visible behavior and defaults are in [the README cops catalog](README.md#cops) and the cop guides.
6
+
7
+ `Markdown/Include` and `Text/Include` are resolved by `FileTypes` from each file's effective RuboCop configuration. The same resolver drives discovery and applicability; overlapping patterns are an error. Format selection is configuration-local, not a process-wide registry or a separate set of hard-coded extension lists.
8
+
9
+ The plugin loads document support and abstract cop bases before concrete cops, then merges shared and per-cop defaults. The runner supplies a file's configuration before source construction when its selected format differs from RuboCop's default classification. This keeps nested configuration, explicit files, stdin, and autocorrection on the same dispatch path.
10
+
11
+ ## Documents and source preservation
12
+
13
+ `Document` retains the untouched input buffer and exposes character-based ranges. `MarkdownDocument` parses Markdown and provides its structure; `TextDocument` groups nonblank lines into paragraphs without interpreting headings, links, fences, HTML, or metadata. Text indentation may indicate preformatted content, so indented paragraphs can be reported but are not automatically reflowed.
14
+
15
+ Markdown parsing combines an AST with source-aware scanners for constructs that may be malformed or omitted from the tree. Scanners must exclude code, escaped syntax, and ignored metadata. Parser byte offsets are converted to character positions before they are mapped to the original source, preserving Unicode locations.
16
+
17
+ Front matter is recognized only as a closed leading header. When ignored, it is masked only in the parser input, preserving line endings and source positions; the original buffer is not rewritten. `Markdown/IgnoreFrontMatter` is resolved while constructing each Markdown document, including documents shared by `Prose/*` cops. Hidden RuboCop directives are recognized only in Markdown outside code and ignored metadata; directive-shaped text remains literal in plain text.
18
+
19
+ Standalone Markdown and all plain text initialize Ruby parsing with empty input and keep the original document in a separate buffer, preventing Ruby cops from interpreting prose. The cop bases enforce format applicability before accessing format-specific APIs. Documents are cached on the processed source by configuration identity, so cops can share analysis without mixing configuration-dependent results.
20
+
21
+ Each Markdown document shares positioned emphasis and strong ranges across style and spacing cops, including table-row source mapping. Both types are collected in one parse; style policies remain cop-local, and corrected sources receive fresh documents.
22
+
23
+ ## Preprocessor interoperability
24
+
25
+ An optional Markdown preprocessor can expose `processed_source.markdown_document` with an untouched `buffer` and `original_range` / `processed_range` mapping methods. The plugin analyzes that original buffer and translates offense and correction ranges at the RuboCop boundary, preserving the preprocessor's Ruby buffer so both kinds of corrections can coexist. This API is optional; standalone Markdown and text linting do not require a preprocessor.
26
+
27
+ Plain text never consults the preprocessor API. A preprocessor without the original-buffer mapping methods is unsupported. Custom Markdown extensions remain lintable standalone when the preprocessor does not recognize them; Ruby extraction is then unavailable. The shared `Markdown:` section preserves keys owned by the preprocessor, while `IgnoreFrontMatter` belongs to this plugin.
28
+
29
+ ## Correction safety
30
+
31
+ Corrections are limited to rewrites whose source mapping and resulting document semantics are known. Markdown reflow preserves container prefixes, hard breaks, inline atomic syntax, and HTML break behavior; text preserves literal contents and paragraph boundaries. Unbreakable tokens and ambiguous structural rewrites can be reported without correction. Markdown structural checks do not reflow headings, tables, or code.
32
+
33
+ Source scanners retain original reference spellings and ranges when AST resolution discards them, and protect inline constructs such as links, code, escapes, and HTML from unrelated formatting corrections. Renderer-dependent heading fragments are configurable approximations, not guarantees for every renderer or extension. Parser warnings are native syntax diagnostics rather than a complete CommonMark validation.
34
+
35
+ Bare link destinations use character-based searches to skip ordinary path text, retaining whitespace, nesting, and escape checks at candidate boundaries without changing original Unicode offsets.
36
+
37
+ Shared blank-line cleanup respects the minimum padding required by enabled, applicable Markdown structure-spacing cops, without applying those rules to plain text. When an offense has multiple plausible rewrites, the cop reports it without choosing one.
38
+
39
+ `Markdown/HardBreakStyle` applies to parser-recognized paragraph hard breaks, not arbitrary terminal backslashes or code. Its default backslash style is coordinated with `Markdown/TrailingWhitespace` so the two cops do not issue overlapping edits; conversions that could change backslash escaping are report-only.
40
+
41
+ Shell-prompt removal preserves code-content ranges and container prefixes. Blocks with output or ambiguous `#` prompts remain uncorrected; so does an entire block if removing any prompt could expose its closing delimiter. See [Markdown/ShellPrompts](docs/cops/markdown/shell_prompts.md) for prompt and language settings.
42
+
43
+ `Markdown/ListContinuationIndentation` uses parsed list-item membership and each paragraph's original-source mapping to find continuation lines, excluding following root paragraphs and child list blocks. Its expected column comes from the parsed item's marker, so ordered marker widths and container prefixes are retained. It reports only: reindentation could change Markdown block ownership, so no correction is offered.
44
+
45
+ Cop guides describe user-visible behavior and correction limits. Parsing, source mapping, and correction rationale belong here rather than in individual guides.
46
+
47
+ ## Artwork
48
+
49
+ The logo pairs the RuboCop helmet with a parchment scroll, keeping both silhouettes legible at the README's 160px display size. Its opaque white background preserves contrast on dark pages.
50
+
51
+ `assets/rubocop-logo.svg` is copied unchanged from [the official website's SVG at a pinned commit](https://github.com/rubocop/rubocop.org/blob/e48d295d87264ea7dbfa0c6df7c7c4b56670979d/src/images/favicon.svg). The upstream MIT copyright and permission notice is preserved in [assets/RUBOCOP-LICENSE](assets/RUBOCOP-LICENSE); the newly drawn scroll uses this repository's [MIT license](LICENSE.txt). Editing and rendering instructions are in [CONTRIBUTING.md](CONTRIBUTING.md#artwork), and all artwork sources, rendered images, and the notice are packaged together.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Doubrovkine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,152 @@
1
+ <img src="assets/logo.gif" alt="The RuboCop helmet logo alongside a parchment scroll rolling up and unfurling." width="160">
2
+
3
+ # rubocop-prose
4
+
5
+ [![Lint](https://github.com/dblock/rubocop-prose/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/dblock/rubocop-prose/actions/workflows/lint.yml) [![Tests](https://github.com/dblock/rubocop-prose/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/dblock/rubocop-prose/actions/workflows/test.yml)
6
+
7
+ Markdown and plain-text prose checks for RuboCop.
8
+
9
+ Use [rubocop-md](https://github.com/rubocop/rubocop-md) to lint Ruby code inside Markdown.
10
+
11
+ This project was inspired by [To Wrap or Not to Wrap in Markdown](https://code.dblock.org/2021/06/07/to-wrap-or-not-to-wrap-in-markdown.html) and borrows many Markdown checks from [markdownlint](https://github.com/DavidAnson/markdownlint).
12
+
13
+ ## Installation
14
+
15
+ Add to your Gemfile, then run `bundle install`:
16
+
17
+ ```ruby
18
+ gem 'rubocop-prose', '~> 0.1', require: false
19
+ ```
20
+
21
+ Add it to `.rubocop.yml` using RuboCop's plugin interface:
22
+
23
+ ```yaml
24
+ plugins:
25
+ - rubocop-prose
26
+ ```
27
+
28
+ Ruby 3.2 or newer and RuboCop 1.72.1 or newer within 1.x are supported.
29
+
30
+ ## Usage
31
+
32
+ Given `example.md`:
33
+
34
+ ```markdown
35
+ A paragraph split
36
+ across two source lines.
37
+ ```
38
+
39
+ Run:
40
+
41
+ ```sh
42
+ bundle exec rubocop example.md
43
+ ```
44
+
45
+ ```text
46
+ example.md:2:1: C: [Correctable] Prose/MaxLength: Keep paragraph text on a single source line.
47
+ across two source lines.
48
+ ^^^^^^^^^^^^^^^^^^^^^^^^
49
+ ```
50
+
51
+ Fix it automatically with `bundle exec rubocop -a example.md`.
52
+
53
+ ## Cops
54
+
55
+ ### Markdown
56
+
57
+ Markdown checks ignore [front matter](docs/settings/front_matter.md) by default and do not treat code blocks as prose. Dedicated code-block cops check their structure; [Markdown/HardTabs](docs/cops/markdown/hard_tabs.md) and [Markdown/StructuralLineLength](docs/cops/markdown/structural_line_length.md) can also inspect code content. Inline formatting checks leave code spans, links, escaped syntax, and HTML untouched unless they specifically check those constructs.
58
+
59
+ | Cop | Default | Purpose |
60
+ | --- | --- | ------- |
61
+ | [Markdown/AtxHeadingSpace](docs/cops/markdown/atx_heading_space.md) | Enabled | Separate opening ATX heading hashes from text. |
62
+ | [Markdown/AtxHeadingSpacing](docs/cops/markdown/atx_heading_spacing.md) | Enabled | Use one space after opening ATX heading hashes. |
63
+ | [Markdown/BareUrl](docs/cops/markdown/bare_url.md) | Disabled | Require Markdown links or autolinks around bare URLs. |
64
+ | [Markdown/BlockquoteBlankLines](docs/cops/markdown/blockquote_blank_lines.md) | Enabled | Keep quote markers on blank lines between blockquotes. |
65
+ | [Markdown/BlockquoteSpacing](docs/cops/markdown/blockquote_spacing.md) | Enabled | Use one space after nonempty blockquote markers. |
66
+ | [Markdown/ClosedHeadingSpace](docs/cops/markdown/closed_heading_space.md) | Enabled | Separate closing ATX heading hashes from text. |
67
+ | [Markdown/ClosedHeadingSpacing](docs/cops/markdown/closed_heading_spacing.md) | Enabled | Use one space before closing ATX heading hashes. |
68
+ | [Markdown/CompactLists](docs/cops/markdown/compact_lists.md) | Enabled | Avoid blank lines between simple list items. |
69
+ | [Markdown/CodeBlockStyle](docs/cops/markdown/code_block_style.md) | Disabled | Use fenced, indented, or consistently styled code blocks. |
70
+ | [Markdown/CodeSpanSpacing](docs/cops/markdown/code_span_spacing.md) | Enabled | Avoid unnecessary padding inside inline code. |
71
+ | [Markdown/DescriptiveLinkText](docs/cops/markdown/descriptive_link_text.md) | Enabled | Require descriptive link text instead of generic labels. |
72
+ | [Markdown/DuplicateHeadings](docs/cops/markdown/duplicate_headings.md) | Enabled | Avoid duplicate heading text. |
73
+ | [Markdown/EmphasisHeading](docs/cops/markdown/emphasis_heading.md) | Disabled | Avoid single-line emphasis-only paragraphs in place of headings. |
74
+ | [Markdown/EmphasisSpacing](docs/cops/markdown/emphasis_spacing.md) | Enabled | Remove whitespace immediately inside emphasis delimiters. |
75
+ | [Markdown/EmphasisStyle](docs/cops/markdown/emphasis_style.md) | Enabled | Use a configured or consistent emphasis delimiter. |
76
+ | [Markdown/EmptyLink](docs/cops/markdown/empty_link.md) | Enabled | Require a nonempty link destination. |
77
+ | [Markdown/FenceBlankLines](docs/cops/markdown/fence_blank_lines.md) | Enabled | Surround fenced code blocks with container-aware blank lines. |
78
+ | [Markdown/FenceLanguage](docs/cops/markdown/fence_language.md) | Enabled | Require a language and optionally restrict fence languages. |
79
+ | [Markdown/FenceStyle](docs/cops/markdown/fence_style.md) | Enabled | Use backtick, tilde, or consistently styled fences. |
80
+ | [Markdown/FirstHeading](docs/cops/markdown/first_heading.md) | Disabled | Begin documents with a heading or front-matter title. |
81
+ | [Markdown/HardBreakStyle](docs/cops/markdown/hard_break_style.md) | Enabled | Use backslashes or trailing spaces for paragraph hard breaks. |
82
+ | [Markdown/HardTabs](docs/cops/markdown/hard_tabs.md) | Enabled | Disallow hard tabs with code-language exceptions. |
83
+ | [Markdown/HeadingBlankLines](docs/cops/markdown/heading_blank_lines.md) | Enabled | Surround headings with blank lines. |
84
+ | [Markdown/HeadingIncrement](docs/cops/markdown/heading_increment.md) | Enabled | Increase heading levels without skipping levels. |
85
+ | [Markdown/HeadingIndentation](docs/cops/markdown/heading_indentation.md) | Enabled | Avoid leading indentation before headings. |
86
+ | [Markdown/HeadingPunctuation](docs/cops/markdown/heading_punctuation.md) | Disabled | Avoid configured trailing heading punctuation. |
87
+ | [Markdown/HeadingStructure](docs/cops/markdown/heading_structure.md) | Disabled | Match a configured exact heading outline. |
88
+ | [Markdown/HeadingStyle](docs/cops/markdown/heading_style.md) | Disabled | Use a consistent heading syntax. |
89
+ | [Markdown/ImageAltText](docs/cops/markdown/image_alt_text.md) | Enabled | Require nonblank Markdown image alternative text. |
90
+ | [Markdown/ImagePathSeparators](docs/cops/markdown/image_path_separators.md) | Enabled | Use forward slashes in local image destinations. |
91
+ | [Markdown/LinkFragment](docs/cops/markdown/link_fragment.md) | Disabled | Validate local fragments using configurable heading anchors. |
92
+ | [Markdown/LinkStyle](docs/cops/markdown/link_style.md) | Disabled | Configure permitted link and image styles independently. |
93
+ | [Markdown/LinkTextSpacing](docs/cops/markdown/link_text_spacing.md) | Enabled | Remove leading and trailing whitespace from link text. |
94
+ | [Markdown/ListBlankLines](docs/cops/markdown/list_blank_lines.md) | Enabled | Surround parsed lists with blank lines. |
95
+ | [Markdown/ListContinuationIndentation](docs/cops/markdown/list_continuation_indentation.md) | Enabled | Indent list continuation text to its item's content column. |
96
+ | [Markdown/ListIndentation](docs/cops/markdown/list_indentation.md) | Enabled | Keep sibling list markers consistently indented. |
97
+ | [Markdown/ListMarkerSpacing](docs/cops/markdown/list_marker_spacing.md) | Enabled | Configure spaces after ordered and unordered list markers. |
98
+ | [Markdown/OrderedListNumbering](docs/cops/markdown/ordered_list_numbering.md) | Disabled | Use sequential numbers or repeated ones in ordered lists. |
99
+ | [Markdown/OutsideSpacing](docs/cops/markdown/outside_spacing.md) | Enabled | Report inline formatting directly adjacent to prose words. |
100
+ | [Markdown/ProperNames](docs/cops/markdown/proper_names.md) | Disabled | Use configured capitalization for proper names. |
101
+ | [Markdown/RawHtml](docs/cops/markdown/raw_html.md) | Disabled | Disallow raw HTML except explicitly allowed elements. |
102
+ | [Markdown/ReferenceDefinitions](docs/cops/markdown/reference_definitions.md) | Enabled | Report unused and duplicate reference definitions. |
103
+ | [Markdown/ReversedLink](docs/cops/markdown/reversed_link.md) | Enabled | Report reversed Markdown link delimiters. |
104
+ | [Markdown/ShellPrompts](docs/cops/markdown/shell_prompts.md) | Enabled | Omit configured shell prompts in examples without output. |
105
+ | [Markdown/SingleTopLevelHeading](docs/cops/markdown/single_top_level_heading.md) | Disabled | Allow at most one top-level heading. |
106
+ | [Markdown/StrongStyle](docs/cops/markdown/strong_style.md) | Enabled | Use a configured or consistent strong delimiter. |
107
+ | [Markdown/StructuralLineLength](docs/cops/markdown/structural_line_length.md) | Disabled | Report overlong heading, code-block, and table source lines without reflowing them. |
108
+ | [Markdown/Syntax](docs/cops/markdown/syntax.md) | Enabled | Report native Markdown parser diagnostics. |
109
+ | [Markdown/TableBlankLines](docs/cops/markdown/table_blank_lines.md) | Enabled | Surround Markdown tables with blank lines. |
110
+ | [Markdown/TableColumns](docs/cops/markdown/table_columns.md) | Enabled | Match table body column counts to the header. |
111
+ | [Markdown/TablePipes](docs/cops/markdown/table_pipes.md) | Enabled | Use consistent leading and trailing table pipes. |
112
+ | [Markdown/TableSpacing](docs/cops/markdown/table_spacing.md) | Enabled | Use configured spacing around table cell content. |
113
+ | [Markdown/ThematicBreakBlankLines](docs/cops/markdown/thematic_break_blank_lines.md) | Enabled | Surround parsed thematic breaks with container-aware blank lines. |
114
+ | [Markdown/ThematicBreakStyle](docs/cops/markdown/thematic_break_style.md) | Enabled | Use a configured or consistent thematic break. |
115
+ | [Markdown/TrailingWhitespace](docs/cops/markdown/trailing_whitespace.md) | Enabled | Remove trailing whitespace while retaining Markdown hard breaks. |
116
+ | [Markdown/UnclosedFencedCodeBlock](docs/cops/markdown/unclosed_fenced_code_block.md) | Enabled | Require an explicit closing fence for fenced code blocks. |
117
+ | [Markdown/UndefinedReference](docs/cops/markdown/undefined_reference.md) | Enabled | Require definitions for link and image references. |
118
+ | [Markdown/UnorderedListIndentation](docs/cops/markdown/unordered_list_indentation.md) | Enabled | Use a configured indentation width for unordered lists. |
119
+ | [Markdown/UnorderedListMarker](docs/cops/markdown/unordered_list_marker.md) | Enabled | Use a configured or consistent unordered list marker. |
120
+ | [Prose/MaxLength](docs/cops/prose/max_length.md) | Enabled | Wrap or unwrap prose paragraphs in Markdown and plain text. |
121
+ | [Prose/MultipleBlankLines](docs/cops/prose/multiple_blank_lines.md) | Enabled | Limit blank lines in prose and quotes, but not code. |
122
+ | [Prose/TrailingNewline](docs/cops/prose/trailing_newline.md) | Enabled | Require exactly one final newline. |
123
+
124
+ #### Settings
125
+
126
+ | Setting | Purpose |
127
+ | --- | --- |
128
+ | [Markdown/Include](docs/settings/files.md) | Select files parsed as Markdown using native RuboCop file patterns. |
129
+ | [Markdown/IgnoreFrontMatter](docs/settings/front_matter.md) | Ignore closed leading metadata during Markdown inspection. |
130
+
131
+ ### Text
132
+
133
+ | Cop | Default | Purpose |
134
+ | --- | --- | ------- |
135
+ | [Prose/MaxLength](docs/cops/prose/max_length.md) | Enabled | Wrap or unwrap prose paragraphs in Markdown and plain text. |
136
+ | [Prose/MultipleBlankLines](docs/cops/prose/multiple_blank_lines.md) | Enabled | Limit consecutive literal blank lines. |
137
+ | [Prose/TrailingNewline](docs/cops/prose/trailing_newline.md) | Enabled | Require exactly one final newline. |
138
+ | [Text/TrailingWhitespace](docs/cops/text/trailing_whitespace.md) | Enabled | Remove all trailing spaces and tabs from plain-text lines. |
139
+
140
+ #### Settings
141
+
142
+ | Setting | Purpose |
143
+ | --- | --- |
144
+ | [Text/Include](docs/settings/files.md) | Select files parsed as literal text using native RuboCop file patterns. |
145
+
146
+ ## Project documentation
147
+
148
+ See [CONTRIBUTING](CONTRIBUTING.md) for development, testing, and artwork maintenance, [DESIGN](DESIGN.md) for architecture and design decisions, and [AGENTS](AGENTS.md) for contributor instructions for coding agents.
149
+
150
+ ## License
151
+
152
+ Released under the [MIT license](LICENSE.txt).
data/RELEASING.md ADDED
@@ -0,0 +1,32 @@
1
+ # Releasing rubocop-prose
2
+
3
+ Release only with explicit maintainer authorization. Release preparation happens on `main`; never force-push `main`.
4
+
5
+ ## Prepare
6
+
7
+ Update `main` with a fast-forward pull. Run `bundle exec rake` and confirm GitHub Actions checks pass, including the separate interoperability workflow. Verify the minimum supported RuboCop with `RUBOCOP_VERSION=1.72.1 bundle install` and `RUBOCOP_VERSION=1.72.1 bundle exec rake spec`; restore the normal dependency resolution afterward. Interoperability currently uses rubocop-md PR #57; update its workflow ref and README compatibility note when the original-source mapping API is released.
8
+
9
+ Set the version in `lib/rubocop/prose/version.rb`, date its CHANGELOG heading as `YYYY/MM/DD`, remove the contribution placeholder from that release, and check README installation instructions. Commit and push preparation changes, wait for green CI, then build and inspect the package:
10
+
11
+ ```sh
12
+ bundle exec rake build
13
+ gem specification pkg/rubocop-prose-0.1.0.gem files
14
+ ```
15
+
16
+ Confirm runtime code, configuration, cop guides, README, CHANGELOG, licenses, and artwork are present; exclude tests, temporary workspaces, and dependency caches. Preserve the vendored helmet license and provenance. Install the exact built gem into a temporary gem environment outside the checkout and exercise plugin loading, discovery, stdin, configuration, and repeated autocorrection for Markdown and text.
17
+
18
+ ## Publish
19
+
20
+ Publish the exact inspected package. Enter a fresh RubyGems MFA code when prompted; never put credentials or codes in source, logs, or documentation.
21
+
22
+ For an assistant-driven release, ask the maintainer for a fresh MFA code only when ready to publish and pass it through `GEM_HOST_OTP_CODE`, not the `--otp` command-line argument. Prefer a hidden local prompt. If the maintainer explicitly chooses chat, explain that the code will be visible in conversation history. Never save the code in repository files or documentation. Alternatively, the maintainer can run `gem push` interactively.
23
+
24
+ ```sh
25
+ gem push pkg/rubocop-prose-0.1.0.gem
26
+ ```
27
+
28
+ Verify that exact version on RubyGems before creating and pushing an annotated `v0.1.0` tag at the release commit. Create a GitHub release with matching changelog notes. Do not move an existing release tag.
29
+
30
+ ## Next development iteration
31
+
32
+ Bump the gem version, add a matching `(Next)` CHANGELOG section with `* Your contribution here.`, then commit and push to `main`.
data/assets/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Logo artwork
2
+
3
+ See [DESIGN.md](../DESIGN.md#artwork) for composition and source attribution, [CONTRIBUTING.md](../CONTRIBUTING.md#artwork) for editing and rendering instructions, and [RUBOCOP-LICENSE](RUBOCOP-LICENSE) for the upstream copyright and permission notice.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012-26 Bozhidar Batsov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/assets/logo.gif ADDED
Binary file
data/assets/logo.png ADDED
Binary file
data/assets/logo.svg ADDED
@@ -0,0 +1,80 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512" role="img" aria-labelledby="title description">
2
+ <title id="title">rubocop-prose logo</title>
3
+ <desc id="description">RuboCop's original helmet logo alongside a parchment scroll that rolls up and unfurls.</desc>
4
+ <style>
5
+ .scroll-static { display: none; }
6
+ @media (prefers-reduced-motion: reduce) {
7
+ .scroll-animated { display: none; }
8
+ .scroll-static { display: inline; }
9
+ }
10
+ </style>
11
+ <defs>
12
+ <g id="scroll-paper-static">
13
+ <path fill="#fff" stroke="#fff" stroke-width="16" d="M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z"/>
14
+ <path fill="#fff6e5" stroke="#17191c" stroke-width="5" d="M-46-83h94V80c0 9-6 16-13 16h-81z"/>
15
+ </g>
16
+ <g id="scroll-top">
17
+ <path fill="#f2dfbf" stroke="#17191c" stroke-width="5" d="M-46-96h94c18 0 18 26 0 26h-94z"/>
18
+ <circle cx="-46" cy="-83" r="13" fill="#e7c9a0" stroke="#17191c" stroke-width="5"/>
19
+ <path fill="none" stroke="#17191c" stroke-width="3" d="M-43-89c-8-2-13 8-6 12 4 3 9-1 6-5"/>
20
+ </g>
21
+ <g id="scroll-lines">
22
+ <path fill="none" stroke="#ec1826" stroke-width="6" d="M-26-42H10"/>
23
+ <path fill="none" stroke="#17191c" stroke-width="4" d="M-26-16H28M-26 5h55M-26 26h40M-26 47h48"/>
24
+ </g>
25
+ <g id="scroll-bottom">
26
+ <path fill="#f2dfbf" stroke="#17191c" stroke-width="5" d="M-46 66h81c19 0 19 30 0 30h-81z"/>
27
+ <circle cx="-46" cy="81" r="15" fill="#e7c9a0" stroke="#17191c" stroke-width="5"/>
28
+ </g>
29
+ <path id="scroll-curl" fill="none" stroke="#17191c" stroke-width="3" d="M-43 74c-9-2-15 10-7 14 5 3 11-2 7-7"/>
30
+ <clipPath id="scroll-paper-clip">
31
+ <rect x="-64" y="-83" width="128" height="179">
32
+ <animate attributeName="height" dur="6s" repeatCount="indefinite"
33
+ values="179;179;43;43;179;179" keyTimes="0;0.25;0.45;0.55;0.75;1"
34
+ calcMode="spline" keySplines="0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1"/>
35
+ </rect>
36
+ </clipPath>
37
+ </defs>
38
+ <path fill="#fff" d="M0 0h512v512H0z"/>
39
+ <image href="rubocop-logo.svg" x="0" y="72" width="360" height="360"/>
40
+ <g transform="translate(423 258)" stroke-linecap="round" stroke-linejoin="round">
41
+ <g class="scroll-static">
42
+ <use href="#scroll-paper-static"/>
43
+ <use href="#scroll-top"/>
44
+ <use href="#scroll-lines"/>
45
+ <use href="#scroll-bottom"/>
46
+ <use href="#scroll-curl"/>
47
+ </g>
48
+ <g class="scroll-animated">
49
+ <path fill="#fff" stroke="#fff" stroke-width="16" d="M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z">
50
+ <animate attributeName="d" dur="6s" repeatCount="indefinite"
51
+ values="M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z;M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z;M-46-96h94c18 0 18 26 0 26V-56c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z;M-46-96h94c18 0 18 26 0 26V-56c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z;M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z;M-46-96h94c18 0 18 26 0 26V80c0 9-6 16-13 16h-81c-19 0-19-30 0-30V-70c-17 0-17-26 0-26z"
52
+ keyTimes="0;0.25;0.45;0.55;0.75;1" calcMode="spline"
53
+ keySplines="0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1"/>
54
+ </path>
55
+ <path id="scroll-paper" fill="#fff6e5" stroke="#17191c" stroke-width="5" d="M-46-83h94V80c0 9-6 16-13 16h-81z">
56
+ <animate attributeName="d" dur="6s" repeatCount="indefinite"
57
+ values="M-46-83h94V80c0 9-6 16-13 16h-81z;M-46-83h94V80c0 9-6 16-13 16h-81z;M-46-83h94V-56c0 9-6 16-13 16h-81z;M-46-83h94V-56c0 9-6 16-13 16h-81z;M-46-83h94V80c0 9-6 16-13 16h-81z;M-46-83h94V80c0 9-6 16-13 16h-81z"
58
+ keyTimes="0;0.25;0.45;0.55;0.75;1" calcMode="spline"
59
+ keySplines="0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1"/>
60
+ </path>
61
+ <use href="#scroll-top"/>
62
+ <g clip-path="url(#scroll-paper-clip)">
63
+ <use href="#scroll-lines"/>
64
+ </g>
65
+ <g id="scroll-roller">
66
+ <animateTransform attributeName="transform" type="translate" dur="6s" repeatCount="indefinite"
67
+ values="0 0;0 0;0 -136;0 -136;0 0;0 0" keyTimes="0;0.25;0.45;0.55;0.75;1"
68
+ calcMode="spline" keySplines="0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1"/>
69
+ <use href="#scroll-bottom"/>
70
+ <g>
71
+ <animateTransform attributeName="transform" type="rotate" dur="6s" repeatCount="indefinite"
72
+ values="0 -46 81;0 -46 81;-540 -46 81;-540 -46 81;0 -46 81;0 -46 81"
73
+ keyTimes="0;0.25;0.45;0.55;0.75;1" calcMode="spline"
74
+ keySplines="0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1;0.45 0 0.2 1"/>
75
+ <use href="#scroll-curl"/>
76
+ </g>
77
+ </g>
78
+ </g>
79
+ </g>
80
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-9.46 0 121.6 121.6"><style>path{fill:#151515}.visor{fill:#eb1c23}@media (prefers-color-scheme:dark){path{fill:#e8e8e3}.visor{fill:#ff2a31}}</style><path d="M99.67 51.58V47.7a7.75 7.75 0 0 0-7.73-7.73h-81.2a7.75 7.75 0 0 0-7.73 7.73v3.88A6.3 6.3 0 0 0 0 56.92v10.39a6.3 6.3 0 0 0 3.01 5.33v4.04a7.75 7.75 0 0 0 7.73 7.72h81.2a7.75 7.75 0 0 0 7.73-7.72v-4.04a6.3 6.3 0 0 0 3.01-5.33V56.92a6.3 6.3 0 0 0-3.01-5.34M51.34 0A43 43 0 0 0 8.7 37.5h85.28A43 43 0 0 0 51.34 0M38.65 95.73h25.38l2.6 3 3.89-3.37-4.13-4.78h-30.1l-4.14 4.78 3.9 3.37zm43.39-8.87v16.43a8.24 8.24 0 0 1-8.21 8.22h-4.47v-.02c-.98 0-1.85-.45-2.42-1.16h-.01l-5.35-6.83-.01.01a3.1 3.1 0 0 0-2.46-1.23l-.01-.01-.02.01H43.6l-.02-.01-.02.01a3.1 3.1 0 0 0-2.33 1.07l-.01-.01-5.47 6.99h-.01a3.1 3.1 0 0 1-2.42 1.16v.02h-4.47a8.25 8.25 0 0 1-8.22-8.22V86.86H10.59v16.48a18.3 18.3 0 0 0 18.26 18.26h44.98a18.3 18.3 0 0 0 18.26-18.26V86.86z"/><path class="visor" d="M84.46 67.87H18.21a5.7 5.7 0 0 1-5.68-5.68 5.7 5.7 0 0 1 5.68-5.69h66.25a5.7 5.7 0 0 1 5.69 5.69 5.7 5.7 0 0 1-5.69 5.68"/></svg>
@@ -0,0 +1,3 @@
1
+ Markdown/AtxHeadingSpace:
2
+ Description: 'Separate opening ATX heading hashes from text.'
3
+ Enabled: true
@@ -0,0 +1,3 @@
1
+ Markdown/AtxHeadingSpacing:
2
+ Description: 'Use one space after opening ATX heading hashes.'
3
+ Enabled: true