Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/moin/converters/_tests/test_rst_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ def test_field_list(self, input, output):
"Abra example_ arba\n\n.. _example:\n\ntext",
'<page><body><p>Abra <a xlink:href="wiki.local:#example">example</a> arba</p><span id="example" /><p>text</p></body></page>',
),
(
"A reference_ with no matching target links to a local Wiki item.",
'<page><body><p>A <a xlink:href="wiki.local:reference">reference</a> with no matching target links to a local Wiki item.</p></body></page>',
),
(
"`Whitespace is\nnormalized & Case is KEPT.`_",
'<page><body><p><a xlink:href="wiki.local:Whitespace%20is%20normalized%20&amp;%20Case%20is%20KEPT.">Whitespace is\nnormalized &amp; Case is KEPT.</a></p></body></page>',
),
(
"http://www.python.org/",
'<page><body><p><a xlink:href="http://www.python.org/">http://www.python.org/</a></p></body></page>',
Expand Down
52 changes: 50 additions & 2 deletions src/moin/converters/rst_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import re

import docutils
from docutils import nodes, utils, writers, core
from docutils import core, nodes, transforms, utils, writers
from docutils.nodes import reference, literal_block
from docutils.parsers.rst import directives, roles

Expand All @@ -31,6 +31,7 @@
from moin.utils.iri import Iri
from moin.utils.tree import html, moin_page, xlink, xinclude
from moin.utils.mime import Type, type_moin_document
from moin.wikiutil import normalize_pagename

from . import default_registry
from ._util import allowed_uri_scheme, decode_data, normalize_split_text
Expand Down Expand Up @@ -781,7 +782,54 @@ def walkabout(node, visitor):
return stop


class Parser(docutils.parsers.rst.Parser):
"""reStructuredText parser for the MoinMoin wiki.

Registers a "transform__" for hyperlink references
without matching target__.

__ https://docutils.sourceforge.io/docs/api/transforms.html
"""

config_section = "MoinMoin parser"
config_section_dependencies = ("parsers", "restructuredtext parser")

def get_transforms(self):
"""Add WikiReferences to the registered transforms."""
return super().get_transforms() + [WikiReferences]


class WikiReferences(transforms.Transform):
"""Resolve references without matching target as local wiki references.

Set the "refuri" attribute to refer to a local wiki item.
The value is derived from the node's text content with
`moin.wikiutil.normalize_pagename()`.

Cf. https://docutils.sourceforge.io/docs/api/transforms.html#docinfo.
"""

default_priority = 775
# Apply between `InternalTargets` (660) and `DanglingReferences` (850)

def apply(self) -> None:
for node in self.document.findall(nodes.reference):
# Skip resolved references, unresolvable references, and references with matching target:
if node.resolved or "refname" not in node or self.document.nameids.get(node["refname"]):
continue
# Get the name from the link text (the "refname" attribute is lowercased).
wikiname = normalize_pagename(node.astext(), None) # second arg is ignored
# Skip references whose "refname" attribute differs from the wikiname (exept for case):
if normalize_pagename(node["refname"], None) != wikiname.lower():
continue
# Resolve the reference:
node["refuri"] = wikiname
del node["refname"]
node.resolved = True


class Writer(writers.Writer):
# Ignored! In moin 2.0, the conversion does not use a Writer component.

supported = ("moin-x-document",)
config_section = "MoinMoin writer"
Expand Down Expand Up @@ -924,7 +972,7 @@ def __call__(self, data, contenttype=None, arguments=None):
while True:
input = "\n".join(input)
try:
docutils_tree = core.publish_doctree(source=input)
docutils_tree = core.publish_doctree(source=input, source_path="rST input", parser=Parser())
except utils.SystemMessage as inst:
string_numb = re.match(
re.compile(r"<string>:([0-9]*):\s*\(.*?\)\s*(.*)", re.X | re.U | re.M | re.S), str(inst)
Expand Down