diff options
Diffstat (limited to 'filters/html-converters/md2html')
| -rwxr-xr-x | filters/html-converters/md2html | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/filters/html-converters/md2html b/filters/html-converters/md2html index 90021a7..79d4a17 100755 --- a/filters/html-converters/md2html +++ b/filters/html-converters/md2html @@ -358,17 +358,21 @@ html = markdown.markdown( "markdown.extensions.codehilite":{"css_class":"highlight"}}) # A README's relative paths point at repo content, but a browser resolves them -# against the page the readme is shown on (/<repo>/about/ or the summary page -# /<repo>/), not against the repo root — so they 404. cgit serves blobs only via -# its `plain`/`tree` commands, so rewrite relative references to absolute cgit -# URLs (absolute so it works both on the about page and the summary page): -# <img src> -> /<repo>/plain/<path>?h=<branch> (raw bytes for the browser) -# <a href> -> /<repo>/tree/<path>?h=<branch> (browsable file/dir view) -# Relative hrefs are resolved as paths against the repo root; a href that climbs -# out of the repo with ".." (e.g. ../sibling) is resolved against the repo's URL -# location instead (-> /sibling), matching how sibling repos are addressed. -# cgit exports the repo context to about-filters via these environment vars; if -# they're absent we leave the references untouched. +# against the page the readme is shown on (/<repo>/about/... or the summary page +# /<repo>/), not against the file's own location — so they 404 or hit the wrong +# file. cgit serves this content through three commands, so rewrite relative +# references to absolute cgit URLs (absolute so they work on the about page and +# the summary page alike): +# <img src> -> /<repo>/plain/<path>?h=<branch> (raw bytes) +# <a href> *.md -> /<repo>/about/<path> (rendered markdown) +# <a href> other/dir -> /<repo>/tree/<path>?h=<branch> (browsable blob view) +# cgit hands the about-filter the path of the file being rendered as argv[1] +# (README.md, or docs/foo.md for a rendered subpage), so relative links resolve +# against *that* file's directory and links inside a rendered subpage work too. +# A href that climbs out of the repo with ".." (e.g. ../sibling) is resolved +# against the repo's URL location (-> /sibling). The about view renders against +# the configured readme ref, so about/ links carry no ?h=. If the repo context +# env vars are absent we leave the references untouched. import os, re from urllib.parse import urljoin repo = os.environ.get("CGIT_REPO_URL", "").strip("/") @@ -377,16 +381,16 @@ if repo: repo_root = "/" + repo + "/" plain = repo_root + "plain/" query = ("?h=" + branch) if branch else "" + # directory of the file being rendered; relative links resolve against it. + # argv[1] is the repo-relative readme/subpage path cgit passes the filter. + cur = sys.argv[1] if len(sys.argv) > 1 else "" + base_dir = "" if cur.startswith("/") else os.path.dirname(cur) + # markdown files are rendered via the about view; everything else is a blob + md_ext = re.compile(r"\.(?:md|markdown|mdown|mkd)$", re.I) # leave absolute, protocol-relative, root-relative, anchor, query-only and # scheme (mailto:, http:, data:, ...) URLs alone skip = re.compile(r"^(?:[a-z][a-z0-9+.\-]*:|//|/|[#?])", re.I) - def rewrite_img(m): - url = m.group(2) - if not url or skip.match(url): - return m.group(0) - return m.group(1) + plain + re.sub(r"^\./", "", url) + query + m.group(3) - def _split_frag(url): # split off a trailing #fragment (kept verbatim on the rewritten URL) if "#" in url: @@ -394,11 +398,13 @@ if repo: return path, "#" + frag return url, "" - def _normalize(path): - # resolve "." / ".." against the repo root; returns (climbs, cleaned) - # where `climbs` counts ".." segments that escaped above the repo root. + def _resolve(path): + # resolve `path` (relative to base_dir) into a repo-root-relative path, + # collapsing "." / ".."; returns (climbs, cleaned) where `climbs` counts + # ".." segments that escaped above the repo root. + combined = (base_dir + "/" + path) if base_dir else path out, climbs = [], 0 - for seg in path.split("/"): + for seg in combined.split("/"): if seg in ("", "."): continue if seg == "..": @@ -410,19 +416,32 @@ if repo: out.append(seg) return climbs, "/".join(out) + def rewrite_img(m): + url = m.group(2) + if not url or skip.match(url): + return m.group(0) + path, frag = _split_frag(url) + climbs, cleaned = _resolve(path) + if climbs or not cleaned: + return m.group(0) + return m.group(1) + plain + cleaned + query + frag + m.group(3) + def rewrite_href(m): url = m.group(2) if not url or skip.match(url): return m.group(0) path, frag = _split_frag(url) - climbs, cleaned = _normalize(path) + climbs, cleaned = _resolve(path) if climbs: # escapes the repo (sibling repo etc.): resolve against repo location dest = urljoin(repo_root, "../" * climbs + cleaned) - elif cleaned: - dest = repo_root + "tree/" + cleaned + query - else: + elif not cleaned: dest = repo_root + (query or "") + elif md_ext.search(cleaned): + # rendered through the about-filter (renders against the readme ref) + dest = repo_root + "about/" + cleaned + else: + dest = repo_root + "tree/" + cleaned + query return m.group(1) + dest + frag + m.group(3) html = re.sub(r'(<img\b[^>]*?\bsrc=")([^"]*)(")', rewrite_img, html, flags=re.I) |
