Mercurial > hg
changeset 15261:e2df5b866d22
minirst: add basic HTML formatting support
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 15 Oct 2011 00:39:01 -0500 |
parents | be2c67a8bf88 |
children | e8076af14498 |
files | mercurial/minirst.py tests/test-minirst.py tests/test-minirst.py.out |
diffstat | 3 files changed, 448 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- 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> +---------------------------------------------------------------------- +