Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for Markdown hard line breaks.

Broke backwards compatibility with RDoc 3.12 for RDoc::Markup::Paragraph from ri when handling paragraphs spanning multiple lines.
  • Loading branch information...
commit f8016a2af94fc9426db13815a6d9d8a56547d33c 1 parent c74de82
@drbrain drbrain authored
Showing with 328 additions and 68 deletions.
  1. +3 −0  Manifest.txt
  2. +2 −4 TODO.rdoc
  3. +1 −1  lib/rdoc/markdown.kpeg
  4. +1 −0  lib/rdoc/markup.rb
  5. +1 −1  lib/rdoc/markup/attribute_manager.rb
  6. +3 −0  lib/rdoc/markup/formatter.rb
  7. +29 −18 lib/rdoc/markup/formatter_test_case.rb
  8. +31 −0 lib/rdoc/markup/hard_break.rb
  9. +14 −0 lib/rdoc/markup/indented_paragraph.rb
  10. +14 −0 lib/rdoc/markup/paragraph.rb
  11. +5 −5 lib/rdoc/markup/parser.rb
  12. +12 −3 lib/rdoc/markup/to_html.rb
  13. +3 −1 lib/rdoc/markup/to_html_snippet.rb
  14. +37 −3 lib/rdoc/markup/to_joined_paragraph.rb
  15. +6 −2 lib/rdoc/markup/to_rdoc.rb
  16. +14 −0 lib/rdoc/test_case.rb
  17. +1 −1  test/test_rdoc_markdown.rb
  18. +31 −0 test/test_rdoc_markup_hard_break.rb
  19. +14 −0 test/test_rdoc_markup_indented_paragraph.rb
  20. +15 −1 test/test_rdoc_markup_paragraph.rb
  21. +24 −26 test/test_rdoc_markup_parser.rb
  22. +4 −0 test/test_rdoc_markup_to_ansi.rb
  23. +6 −0 test/test_rdoc_markup_to_bs.rb
  24. +4 −0 test/test_rdoc_markup_to_html.rb
  25. +8 −2 test/test_rdoc_markup_to_html_snippet.rb
  26. +32 −0 test/test_rdoc_markup_to_joined_paragraph.rb
  27. +4 −0 test/test_rdoc_markup_to_rdoc.rb
  28. +1 −0  test/test_rdoc_markup_to_table_of_contents.rb
  29. +4 −0 test/test_rdoc_markup_to_tt_only.rb
  30. +4 −0 test/test_rdoc_text.rb
