Skip to content

Commit

Permalink
Require space between hash/content in ATX heading
Browse files Browse the repository at this point in the history
While writing some Markdown documentation for Rails, I came across an
interesting case where trying to link to an instance method at the start
of a line would instead parse as an H1 heading:

```markdown
#response_body=
```

Expected:

```html
<a href=""><code>#response_body=</code></a>
```

Actual:

```html
<h1>response_body=</h1>
```

According to the CommonMark spec:

> At least one space or tab is required between the # characters and the
> heading’s contents, unless the heading is empty. Note that many
> implementations currently do not require the space. However, the space
> was required by the original ATX implementation, and it helps prevent
> things like the following from being parsed as headings:
>
> Example 64

So while some implementations do not follow this requirement, I believe
RDoc should because it makes it easy to write text similar to Example 64
(which was used in the new test) and it also enables automatically
linking to instance methods at the start of a line.
  • Loading branch information
skipkayhil committed Jul 13, 2024
1 parent 636e34b commit 2ad9662
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
2 changes: 1 addition & 1 deletion lib/rdoc/markdown.kpeg
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ AtxInline = !@Newline !(@Sp /#*/ @Sp @Newline) Inline
AtxStart = < /\#{1,6}/ >
{ text.length }

AtxHeading = AtxStart:s @Sp AtxInline+:a (@Sp /#*/ @Sp)? @Newline
AtxHeading = AtxStart:s @Spacechar+ AtxInline+:a (@Sp /#*/ @Sp)? @Newline
{ RDoc::Markup::Heading.new(s, a.join) }

SetextHeading = SetextHeading1 | SetextHeading2
Expand Down
17 changes: 15 additions & 2 deletions test/rdoc/test_rdoc_markdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,23 @@ def test_parse_escape
end

def test_parse_heading_atx
doc = parse "# heading\n"
# CommonMark Example 62
(1..6).each do |level|
doc = parse "#{"#" * level} heading\n"

expected = @RM::Document.new(
@RM::Heading.new(level, "heading"))

assert_equal expected, doc
end

# CommonMark Example 64
doc = parse "#5 bolt\n\n#hashtag\n"

expected = @RM::Document.new(
@RM::Heading.new(1, "heading"))
para("#5 bolt"),
para("#hashtag"),
)

assert_equal expected, doc
end
Expand Down

0 comments on commit 2ad9662

Please sign in to comment.