1.1 --- a/moinformat/links/__init__.py Mon Aug 13 15:53:53 2018 +0200
1.2 +++ b/moinformat/links/__init__.py Mon Aug 13 17:10:07 2018 +0200
1.3 @@ -32,17 +32,17 @@
1.4
1.5 return linkers.get(name)
1.6
1.7 -def make_linker(name, pagename, mapping=None):
1.8 +def make_linker(name, pagename, mapping=None, parameters=None):
1.9
1.10 """
1.11 Return a linking scheme handler with the given 'name' and using the given
1.12 - 'pagename' and interwiki 'mapping'.
1.13 + 'pagename', interwiki 'mapping' and 'parameters'.
1.14 """
1.15
1.16 linker_cls = get_linker(name)
1.17 if not linker_cls:
1.18 return None
1.19
1.20 - return linker_cls(pagename, mapping)
1.21 + return linker_cls(pagename, mapping, parameters)
1.22
1.23 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/moinformat/links/common.py Mon Aug 13 15:53:53 2018 +0200
2.2 +++ b/moinformat/links/common.py Mon Aug 13 17:10:07 2018 +0200
2.3 @@ -23,14 +23,64 @@
2.4
2.5 "Translate Moin links into other forms."
2.6
2.7 - def __init__(self, pagename, mapping=None):
2.8 + def __init__(self, pagename, mapping=None, parameters=None):
2.9
2.10 """
2.11 - Initialise the linker with the 'pagename' and optional interwiki
2.12 - 'mapping'.
2.13 + Initialise the linker with the 'pagename', optional interwiki 'mapping'
2.14 + and 'parameters'.
2.15 """
2.16
2.17 self.pagename = pagename
2.18 self.mapping = mapping or {}
2.19 + self.parameters = parameters or {}
2.20 +
2.21 + self.root_pagename = self.parameters.get("root_pagename") or "FrontPage"
2.22 +
2.23 +def resolve(path, pagename, root_pagename):
2.24 +
2.25 + "Resolve 'path' relative to 'pagename'."
2.26 +
2.27 + # Omit the root pagename from the resolved path components.
2.28 +
2.29 + if pagename == root_pagename:
2.30 + parts = []
2.31 + else:
2.32 + parts = pagename.rstrip("/").split("/")
2.33 +
2.34 + t = path.split("/")
2.35 +
2.36 + first = True
2.37 +
2.38 + for p in t:
2.39 +
2.40 + # Handle replacement of the page with another.
2.41 +
2.42 + if p == ".":
2.43 + parts = []
2.44 +
2.45 + # Handle ascent in the page hierarchy.
2.46 +
2.47 + elif p == "..":
2.48 + if parts:
2.49 + parts.pop()
2.50 +
2.51 + # Any non-navigation element replaces the path at the start.
2.52 + # Otherwise, the path is extended.
2.53 + # Omit the root pagename from the resolved path components if it would
2.54 + # appear at the start.
2.55 +
2.56 + elif p:
2.57 + if first:
2.58 + if p == root_pagename:
2.59 + parts = []
2.60 + else:
2.61 + parts = [p]
2.62 + else:
2.63 + if parts or p != root_pagename:
2.64 + parts.append(p)
2.65 +
2.66 + first = False
2.67 +
2.68 + return "/".join(parts)
2.69
2.70 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/moinformat/links/html.py Mon Aug 13 15:53:53 2018 +0200
3.2 +++ b/moinformat/links/html.py Mon Aug 13 17:10:07 2018 +0200
3.3 @@ -19,7 +19,7 @@
3.4 this program. If not, see <http://www.gnu.org/licenses/>.
3.5 """
3.6
3.7 -from moinformat.links.common import Linker
3.8 +from moinformat.links.common import Linker, resolve
3.9 from urllib import quote, quote_plus
3.10 from urlparse import urlparse
3.11
3.12 @@ -33,7 +33,14 @@
3.13
3.14 "Return a relative link to the top level."
3.15
3.16 - levels = self.pagename.count("/")
3.17 + # The root page is at the top level already.
3.18 +
3.19 + if self.pagename == self.root_pagename:
3.20 + return ""
3.21 +
3.22 + # Siblings of the root page are actually one level below.
3.23 +
3.24 + levels = self.pagename.count("/") + 1
3.25 return "/".join([".."] * levels)
3.26
3.27 def is_url(self, target):
3.28 @@ -65,13 +72,13 @@
3.29
3.30 # Sub-pages. Remove the leading slash for the label.
3.31
3.32 - elif target.startswith("/"):
3.33 - return self.translate_subpage(target), target.lstrip("/")
3.34 + if target.startswith("/"):
3.35 + return self.translate_pagename(target), target.lstrip("/")
3.36
3.37 # Sibling (of ancestor) pages.
3.38
3.39 if target.startswith("../"):
3.40 - return self.translate_relative(target), None
3.41 + return self.translate_pagename(target), None
3.42
3.43 # Attachment or interwiki link.
3.44
3.45 @@ -87,8 +94,30 @@
3.46
3.47 # Top-level pages.
3.48
3.49 + return self.translate_pagename(target), None
3.50 +
3.51 + def translate_pagename(self, target):
3.52 +
3.53 + "Translate the pagename in 'target'."
3.54 +
3.55 + # Obtain the target pagename and the fragment.
3.56 + # Split the pagename into path components.
3.57 +
3.58 + t = target.split("#", 1)
3.59 + p = t[0].rstrip("/").split("/")
3.60 +
3.61 + # Determine the actual pagename referenced.
3.62 + # Replace the root pagename if it appears.
3.63 +
3.64 + resolved = resolve(t[0], self.pagename, self.root_pagename)
3.65 +
3.66 + # Rewrite the target using a relative link to the top level and then the
3.67 + # resolved pagename.
3.68 +
3.69 top_level = self.get_top_level()
3.70 - return self.quote("%s%s" % (top_level and "%s/" % top_level or "", target)), None
3.71 + t[0] = "%s%s" % (top_level and "%s/" % top_level or "", resolved)
3.72 +
3.73 + return self.quote("#".join(t))
3.74
3.75 def translate_qualified_link(self, target):
3.76
3.77 @@ -132,18 +161,6 @@
3.78
3.79 return "%s%s" % (self.normalise(url), self.quote(target))
3.80
3.81 - def translate_relative(self, target):
3.82 -
3.83 - "Return a translation of the given relative 'target'."
3.84 -
3.85 - return self.quote(target)
3.86 -
3.87 - def translate_subpage(self, target):
3.88 -
3.89 - "Return a translation of the given subpage 'target'."
3.90 -
3.91 - return self.quote(".%s" % target)
3.92 -
3.93 # Path encoding.
3.94
3.95 def quote(self, s):