[ruby/rdoc] Allow rich definition list labels for Markdown

Previously, any sort of "rich" markup for a definition list's label
would cause the Markdown parser to not recognize a definition list:

```ruby
md = <<~md
`one`
:    This is a definition
md

doc = RDoc::Markdown.parse(md)
doc # => [doc: [para: "<code>one</code>\n: This is a definition"]]
```

This commit tweaks the grammar for Markdown definition lists so that
labels can include "rich" markup such as bold (`**`), code (```), etc:

```ruby
md = <<~md
`one`
:    This is a definition
md

doc = RDoc::Markdown.parse(md)
doc # => [doc: [list: NOTE [item: ["<code>one</code>"]; [para: "This is a definition"]]]]
```

The [PHP Markdown Extra][1] Spec does not seem to specify whether or not
this should be allowed, but it is allowed in the RDoc format:

```ruby
rdoc = <<~rdoc
+code+::
    This is a definition
rdoc

doc = RDoc::Markup.parse(rdoc)
doc # => [doc: [list: NOTE [item: ["+code+"]; [para: "This is a definition"]]]]
```

so accepting this change increases the parity of the two formats.

[1]: https://michelf.ca/projects/php-markdown/extra/#def-list

8f943bbba4
This commit is contained in:
Hartley McGuire 2024-03-06 20:22:28 -05:00 committed by Nobuyoshi Nakada
parent 7a398adc2f
commit 08961ce8e3
2 changed files with 22 additions and 3 deletions

View file

@ -16445,12 +16445,12 @@ class RDoc::Markdown
return _tmp return _tmp
end end
# DefinitionListLabel = StrChunk:label @Sp @Newline { label } # DefinitionListLabel = Inline:label @Sp @Newline { label }
def _DefinitionListLabel def _DefinitionListLabel
_save = self.pos _save = self.pos
while true # sequence while true # sequence
_tmp = apply(:_StrChunk) _tmp = apply(:_Inline)
label = @result label = @result
unless _tmp unless _tmp
self.pos = _save self.pos = _save
@ -16777,7 +16777,7 @@ class RDoc::Markdown
Rules[:_TableAlign] = rule_info("TableAlign", "< /:?-+:?/ > @Sp { text.start_with?(\":\") ? (text.end_with?(\":\") ? :center : :left) : (text.end_with?(\":\") ? :right : nil) }") Rules[:_TableAlign] = rule_info("TableAlign", "< /:?-+:?/ > @Sp { text.start_with?(\":\") ? (text.end_with?(\":\") ? :center : :left) : (text.end_with?(\":\") ? :right : nil) }")
Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }") Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }")
Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }") Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }")
Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }") Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "Inline:label @Sp @Newline { label }")
Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "@NonindentSpace \":\" @Space Inlines:a @BlankLine+ { paragraph a }") Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "@NonindentSpace \":\" @Space Inlines:a @BlankLine+ { paragraph a }")
# :startdoc: # :startdoc:
end end

View file

@ -305,6 +305,25 @@ that also extends to two lines
assert_equal expected, doc assert_equal expected, doc
end end
def test_parse_definition_list_rich_label
doc = parse <<-MD
`one`
: This is a definition
**two**
: This is another definition
MD
expected = doc(
list(:NOTE,
item(%w[<code>one</code>],
para("This is a definition")),
item(%w[*two*],
para("This is another definition"))))
assert_equal expected, doc
end
def test_parse_definition_list_no def test_parse_definition_list_no
@parser.definition_lists = false @parser.definition_lists = false