View
3  Manifest.txt
@@ -100,6 +100,7 @@ lib/rdoc/markup/block_quote.rb
lib/rdoc/markup/document.rb
lib/rdoc/markup/formatter.rb
lib/rdoc/markup/formatter_test_case.rb
+lib/rdoc/markup/hard_break.rb
lib/rdoc/markup/heading.rb
lib/rdoc/markup/include.rb
lib/rdoc/markup/indented_paragraph.rb
@@ -215,6 +216,7 @@ test/test_rdoc_markup.rb
test/test_rdoc_markup_attribute_manager.rb
test/test_rdoc_markup_document.rb
test/test_rdoc_markup_formatter.rb
+test/test_rdoc_markup_hard_break.rb
test/test_rdoc_markup_heading.rb
test/test_rdoc_markup_include.rb
test/test_rdoc_markup_indented_paragraph.rb
@@ -227,6 +229,7 @@ test/test_rdoc_markup_to_bs.rb
test/test_rdoc_markup_to_html.rb
test/test_rdoc_markup_to_html_crossref.rb
test/test_rdoc_markup_to_html_snippet.rb
+test/test_rdoc_markup_to_joined_paragraph.rb
test/test_rdoc_markup_to_label.rb
test/test_rdoc_markup_to_rdoc.rb
test/test_rdoc_markup_to_table_of_contents.rb
View
6 TODO.rdoc
@@ -8,10 +8,8 @@ Blockers:
* The alias keyword should not be bidirectional
* Github extensions to markdown
* Fix RDoc::Parser#use_markup to handle the filename (see TODO)
-* Fix markdown link:
- [peg-markdown][pegmarkdown]
-
- [pegmarkdown]: https://...
+* Restore backwards compatibility due to paragraph text joining from existing
+ ri files
Nice to have:
View
2  lib/rdoc/markdown.kpeg
@@ -766,7 +766,7 @@ NormalEndline = Sp Newline !BlankLine !">" !AtxStart
TerminalEndline = Sp Newline Eof
-LineBreak = < " " NormalEndline > { text }
+LineBreak = < " " NormalEndline > { RDoc::Markup::HardBreak.new }
Symbol = < SpecialChar >
{ text }
View
1  lib/rdoc/markup.rb
@@ -813,6 +813,7 @@ def convert input, formatter
autoload :BlankLine, 'rdoc/markup/blank_line'
autoload :BlockQuote, 'rdoc/markup/block_quote'
autoload :Document, 'rdoc/markup/document'
+ autoload :HardBreak, 'rdoc/markup/hard_break'
autoload :Heading, 'rdoc/markup/heading'
autoload :Include, 'rdoc/markup/include'
autoload :IndentedParagraph, 'rdoc/markup/indented_paragraph'
View
2  lib/rdoc/markup/attribute_manager.rb
@@ -236,7 +236,7 @@ def add_special(pattern, name)
##
# Processes +str+ converting attributes, HTML and specials
- def flow(str)
+ def flow str
@str = str
mask_protected_sequences
View
3  lib/rdoc/markup/formatter.rb
@@ -23,11 +23,14 @@ class RDoc::Markup::Formatter
def initialize markup = nil
@markup = markup || RDoc::Markup.new
@am = @markup.attribute_manager
+ @am.add_special(/<br>/, :HARD_BREAK)
@attr_tags = []
@in_tt = 0
@tt_bit = RDoc::Markup::Attribute.bitmap_for :TT
+
+ @hard_break = ''
end
##
View
47 lib/rdoc/markup/formatter_test_case.rb
@@ -34,7 +34,7 @@
#
# end
-class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
+class RDoc::Markup::FormatterTestCase < RDoc::TestCase
##
# Call #setup when inheriting from this test case.
@@ -53,7 +53,6 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
def setup
super
- @RM = RDoc::Markup
@m = @RM.new
@bullet_list = @RM::List.new(:BULLET,
@@ -233,6 +232,17 @@ def test_accept_paragraph_b
end
##
+ # Calls accept_paragraph with a Paragraph containing a hard break
+
+ def test_accept_paragraph_break
+ @to.start_accepting
+
+ @to.accept_paragraph para('hello', hard_break, 'world')
+
+ accept_paragraph_break
+ end
+
+ ##
# Calls accept_paragraph_i with a RDoc::Markup::Paragraph containing
# emphasized words
@@ -669,22 +679,23 @@ def test_list_nested
# Calls list_verbatim with a list containing a verbatim block
def test_list_verbatim # HACK overblown
- doc = @RM::Document.new(
- @RM::List.new(:BULLET,
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('list', 'stuff'),
- @RM::BlankLine.new,
- @RM::Verbatim.new("* list\n",
- " with\n",
- "\n",
- " second\n",
- "\n",
- " 1. indented\n",
- " 2. numbered\n",
- "\n",
- " third\n",
- "\n",
- "* second\n"))))
+ doc =
+ doc(
+ list(:BULLET,
+ item(nil,
+ para('list stuff'),
+ blank_line,
+ verb("* list\n",
+ " with\n",
+ "\n",
+ " second\n",
+ "\n",
+ " 1. indented\n",
+ " 2. numbered\n",
+ "\n",
+ " third\n",
+ "\n",
+ "* second\n"))))
doc.accept @to
View
31 lib/rdoc/markup/hard_break.rb
@@ -0,0 +1,31 @@
+##
+# A hard-break in the middle of a paragraph.
+
+class RDoc::Markup::HardBreak
+
+ @instance = new
+
+ ##
+ # RDoc::Markup::HardBreak is a singleton
+
+ def self.new
+ @instance
+ end
+
+ ##
+ # Calls #accept_hard_break on +visitor+
+
+ def accept visitor
+ visitor.accept_hard_break self
+ end
+
+ def == other # :nodoc:
+ self.class === other
+ end
+
+ def pretty_print q # :nodoc:
+ q.text "[break]"
+ end
+
+end
+
View
14 lib/rdoc/markup/indented_paragraph.rb
@@ -29,5 +29,19 @@ def accept visitor
visitor.accept_indented_paragraph self
end
+ ##
+ # Joins the raw paragraph text and converts inline HardBreaks to the
+ # +hard_break+ text followed by the indent.
+
+ def text hard_break = nil
+ @parts.map do |part|
+ if RDoc::Markup::HardBreak === part then
+ '%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break
+ else
+ part
+ end
+ end.join
+ end
+
end
View
14 lib/rdoc/markup/paragraph.rb
@@ -10,5 +10,19 @@ def accept visitor
visitor.accept_paragraph self
end
+ ##
+ # Joins the raw paragraph text and converts inline HardBreaks to the
+ # +hard_break+ text.
+
+ def text hard_break = ''
+ @parts.map do |part|
+ if RDoc::Markup::HardBreak === part then
+ hard_break
+ else
+ part
+ end
+ end.join
+ end
+
end
View
10 lib/rdoc/markup/parser.rb
@@ -201,20 +201,20 @@ def build_paragraph margin
until @tokens.empty? do
type, data, column, = get
- if type == :TEXT && column == margin then
+ if type == :TEXT and column == margin then
paragraph << data
- if peek_token[0] == :BREAK then
- break
- end
+ break if peek_token.first == :BREAK
- skip :NEWLINE
+ data << ' ' if skip :NEWLINE
else
unget
break
end
end
+ paragraph.parts.last.sub!(/ \z/, '') # cleanup
+
p :paragraph_end => margin if @debug
paragraph
View
15 lib/rdoc/markup/to_html.rb
@@ -73,6 +73,7 @@ def initialize markup = nil
@in_list_entry = nil
@list = nil
@th = nil
+ @hard_break = "<br>\n"
# external links
@markup.add_special(/((link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w)/,
@@ -92,6 +93,13 @@ def initialize markup = nil
# These methods handle special markup added by RDoc::Markup#add_special.
##
+ # +special+ is a <code><br></code> that is not converted.
+
+ def handle_special_HARD_BREAK special
+ special.text
+ end
+
+ ##
# +special+ is a potential link. The following schemes are handled:
#
# <tt>mailto:</tt>::
@@ -179,9 +187,10 @@ def end_accepting
##
# Adds +paragraph+ to the output
- def accept_paragraph(paragraph)
+ def accept_paragraph paragraph
@res << "\n<p>"
- @res << wrap(to_html(paragraph.text))
+ text = paragraph.text @hard_break
+ @res << wrap(to_html(text))
@res << "</p>\n"
end
@@ -288,7 +297,7 @@ def accept_raw raw
# :section: Utilities
##
- # CGI escapes +text+
+ # CGI-escapes +text+
def convert_string(text)
CGI.escapeHTML text
View
4 lib/rdoc/markup/to_html_snippet.rb
@@ -68,7 +68,9 @@ def accept_heading heading
def accept_paragraph paragraph
para = @in_list_entry.last || "<p>"
- @res << "#{para}#{wrap to_html paragraph.text}\n"
+ text = paragraph.text @hard_break
+
+ @res << "#{para}#{wrap to_html text}\n"
add_paragraph
end
View
40 lib/rdoc/markup/to_joined_paragraph.rb
@@ -1,8 +1,10 @@
##
# Joins the parts of an RDoc::Markup::Paragraph into a single String.
#
-# This allows for easier testing of Markdown support as Paragraphs are split
-# up piecemeal to allow later replacing.
+# This allows for easier maintenance and testing of Markdown support.
+#
+# This formatter only works on Paragraph instances. Attempting to process
+# other markup syntax items will not work.
class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
@@ -13,7 +15,39 @@ def end_accepting
end
def accept_paragraph paragraph
- paragraph.parts.replace [paragraph.parts.join.rstrip]
+ parts = []
+ string = false
+
+ paragraph.parts.each do |part|
+ if String === part then
+ if string then
+ string << part
+ else
+ parts << part
+ string = part
+ end
+ else
+ parts << part
+ string = false
+ end
+ end
+
+ parts = parts.map do |part|
+ if String === part then
+ part.rstrip
+ else
+ part
+ end
+ end
+
+ # TODO use Enumerable#chunk when ruby 1.8 support is dropped
+ #parts = paragraph.parts.chunk do |part|
+ # String === part
+ #end.map do |string, chunk|
+ # string ? chunk.join.rstrip : chunk
+ #end.flatten
+
+ paragraph.parts.replace parts
end
alias accept_block_quote ignore
View
8 lib/rdoc/markup/to_rdoc.rb
@@ -57,6 +57,8 @@ def initialize markup = nil
@headings[4] = ['==== ', '']
@headings[5] = ['===== ', '']
@headings[6] = ['====== ', '']
+
+ @hard_break = "\n"
end
##
@@ -170,7 +172,8 @@ def accept_list_start list
# Adds +paragraph+ to the output
def accept_paragraph paragraph
- wrap attributes(paragraph.text)
+ text = paragraph.text @hard_break
+ wrap attributes text
end
##
@@ -178,7 +181,8 @@ def accept_paragraph paragraph
def accept_indented_paragraph paragraph
@indent += paragraph.indent
- wrap attributes(paragraph.text)
+ text = paragraph.text @hard_break
+ wrap attributes text
@indent -= paragraph.indent
end
View
14 lib/rdoc/test_case.rb
@@ -42,6 +42,13 @@ def setup
end
##
+ # Shortcut for RDoc::Markup::BlankLine.new
+
+ def blank_line
+ @RM::BlankLine.new
+ end
+
+ ##
# Shortcut for RDoc::Markup::BlockQuote.new with +contents+
def block *contents
@@ -64,6 +71,13 @@ def doc *contents
end
##
+ # Shortcut for RDoc::Markup::HardBreak.new
+
+ def hard_break
+ @RM::HardBreak.new
+ end
+
+ ##
# Shortcut for RDoc::Markup::Heading.new with +level+ and +text+
def head level, text
View
2  test/test_rdoc_markdown.rb
@@ -264,7 +264,7 @@ def test_parse_line_break
doc = parse "Some text \nwith extra lines"
expected = doc(
- para("Some text \nwith extra lines"))
+ para("Some text", hard_break, "with extra lines"))
assert_equal expected, doc
end
View
31 test/test_rdoc_markup_hard_break.rb
@@ -0,0 +1,31 @@
+require 'rdoc/test_case'
+
+class TestRDocMarkupHardBreak < RDoc::TestCase
+
+ def setup
+ super
+
+ @hb = RDoc::Markup::HardBreak.new
+ end
+
+ def test_accept
+ visitor = Object.new
+
+ def visitor.accept_hard_break(obj) @obj = obj end
+ def visitor.obj() @obj end
+
+ @hb.accept visitor
+
+ assert_same @hb, visitor.obj
+ end
+
+ def test_equals2
+ other = RDoc::Markup::HardBreak.new
+
+ assert_equal @hb, other
+
+ refute_equal @hb, Object.new
+ end
+
+end
+
View
14 test/test_rdoc_markup_indented_paragraph.rb
@@ -35,5 +35,19 @@ def test_equals2
refute_equal one, two
end
+ def test_text
+ paragraph = @IP.new(2, 'hello', ' world')
+
+ assert_equal 'hello world', paragraph.text
+ end
+
+ def test_text_break
+ paragraph = @IP.new(2, 'hello', hard_break, 'world')
+
+ assert_equal 'helloworld', paragraph.text
+
+ assert_equal "hello\n world", paragraph.text("\n")
+ end
+
end
View
16 test/test_rdoc_markup_paragraph.rb
@@ -11,7 +11,21 @@ def visitor.obj() @obj end
paragraph.accept visitor
- assert_equal paragraph, visitor.obj
+ assert_same paragraph, visitor.obj
+ end
+
+ def test_text
+ paragraph = para('hello', ' world')
+
+ assert_equal 'hello world', paragraph.text
+ end
+
+ def test_text_break
+ paragraph = para('hello', hard_break, 'world')
+
+ assert_equal 'helloworld', paragraph.text
+
+ assert_equal "hello\nworld", paragraph.text("\n")
end
end
View
50 test/test_rdoc_markup_parser.rb
@@ -146,13 +146,11 @@ def test_parse_bullet_multiline
STR
expected = [
- @RM::List.new(:BULLET, *[
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('l1', 'l1+')),
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('l2')),
- ]),
- ]
+ list(:BULLET,
+ item(nil,
+ para('l1 ', 'l1+')),
+ item(nil,
+ para('l2')))]
assert_equal expected, @RMP.parse(str).parts
end
@@ -189,16 +187,16 @@ def test_parse_bullet_indent_verbatim
STR
expected = [
- @RM::List.new(:BULLET, *[
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('l1'),
- @RM::List.new(:BULLET, *[
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('l1.1', 'text'),
- @RM::Verbatim.new("code\n", " code\n"),
- @RM::Paragraph.new('text'))])),
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('l2'))])]
+ list(:BULLET,
+ item(nil,
+ para('l1'),
+ list(:BULLET,
+ item(nil,
+ para('l1.1 ', 'text'),
+ verb("code\n", " code\n"),
+ para('text')))),
+ item(nil,
+ para('l2')))]
assert_equal expected, @RMP.parse(str).parts
end
@@ -361,11 +359,11 @@ def test_parse_label_multiline
STR
expected = [
- @RM::List.new(:LABEL, *[
- @RM::ListItem.new('cat',
- @RM::Paragraph.new('l1', 'continuation')),
- @RM::ListItem.new('dog',
- @RM::Paragraph.new('l2'))])]
+ list(:LABEL,
+ item('cat',
+ para('l1 ', 'continuation')),
+ item('dog',
+ para('l2')))]
assert_equal expected, @RMP.parse(str).parts
end
@@ -445,9 +443,9 @@ def test_parse_line_break
str = "now is\nthe time \nfor all"
expected = [
- @RM::Paragraph.new('now is', 'the time'),
- @RM::BlankLine.new,
- @RM::Paragraph.new('for all')]
+ para('now is ', 'the time'),
+ blank_line,
+ para('for all')]
assert_equal expected, @RMP.parse(str).parts
end
@@ -632,7 +630,7 @@ def test_parse_paragraph
def test_parse_paragraph_multiline
str = "now is the time\nfor all good men"
- expected = @RM::Paragraph.new 'now is the time', 'for all good men'
+ expected = @RM::Paragraph.new 'now is the time ', 'for all good men'
assert_equal [expected], @RMP.parse(str).parts
end
View
4 test/test_rdoc_markup_to_ansi.rb
@@ -246,6 +246,10 @@ def accept_paragraph_b
assert_equal "\e[0mreg \e[1mbold words\e[m reg\n", @to.end_accepting
end
+ def accept_paragraph_break
+ assert_equal "\e[0mhello\nworld\n", @to.end_accepting
+ end
+
def accept_paragraph_i
assert_equal "\e[0mreg \e[4mitalic words\e[m reg\n", @to.end_accepting
end
View
6 test/test_rdoc_markup_to_bs.rb
@@ -255,6 +255,12 @@ def accept_paragraph_b
@to.end_accepting
end
+ def accept_paragraph_break
+ skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars
+ assert_equal "hello\nworld\n",
+ @to.end_accepting
+ end
+
def accept_paragraph_i
skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars
assert_equal "reg _\bi_\bt_\ba_\bl_\bi_\bc_\b _\bw_\bo_\br_\bd_\bs reg\n",
View
4 test/test_rdoc_markup_to_html.rb
@@ -212,6 +212,10 @@ def accept_paragraph_b
assert_equal "\n<p>reg <strong>bold words</strong> reg</p>\n", @to.res.join
end
+ def accept_paragraph_break
+ assert_equal "\n<p>hello<br>\nworld</p>\n", @to.res.join
+ end
+
def accept_paragraph_i
assert_equal "\n<p>reg <em>italic words</em> reg</p>\n", @to.res.join
end
View
10 test/test_rdoc_markup_to_html_snippet.rb
@@ -235,6 +235,12 @@ def accept_paragraph_b
assert_equal 18, @to.characters
end
+ def accept_paragraph_break
+ assert_equal "<p>hello<br>\nworld\n", @to.res.join
+
+ assert_equal 15, @to.characters
+ end
+
def accept_paragraph_i
assert_equal "<p>reg <em>italic words</em> reg\n", @to.res.join
@@ -424,8 +430,8 @@ def test_convert_limit
actual = @to.convert rdoc
- assert_equal 111, @to.characters
assert_equal expected, actual
+ assert_equal 111, @to.characters, 'snippet character length'
end
def test_convert_limit_2
@@ -444,7 +450,7 @@ def test_convert_limit_2
actual = @to.convert rdoc
assert_equal expected, actual
- assert_equal 159, @to.characters
+ assert_equal 159, @to.characters, 'snippet character length'
end
def test_convert_limit_paragraphs
View
32 test/test_rdoc_markup_to_joined_paragraph.rb
@@ -0,0 +1,32 @@
+require 'rdoc/test_case'
+
+class TestRDocMarkupToJoinedParagraph < RDoc::TestCase
+
+ def setup
+ super
+
+ @to = RDoc::Markup::ToJoinedParagraph.new
+ end
+
+ def test_accept_paragraph
+ parsed = para('hello', ' ', 'world')
+
+ @to.accept_paragraph parsed
+
+ expected = para('hello world')
+
+ assert_equal expected, parsed
+ end
+
+ def test_accept_paragraph_break
+ parsed = para('hello', ' ', 'world', hard_break, 'everyone')
+
+ @to.accept_paragraph parsed
+
+ expected = para('hello world', hard_break, 'everyone')
+
+ assert_equal expected, parsed
+ end
+
+end
+
View
4 test/test_rdoc_markup_to_rdoc.rb
@@ -245,6 +245,10 @@ def accept_paragraph_b
assert_equal "reg <b>bold words</b> reg\n", @to.end_accepting
end
+ def accept_paragraph_break
+ assert_equal "hello\nworld\n", @to.end_accepting
+ end
+
def accept_paragraph_i
assert_equal "reg <em>italic words</em> reg\n", @to.end_accepting
end
View
1  test/test_rdoc_markup_to_table_of_contents.rb
@@ -75,6 +75,7 @@ def accept_heading_suppressed_crossref
alias accept_list_start_ualpha empty
alias accept_paragraph empty
alias accept_paragraph_b empty
+ alias accept_paragraph_break empty
alias accept_paragraph_i empty
alias accept_paragraph_plus empty
alias accept_paragraph_star empty
View
4 test/test_rdoc_markup_to_tt_only.rb
@@ -122,6 +122,10 @@ def accept_paragraph
assert_empty @to.end_accepting
end
+ def accept_paragraph_break
+ assert_empty @to.end_accepting
+ end
+
def accept_raw
assert_empty @to.end_accepting
end
View
4 test/test_rdoc_text.rb
@@ -471,6 +471,10 @@ def test_to_html_backslash
assert_equal 'S', to_html('\\S')
end
+ def test_to_html_br
+ assert_equal '<br>', to_html('<br>')
+ end
+
def test_to_html_copyright
assert_equal '©', to_html('(c)')
end
Please sign in to comment.
Something went wrong with that request. Please try again.