feat: add no-heading-like-paragraph rule - #716
Conversation
lumirlumir
left a comment
There was a problem hiding this comment.
Disclosure: I'm a participant of open source contribution program OSSCA: confirmed.
Can you take a look at the CI failure? Running npm run fmt should resolve the problem.
| const gfmRuleTester = new RuleTester({ | ||
| plugins: { | ||
| markdown, | ||
| }, | ||
| language: "markdown/gfm", | ||
| }); |
There was a problem hiding this comment.
I think we can use language: "markdown/gfm" where necessary to test GFM mode, as shown below. Consolidating these RuleTester test cases with the ones above also seems helpful.
markdown/tests/rules/no-missing-label-refs.test.js
Lines 126 to 131 in ac31775
There was a problem hiding this comment.
Integrated the GFM cases into the existing RuleTester as suggested.
| type: "problem", | ||
|
|
||
| docs: { | ||
| recommended: false, |
There was a problem hiding this comment.
| recommended: false, |
Non-blocking stylistic choice: The repository usually omits the recommended field when it is false.
There was a problem hiding this comment.
Removed recommended: false to match the existing repository style. Thanks!
| endColumn: 8, | ||
| suggestions: [ | ||
| { | ||
| messageId: "useMaxDepthHashes", |
There was a problem hiding this comment.
Could you add the missing data properties to the invalid test cases? This applies to all other invalid test cases as well.
There was a problem hiding this comment.
Added the required data properties to all invalid test cases.
| Seven ####### characters in the middle of a paragraph. | ||
| ``` | ||
|
|
||
| This rule only checks the beginning of a paragraph, so it ignores hash characters on a continuation line: |
There was a problem hiding this comment.
This case should still be handled by the rule as the writer expects to create a heading (which would be created if it would use valid heading syntax).
This could be accomplished by setting the m(ultiline) flag for headingLikeParagraphPattern.
There was a problem hiding this comment.
I agree. I’ll update the rule to handle continuation lines as well. I think this will also keep it consistent with no-missing-atx-heading-space.
However, since the m flag alone can miss continuation lines inside blockquotes or list items, would it be okay to handle those container cases as well as the top-level case and add tests for them?
There was a problem hiding this comment.
I do not think we need to check for continuation lines inside a container (like blockquotes).
What do you think @lumirlumir?
| * the author escaped the leading hash on purpose. | ||
| */ | ||
| const match = headingLikeParagraphPattern.exec( | ||
| sourceCode.getText(node), |
There was a problem hiding this comment.
| sourceCode.getText(node), | |
| sourceCode.getText(node.children[0]), |
Why not use just the first child. This would make the text potentially smaller which is always good when using regular expressions.
There was a problem hiding this comment.
Using only the first child could introduce false positives when inline markup immediately follows the hashes. For example, in the current valid test case #######*Installation*, the source of the first child ends with #######, so the $ condition in the regular expression could match. However, in the full paragraph source, the hashes are followed by *, so it does not satisfy the ATX heading delimiter condition.
Also, checking only the first child would not be sufficient for handling continuation lines discussed in the other thread. For example, in Install **first**.\n####### Config, the heading-like text can be contained in a later child rather than the first one, so this case would be missed.
For correctness, I think matching against the whole paragraph source is safer than checking only the first child.
There was a problem hiding this comment.
For this edge case you can pass afterCount to get also the following characters, so
sourceCode.getText(node.children[0], 0, 1).
| ], | ||
| }, | ||
| { | ||
| code: "#######", |
There was a problem hiding this comment.
I do not think this should be an invalid test case as the text after the hashes are missing.
Some may use thisas decoration.
There was a problem hiding this comment.
That makes sense. If there’s no text after the hashes, I agree that it’s much less clear whether the author actually intended to create a heading. For reference, remark-lint-no-heading-like-paragraph does report a bare #######, but I agree that this case could reasonably be treated as decoration.
I’d just like to clarify the intended scope. Should cases like ####### , where the hashes are followed only by trailing whitespace, and #######\nText, where the first line of a multi-line paragraph contains only the hashes, also be ignored? Or should only the single-line bare ####### case be excluded?
| messageId: "headingLikeParagraph", | ||
| data: { count: hashes.length }, | ||
|
|
||
| /* |
There was a problem hiding this comment.
This comment is unnecessary as two suggestions are provided, it is clear that there can be no autofix.
There was a problem hiding this comment.
I removed the unnecessary comment as you suggested. Thank you!
Prerequisites checklist
AI acknowledgment
What is the purpose of this pull request?
This PR implements the
no-heading-like-paragraphrule proposed and accepted in #700.CommonMark ATX headings support at most six
#characters. As a result, content such as####### Installationis parsed as a paragraph rather than a heading, even though it can easily look like an intended heading in the source.The rule reports these heading-like paragraphs so that likely heading mistakes can be identified.
What changes did you make? (Give an overview)
no-heading-like-paragraphrule for paragraphs that look like ATX headings with seven or more leading#characters.#to keep it as a paragraph.Related Issues
fixes #700
Disclosure: I'm a participant of open source contribution program OSSCA