diff --git a/src/moin/converters/_tests/test_rst_in.py b/src/moin/converters/_tests/test_rst_in.py index cf8fdc39d..f76c1d343 100644 --- a/src/moin/converters/_tests/test_rst_in.py +++ b/src/moin/converters/_tests/test_rst_in.py @@ -37,6 +37,14 @@ def setup_class(self): ("**Text**", "

Text

"), ("*Text*", "

Text

"), ("``Text``", "

Text

"), + ( # custom role using a CSS class + ".. role:: orange\n\n:orange:`colourful` text", + '

colourful text

', + ), + ( # special custom roles for and + ".. role:: del\n.. role:: ins\n\n" ":del:`deleted` text :ins:`inserted` text", + "

deleted text inserted text

", + ), ("a _`Link`", '

a Link

'), ( "`Text `_", @@ -57,9 +65,10 @@ def test_base(self, input, output): data = [ ( "1. a\n b\n c\n\n2. b\n\n d", - """

a -b -c

b

d

""", + '' + "

a\nb\nc

" + "

b

d

" + "
", ), ( "1. a\n2. b\n\nA. c\n\na. A\n\n 1. B\n\n 2. C\n\n", @@ -73,12 +82,11 @@ def test_base(self, input, output): "what\n def\n\nhow\n to", "what

def

how

to

", ), - # starting an ordered list with a value other than 1 generates an error + # nested in a block-quote and starting with a value other than 1 ( " 3. A\n #. B", - '

A

' + '

A

' "

B

" - '

Enumerated list start value not ordinal-1: "3" (ordinal 3)

' "
", ), ] @@ -353,19 +361,45 @@ def test_table(self, input, output): self.do(input, output) data = [ + # bibliographic data (visible meta-data) ( ":Author: Test\n:Version: $Revision: 1.17 $\n:Copyright: c\n:Test: t", "Author:TestVersion:1.17Copyright:cTest:

t

", ), - ( - """ -.. note:: - :name: note-id - - An admonition of type "note" -""", - '

An admonition of type "note"

', - ), + # admonitions (hint, info, warning, error, ...) + ( + ".. note::\n" " :name: note-id\n\n" ' An admonition of type "note"', + '' + '

An admonition of type "note"

', + ), + # use an attention for a generic admonition + ( + ".. admonition:: Generic Admonition\n\n" " Be alert!", + '' + 'Generic Admonition' + "

Be alert!

", + ), + # Moin uses admonitions also for system messages + ( + "Unbalanced *inline markup.", + '

Unbalanced *inline markup.

' + '' + '

System Message: WARNING/2 (rST input line 1) ' + 'backlink

' + "

Inline emphasis start-string without end-string.

" + "
", + ), + # TODO: this currently fails because the parsing error is not cleared. + # ( + # "Sections must not be nested in body elements.\n\n" + # " not allowed\n" + # " -----------\n", + # "

Sections must not be nested in body elements.

" + # '

System Message: ERROR/3 (rST input line 4)

' + # "

Unexpected section title.

" + # "not allowed\n-----------" + # "
" + # ) ] @pytest.mark.parametrize("input,output", data) diff --git a/src/moin/converters/rst_in.py b/src/moin/converters/rst_in.py index 3f6d8f1a2..7530daa1a 100644 --- a/src/moin/converters/rst_in.py +++ b/src/moin/converters/rst_in.py @@ -314,6 +314,9 @@ def visit_enumerated_list(self, node): type = enum_style.get(node["enumtype"], None) if type: new_node.set(moin_page.list_style_type, type) + startvalue = node.get("start", 1) + if startvalue > 1: + new_node.set(moin_page.list_start, str(startvalue)) self.open_moin_page_node(new_node, node) def depart_enumerated_list(self, node): @@ -434,10 +437,21 @@ def depart_image(self, node): self.close_moin_page_node() def visit_inline(self, node): - pass + classes = node["classes"] + moin_node = moin_page.span + attrib = {} + if "ins" in classes: + moin_node = moin_page.ins + classes.remove("ins") + if "del" in classes: + moin_node = moin_page.del_ + classes.remove("del") + if classes: + attrib[html.class_] = " ".join(classes) + self.open_moin_page_node(moin_node(attrib=attrib)) def depart_inline(self, node): - pass + self.close_moin_page_node() def visit_label(self, node): if self.status[-1] == "footnote": @@ -529,6 +543,7 @@ def visit_paragraph(self, node): footnote_node = self.footnotes.get(self.footnote_lable, None) if footnote_node: # TODO: `node.astext()` ignores all markup! + # "moin" footnotes support inline markup footnote_node.append(node.astext()) raise nodes.SkipNode self.open_moin_page_node(moin_page.p(), node) @@ -538,10 +553,15 @@ def depart_paragraph(self, node): self.close_moin_page_node() def visit_problematic(self, node): - pass + if node.hasattr("refid"): + refuri = f"#{node['refid']}" + attrib = {xlink.href: refuri, html.class_: "red"} + self.open_moin_page_node(moin_page.a(attrib=attrib), node) + else: + self.open_moin_page_node(moin_page.span(attrib={html.class_: "red"})) def depart_problematic(self, node): - pass + self.close_moin_page_node() def visit_reference(self, node): refuri = node.get("refuri", "") @@ -584,6 +604,7 @@ def visit_reference(self, node): return if not allowed_uri_scheme(refuri): + # TODO: prepend "wiki.local" as in "moin_in"? self.visit_error(node) return @@ -678,9 +699,25 @@ def depart_superscript(self, node): self.close_moin_page_node() def visit_system_message(self, node): - # we have encountered a parsing error, insert an error message - # TODO: also show error level and line number. - self.visit_admonition(node, "error") + # an element reporting a parsing issue (DEBUG, INFO, WARNING, ERROR, or SEVERE) + # TODO: handle node['backrefs'] to element. + if node.get("level", 4) < 3: + self.visit_admonition(node, "caution") + else: + self.visit_admonition(node, "error") + self.open_moin_page_node(moin_page.p()) + self.open_moin_page_node(moin_page.strong(attrib={html.class_: "title"})) + title = f"{node['type']}/{node['level']}" + self.current_node.append(f"System Message: {title}") + self.close_moin_page_node() # + if node.hasattr("line"): + self.current_node.append(f" ({node['source']} line {node['line']}) ") + if node.get("backrefs", []): + backrefuri = f"#{node['backrefs'][0]}" + self.open_moin_page_node(moin_page.a(attrib={xlink.href: backrefuri}), node) + self.current_node.append("backlink") + self.close_moin_page_node() # + self.close_moin_page_node() #

def depart_system_message(self, node): self.depart_admonition(node) @@ -823,6 +860,8 @@ class Parser(docutils.parsers.rst.Parser): Registers a "transform__" for hyperlink references without matching target__. + Also register the "transforms" that are added by default for a Docutils writer. + __ https://docutils.sourceforge.io/docs/api/transforms.html __ https://docutils.sourceforge.io/docs/ref/doctree.html#target """ @@ -832,7 +871,13 @@ class Parser(docutils.parsers.rst.Parser): def get_transforms(self): """Add WikiReferences to the registered transforms.""" - return super().get_transforms() + [WikiReferences] + moin_parser_transforms = [ + WikiReferences, + transforms.universal.StripClassesAndElements, + transforms.universal.Messages, + transforms.universal.FilterMessages, + ] + return super().get_transforms() + moin_parser_transforms class WikiReferences(transforms.Transform):