# HG changeset patch # User Matt Mackall # Date 2011-10-15 05:39:01 # Node ID e2df5b866d22f01c11e091df427c8dd62599a253 # Parent be2c67a8bf886601671b6103a9b405ebd7d4b030 minirst: add basic HTML formatting support diff --git a/mercurial/minirst.py b/mercurial/minirst.py --- a/mercurial/minirst.py +++ b/mercurial/minirst.py @@ -497,6 +497,93 @@ def formatblock(block, width): 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('

\n%s %s\n

\n' % (admonition, text)) + elif btype == 'paragraph': + out.append('

\n%s\n

\n' % '\n'.join(lines)) + elif btype == 'margin': + pass + elif btype == 'literal': + out.append('
\n%s\n
\n' % '\n'.join(lines)) + elif btype == 'section': + i = b['underline'] + if i not in headernest: + headernest += i + level = headernest.index(i) + 1 + out.append('%s\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('%s' % v) + else: + l.append('%s' % v) + t.append(' %s\n' % ''.join(l)) + out.append('\n%s
\n' % ''.join(t)) + elif btype == 'definition': + openlist('dl', level) + term = lines[0] + text = ' '.join(map(str.strip, lines[1:])) + out.append('
%s\n
%s\n' % (term, text)) + elif btype == 'bullet': + bullet, head = lines[0].split(' ', 1) + if bullet == '-': + openlist('ul', level) + else: + openlist('ol', level) + out.append('
  • %s\n' % ' '.join([head] + lines[1:])) + elif btype == 'field': + openlist('dl', level) + key = b['key'] + text = ' '.join(map(str.strip, lines)) + out.append('
    %s\n
    %s\n' % (key, text)) + elif btype == 'option': + openlist('dl', level) + opt = b['optstr'] + desc = ' '.join(map(str.strip, lines)) + out.append('
    %s\n
    %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('\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('\n' % start) + listnest.pop() + + return ''.join(out) + def parse(text, indent=0, keep=None): """Parse text into a list of blocks""" pruned = [] diff --git a/tests/test-minirst.py b/tests/test-minirst.py --- a/tests/test-minirst.py +++ b/tests/test-minirst.py @@ -3,8 +3,9 @@ from mercurial import minirst 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 @@ def debugformat(title, text, width, **kw else: print formatted print "-" * 70 + print html + print "-" * 70 print paragraphs = """ diff --git a/tests/test-minirst.py.out b/tests/test-minirst.py.out --- a/tests/test-minirst.py.out +++ b/tests/test-minirst.py.out @@ -8,6 +8,19 @@ This is some text in the first paragraph The third and final paragraph. ---------------------------------------------------------------------- +

    +This is some text in the first paragraph. +

    +

    +A small indented paragraph. +It is followed by some lines +containing random whitespace. +

    +

    +The third and final paragraph. +

    + +---------------------------------------------------------------------- paragraphs formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -22,6 +35,19 @@ paragraph. The third and final paragraph. ---------------------------------------------------------------------- +

    +This is some text in the first paragraph. +

    +

    +A small indented paragraph. +It is followed by some lines +containing random whitespace. +

    +

    +The third and final paragraph. +

    + +---------------------------------------------------------------------- definitions formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -37,6 +63,16 @@ Another Term Definition. ---------------------------------------------------------------------- +
    +
    A Term +
    Definition. The indented lines make up the definition. +
    Another Term +
    Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces. +
    A Nested/Indented Term +
    Definition. +
    + +---------------------------------------------------------------------- definitions formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -57,6 +93,16 @@ Another Term Definition. ---------------------------------------------------------------------- +
    +
    A Term +
    Definition. The indented lines make up the definition. +
    Another Term +
    Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces. +
    A Nested/Indented Term +
    Definition. +
    + +---------------------------------------------------------------------- literals formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -78,6 +124,31 @@ space-double-colon. with '::' disappears in the final output. ---------------------------------------------------------------------- +

    +The fully minimized form is the most +convenient form: +

    +
    +Hello
    +  literal
    +    world
    +
    +

    +In the partially minimized form a paragraph +simply ends with space-double-colon. +

    +
    +////////////////////////////////////////
    +long un-wrapped line in a literal block
    +\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    +
    +
    +This literal block is started with '::',
    +  the so-called expanded form. The paragraph
    +    with '::' disappears in the final output.
    +
    + +---------------------------------------------------------------------- literals formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -101,6 +172,31 @@ with space-double-colon. with '::' disappears in the final output. ---------------------------------------------------------------------- +

    +The fully minimized form is the most +convenient form: +

    +
    +Hello
    +  literal
    +    world
    +
    +

    +In the partially minimized form a paragraph +simply ends with space-double-colon. +

    +
    +////////////////////////////////////////
    +long un-wrapped line in a literal block
    +\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    +
    +
    +This literal block is started with '::',
    +  the so-called expanded form. The paragraph
    +    with '::' disappears in the final output.
    +
    + +---------------------------------------------------------------------- lists formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -137,6 +233,49 @@ This is the first line. The line continu This is the second line. ---------------------------------------------------------------------- +
      +
    • This is the first list item. +

      +Second paragraph in the first list item. +

      +
    • List items need not be separated by a blank line. +
    • And will be rendered without one in any case. +
    +

    +We can have indented lists: +

    +
      +
    • This is an indented list item +
    • Another indented list item: +
      +- A literal block in the middle
      +      of an indented list.
      +
      +
      +(The above is not a list item since we are in the literal block.)
      +
      +
    +
    +Literal block with no indentation (apart from
    +the two spaces added to all literal blocks).
    +
    +
      +
    1. This is an enumerated list (first item). +
    2. Continuing with the second item. +
    3. foo +
    4. bar +
    5. Another +
    6. List +
    +

    +Line blocks are also a form of list: +

    +
      +
    1. This is the first line. The line continues here. +
    2. This is the second line. +
    + +---------------------------------------------------------------------- lists formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -182,6 +321,49 @@ line continues here. This is the second line. ---------------------------------------------------------------------- +
      +
    • This is the first list item. +

      +Second paragraph in the first list item. +

      +
    • List items need not be separated by a blank line. +
    • And will be rendered without one in any case. +
    +

    +We can have indented lists: +

    +
      +
    • This is an indented list item +
    • Another indented list item: +
      +- A literal block in the middle
      +      of an indented list.
      +
      +
      +(The above is not a list item since we are in the literal block.)
      +
      +
    +
    +Literal block with no indentation (apart from
    +the two spaces added to all literal blocks).
    +
    +
      +
    1. This is an enumerated list (first item). +
    2. Continuing with the second item. +
    3. foo +
    4. bar +
    5. Another +
    6. List +
    +

    +Line blocks are also a form of list: +

    +
      +
    1. This is the first line. The line continues here. +
    2. This is the second line. +
    + +---------------------------------------------------------------------- options formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -210,6 +392,37 @@ paragraph: --foo bar baz ---------------------------------------------------------------------- +

    +There is support for simple option lists, +but only with long options: +

    +
    +
    -X --exclude filter +
    an option with a short and long option with an argument +
    -I --include +
    an option with both a short option and a long option +
    --all +
    Output all. +
    --both +
    Output both (this description is quite long). +
    --long +
    Output all day long. +
    --par +
    This option has two paragraphs in its description. This is the first. +

    +This is the second. Blank lines may be omitted between +options (as above) or left in (as here). +

    +
    +

    +The next paragraph looks like an option list, but lacks the two-space +marker after the option. It is treated as a normal paragraph: +

    +

    +--foo bar baz +

    + +---------------------------------------------------------------------- options formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -283,6 +496,37 @@ normal paragraph: --foo bar baz ---------------------------------------------------------------------- +

    +There is support for simple option lists, +but only with long options: +

    +
    +
    -X --exclude filter +
    an option with a short and long option with an argument +
    -I --include +
    an option with both a short option and a long option +
    --all +
    Output all. +
    --both +
    Output both (this description is quite long). +
    --long +
    Output all day long. +
    --par +
    This option has two paragraphs in its description. This is the first. +

    +This is the second. Blank lines may be omitted between +options (as above) or left in (as here). +

    +
    +

    +The next paragraph looks like an option list, but lacks the two-space +marker after the option. It is treated as a normal paragraph: +

    +

    +--foo bar baz +

    + +---------------------------------------------------------------------- fields formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -298,6 +542,23 @@ much too large This key is big enough to get its own line. ---------------------------------------------------------------------- +
    +
    a +
    First item. +
    ab +
    Second item. Indentation and wrapping is handled automatically. +
    +

    +Next list: +

    +
    +
    small +
    The larger key below triggers full indentation here. +
    much too large +
    This key is big enough to get its own line. +
    + +---------------------------------------------------------------------- fields formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -318,12 +579,34 @@ much too large own line. ---------------------------------------------------------------------- +
    +
    a +
    First item. +
    ab +
    Second item. Indentation and wrapping is handled automatically. +
    +

    +Next list: +

    +
    +
    small +
    The larger key below triggers full indentation here. +
    much too large +
    This key is big enough to get its own line. +
    + +---------------------------------------------------------------------- containers (normal) formatted to fit within 60 characters: ---------------------------------------------------------------------- Normal output. ---------------------------------------------------------------------- +

    +Normal output. +

    + +---------------------------------------------------------------------- containers (verbose) formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -334,6 +617,14 @@ Verbose output. ---------------------------------------------------------------------- ['debug', 'debug'] ---------------------------------------------------------------------- +

    +Normal output. +

    +

    +Verbose output. +

    + +---------------------------------------------------------------------- containers (debug) formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -344,6 +635,14 @@ Initial debug output. ---------------------------------------------------------------------- ['verbose'] ---------------------------------------------------------------------- +

    +Normal output. +

    +

    +Initial debug output. +

    + +---------------------------------------------------------------------- containers (verbose debug) formatted to fit within 60 characters: ---------------------------------------------------------------------- @@ -358,12 +657,31 @@ Debug output. ---------------------------------------------------------------------- [] ---------------------------------------------------------------------- +

    +Normal output. +

    +

    +Initial debug output. +

    +

    +Verbose output. +

    +

    +Debug output. +

    + +---------------------------------------------------------------------- roles formatted to fit within 60 characters: ---------------------------------------------------------------------- Please see "hg add". ---------------------------------------------------------------------- +

    +Please see "hg add". +

    + +---------------------------------------------------------------------- sections formatted to fit within 20 characters: ---------------------------------------------------------------------- @@ -380,6 +698,12 @@ Markup: "foo" and "hg help" --------------------------- ---------------------------------------------------------------------- +

    Title

    +

    Section

    +

    Subsection

    +

    Markup: "foo" and "hg help"

    + +---------------------------------------------------------------------- admonitions formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -397,6 +721,21 @@ Note: This is danger ---------------------------------------------------------------------- +

    +Note: This is a note +

    +
      +
    • Bullet 1 +
    • Bullet 2 +
    +

    +Warning! This is a warning Second input line of warning +

    +

    +!Danger! This is danger +

    + +---------------------------------------------------------------------- comments formatted to fit within 30 characters: ---------------------------------------------------------------------- @@ -407,6 +746,17 @@ Some text. Empty comment above ---------------------------------------------------------------------- +

    +Some text. +

    +

    +Some indented text. +

    +

    +Empty comment above +

    + +---------------------------------------------------------------------- === === ======================================== a b c @@ -425,4 +775,11 @@ table formatted to fit within 30 charact man ---------------------------------------------------------------------- + + + + +
    abc
    123
    foobarbaz this list is very very very long man
    +---------------------------------------------------------------------- +