--- a/mercurial/minirst.py Fri Oct 14 15:40:50 2011 -0500
+++ b/mercurial/minirst.py Sat Oct 15 00:39:01 2011 -0500
@@ -497,6 +497,93 @@
initindent=indent,
hangindent=subindent) + '\n'
+def formathtml(blocks):
+ """Format RST blocks as HTML"""
+
+ out = []
+ headernest = ''
+ listnest = []
+
+ def openlist(start, level):
+ if not listnest or listnest[-1][0] != start:
+ listnest.append((start, level))
+ out.append('<%s>\n' % start)
+
+ blocks = [b for b in blocks if b['type'] != 'margin']
+
+ for pos, b in enumerate(blocks):
+ btype = b['type']
+ level = b['indent']
+ lines = b['lines']
+
+ if btype == 'admonition':
+ admonition = _admonitiontitles[b['admonitiontitle']]
+ text = ' '.join(map(str.strip, lines))
+ out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
+ elif btype == 'paragraph':
+ out.append('<p>\n%s\n</p>\n' % '\n'.join(lines))
+ elif btype == 'margin':
+ pass
+ elif btype == 'literal':
+ out.append('<pre>\n%s\n</pre>\n' % '\n'.join(lines))
+ elif btype == 'section':
+ i = b['underline']
+ if i not in headernest:
+ headernest += i
+ level = headernest.index(i) + 1
+ out.append('<h%d>%s</h%d>\n' % (level, lines[0], level))
+ elif btype == 'table':
+ table = b['table']
+ t = []
+ for row in table:
+ l = []
+ for v in zip(row):
+ if not t:
+ l.append('<th>%s</th>' % v)
+ else:
+ l.append('<td>%s</td>' % v)
+ t.append(' <tr>%s</tr>\n' % ''.join(l))
+ out.append('<table>\n%s</table>\n' % ''.join(t))
+ elif btype == 'definition':
+ openlist('dl', level)
+ term = lines[0]
+ text = ' '.join(map(str.strip, lines[1:]))
+ out.append(' <dt>%s\n <dd>%s\n' % (term, text))
+ elif btype == 'bullet':
+ bullet, head = lines[0].split(' ', 1)
+ if bullet == '-':
+ openlist('ul', level)
+ else:
+ openlist('ol', level)
+ out.append(' <li> %s\n' % ' '.join([head] + lines[1:]))
+ elif btype == 'field':
+ openlist('dl', level)
+ key = b['key']
+ text = ' '.join(map(str.strip, lines))
+ out.append(' <dt>%s\n <dd>%s\n' % (key, text))
+ elif btype == 'option':
+ openlist('dl', level)
+ opt = b['optstr']
+ desc = ' '.join(map(str.strip, lines))
+ out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
+
+ # close lists if indent level of next block is lower
+ if listnest:
+ start, level = listnest[-1]
+ if pos == len(blocks) - 1:
+ out.append('</%s>\n' % start)
+ listnest.pop()
+ else:
+ nb = blocks[pos + 1]
+ ni = nb['indent']
+ if (ni < level or
+ (ni == level and
+ nb['type'] not in 'definition bullet field option')):
+ out.append('</%s>\n' % start)
+ listnest.pop()
+
+ return ''.join(out)
+
def parse(text, indent=0, keep=None):
"""Parse text into a list of blocks"""
pruned = []
--- a/tests/test-minirst.py Fri Oct 14 15:40:50 2011 -0500
+++ b/tests/test-minirst.py Sat Oct 15 00:39:01 2011 -0500
@@ -3,8 +3,9 @@
def debugformat(title, text, width, **kwargs):
print "%s formatted to fit within %d characters:" % (title, width)
+ formatted = minirst.format(text, width, **kwargs)
+ html = minirst.formathtml(minirst.parse(text, **kwargs)[0])
print "-" * 70
- formatted = minirst.format(text, width, **kwargs)
if type(formatted) == tuple:
print formatted[0]
print "-" * 70
@@ -12,6 +13,8 @@
else:
print formatted
print "-" * 70
+ print html
+ print "-" * 70
print
paragraphs = """
--- a/tests/test-minirst.py.out Fri Oct 14 15:40:50 2011 -0500
+++ b/tests/test-minirst.py.out Sat Oct 15 00:39:01 2011 -0500
@@ -8,6 +8,19 @@
The third and final paragraph.
----------------------------------------------------------------------
+<p>
+This is some text in the first paragraph.
+</p>
+<p>
+A small indented paragraph.
+It is followed by some lines
+containing random whitespace.
+</p>
+<p>
+The third and final paragraph.
+</p>
+
+----------------------------------------------------------------------
paragraphs formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -22,6 +35,19 @@
The third and final paragraph.
----------------------------------------------------------------------
+<p>
+This is some text in the first paragraph.
+</p>
+<p>
+A small indented paragraph.
+It is followed by some lines
+containing random whitespace.
+</p>
+<p>
+The third and final paragraph.
+</p>
+
+----------------------------------------------------------------------
definitions formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -37,6 +63,16 @@
Definition.
----------------------------------------------------------------------
+<dl>
+ <dt>A Term
+ <dd>Definition. The indented lines make up the definition.
+ <dt>Another Term
+ <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
+ <dt>A Nested/Indented Term
+ <dd>Definition.
+</dl>
+
+----------------------------------------------------------------------
definitions formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -57,6 +93,16 @@
Definition.
----------------------------------------------------------------------
+<dl>
+ <dt>A Term
+ <dd>Definition. The indented lines make up the definition.
+ <dt>Another Term
+ <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
+ <dt>A Nested/Indented Term
+ <dd>Definition.
+</dl>
+
+----------------------------------------------------------------------
literals formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -78,6 +124,31 @@
with '::' disappears in the final output.
----------------------------------------------------------------------
+<p>
+The fully minimized form is the most
+convenient form:
+</p>
+<pre>
+Hello
+ literal
+ world
+</pre>
+<p>
+In the partially minimized form a paragraph
+simply ends with space-double-colon.
+</p>
+<pre>
+////////////////////////////////////////
+long un-wrapped line in a literal block
+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+</pre>
+<pre>
+This literal block is started with '::',
+ the so-called expanded form. The paragraph
+ with '::' disappears in the final output.
+</pre>
+
+----------------------------------------------------------------------
literals formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -101,6 +172,31 @@
with '::' disappears in the final output.
----------------------------------------------------------------------
+<p>
+The fully minimized form is the most
+convenient form:
+</p>
+<pre>
+Hello
+ literal
+ world
+</pre>
+<p>
+In the partially minimized form a paragraph
+simply ends with space-double-colon.
+</p>
+<pre>
+////////////////////////////////////////
+long un-wrapped line in a literal block
+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+</pre>
+<pre>
+This literal block is started with '::',
+ the so-called expanded form. The paragraph
+ with '::' disappears in the final output.
+</pre>
+
+----------------------------------------------------------------------
lists formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -137,6 +233,49 @@
This is the second line.
----------------------------------------------------------------------
+<ul>
+ <li> This is the first list item.
+<p>
+Second paragraph in the first list item.
+</p>
+ <li> List items need not be separated by a blank line.
+ <li> And will be rendered without one in any case.
+</ul>
+<p>
+We can have indented lists:
+</p>
+<ul>
+ <li> This is an indented list item
+ <li> Another indented list item:
+<pre>
+- A literal block in the middle
+ of an indented list.
+</pre>
+<pre>
+(The above is not a list item since we are in the literal block.)
+</pre>
+</ul>
+<pre>
+Literal block with no indentation (apart from
+the two spaces added to all literal blocks).
+</pre>
+<ol>
+ <li> This is an enumerated list (first item).
+ <li> Continuing with the second item.
+ <li> foo
+ <li> bar
+ <li> Another
+ <li> List
+</ol>
+<p>
+Line blocks are also a form of list:
+</p>
+<ol>
+ <li> This is the first line. The line continues here.
+ <li> This is the second line.
+</ol>
+
+----------------------------------------------------------------------
lists formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -182,6 +321,49 @@
This is the second line.
----------------------------------------------------------------------
+<ul>
+ <li> This is the first list item.
+<p>
+Second paragraph in the first list item.
+</p>
+ <li> List items need not be separated by a blank line.
+ <li> And will be rendered without one in any case.
+</ul>
+<p>
+We can have indented lists:
+</p>
+<ul>
+ <li> This is an indented list item
+ <li> Another indented list item:
+<pre>
+- A literal block in the middle
+ of an indented list.
+</pre>
+<pre>
+(The above is not a list item since we are in the literal block.)
+</pre>
+</ul>
+<pre>
+Literal block with no indentation (apart from
+the two spaces added to all literal blocks).
+</pre>
+<ol>
+ <li> This is an enumerated list (first item).
+ <li> Continuing with the second item.
+ <li> foo
+ <li> bar
+ <li> Another
+ <li> List
+</ol>
+<p>
+Line blocks are also a form of list:
+</p>
+<ol>
+ <li> This is the first line. The line continues here.
+ <li> This is the second line.
+</ol>
+
+----------------------------------------------------------------------
options formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -210,6 +392,37 @@
--foo bar baz
----------------------------------------------------------------------
+<p>
+There is support for simple option lists,
+but only with long options:
+</p>
+<dl>
+ <dt>-X --exclude filter
+ <dd>an option with a short and long option with an argument
+ <dt>-I --include
+ <dd>an option with both a short option and a long option
+ <dt> --all
+ <dd>Output all.
+ <dt> --both
+ <dd>Output both (this description is quite long).
+ <dt> --long
+ <dd>Output all day long.
+ <dt> --par
+ <dd>This option has two paragraphs in its description. This is the first.
+<p>
+This is the second. Blank lines may be omitted between
+options (as above) or left in (as here).
+</p>
+</dl>
+<p>
+The next paragraph looks like an option list, but lacks the two-space
+marker after the option. It is treated as a normal paragraph:
+</p>
+<p>
+--foo bar baz
+</p>
+
+----------------------------------------------------------------------
options formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -283,6 +496,37 @@
--foo bar baz
----------------------------------------------------------------------
+<p>
+There is support for simple option lists,
+but only with long options:
+</p>
+<dl>
+ <dt>-X --exclude filter
+ <dd>an option with a short and long option with an argument
+ <dt>-I --include
+ <dd>an option with both a short option and a long option
+ <dt> --all
+ <dd>Output all.
+ <dt> --both
+ <dd>Output both (this description is quite long).
+ <dt> --long
+ <dd>Output all day long.
+ <dt> --par
+ <dd>This option has two paragraphs in its description. This is the first.
+<p>
+This is the second. Blank lines may be omitted between
+options (as above) or left in (as here).
+</p>
+</dl>
+<p>
+The next paragraph looks like an option list, but lacks the two-space
+marker after the option. It is treated as a normal paragraph:
+</p>
+<p>
+--foo bar baz
+</p>
+
+----------------------------------------------------------------------
fields formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -298,6 +542,23 @@
This key is big enough to get its own line.
----------------------------------------------------------------------
+<dl>
+ <dt>a
+ <dd>First item.
+ <dt>ab
+ <dd>Second item. Indentation and wrapping is handled automatically.
+</dl>
+<p>
+Next list:
+</p>
+<dl>
+ <dt>small
+ <dd>The larger key below triggers full indentation here.
+ <dt>much too large
+ <dd>This key is big enough to get its own line.
+</dl>
+
+----------------------------------------------------------------------
fields formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -318,12 +579,34 @@
own line.
----------------------------------------------------------------------
+<dl>
+ <dt>a
+ <dd>First item.
+ <dt>ab
+ <dd>Second item. Indentation and wrapping is handled automatically.
+</dl>
+<p>
+Next list:
+</p>
+<dl>
+ <dt>small
+ <dd>The larger key below triggers full indentation here.
+ <dt>much too large
+ <dd>This key is big enough to get its own line.
+</dl>
+
+----------------------------------------------------------------------
containers (normal) formatted to fit within 60 characters:
----------------------------------------------------------------------
Normal output.
----------------------------------------------------------------------
+<p>
+Normal output.
+</p>
+
+----------------------------------------------------------------------
containers (verbose) formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -334,6 +617,14 @@
----------------------------------------------------------------------
['debug', 'debug']
----------------------------------------------------------------------
+<p>
+Normal output.
+</p>
+<p>
+Verbose output.
+</p>
+
+----------------------------------------------------------------------
containers (debug) formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -344,6 +635,14 @@
----------------------------------------------------------------------
['verbose']
----------------------------------------------------------------------
+<p>
+Normal output.
+</p>
+<p>
+Initial debug output.
+</p>
+
+----------------------------------------------------------------------
containers (verbose debug) formatted to fit within 60 characters:
----------------------------------------------------------------------
@@ -358,12 +657,31 @@
----------------------------------------------------------------------
[]
----------------------------------------------------------------------
+<p>
+Normal output.
+</p>
+<p>
+Initial debug output.
+</p>
+<p>
+Verbose output.
+</p>
+<p>
+Debug output.
+</p>
+
+----------------------------------------------------------------------
roles formatted to fit within 60 characters:
----------------------------------------------------------------------
Please see "hg add".
----------------------------------------------------------------------
+<p>
+Please see "hg add".
+</p>
+
+----------------------------------------------------------------------
sections formatted to fit within 20 characters:
----------------------------------------------------------------------
@@ -380,6 +698,12 @@
---------------------------
----------------------------------------------------------------------
+<h1>Title</h1>
+<h2>Section</h2>
+<h3>Subsection</h3>
+<h2>Markup: "foo" and "hg help"</h2>
+
+----------------------------------------------------------------------
admonitions formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -397,6 +721,21 @@
This is danger
----------------------------------------------------------------------
+<p>
+<b>Note:</b> This is a note
+</p>
+<ul>
+ <li> Bullet 1
+ <li> Bullet 2
+</ul>
+<p>
+<b>Warning!</b> This is a warning Second input line of warning
+</p>
+<p>
+<b>!Danger!</b> This is danger
+</p>
+
+----------------------------------------------------------------------
comments formatted to fit within 30 characters:
----------------------------------------------------------------------
@@ -407,6 +746,17 @@
Empty comment above
----------------------------------------------------------------------
+<p>
+Some text.
+</p>
+<p>
+Some indented text.
+</p>
+<p>
+Empty comment above
+</p>
+
+----------------------------------------------------------------------
=== === ========================================
a b c
@@ -425,4 +775,11 @@
man
----------------------------------------------------------------------
+<table>
+ <tr><th>a</th><th>b</th><th>c</th></tr>
+ <tr><td>1</td><td>2</td><td>3</td></tr>
+ <tr><td>foo</td><td>bar</td><td>baz this list is very very very long man</td></tr>
+</table>
+----------------------------------------------------------------------
+