From 424ec3621d9fc24cdad7ae938cef75c5a865ee8c Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Thu, 18 Sep 2025 14:19:48 -0500 Subject: [PATCH] replace links that have .md suffixes with clean links to aid viewing the raw markdown source in e.g. a gitlab source browser, or to aid navigation in vim with "gf" style commands to jump between files, allow the markdown source to specify foo.md or whatever/index.md explicitly, yet generate the clean URLs for linking in the HTML output this assumes that nginx is serving "foo" with foo.html, and "bar/" with bar/index.html Signed-off-by: Brian S. Stephan --- incorporealcms/markdown.py | 11 ++++++++++ .../instance/pages/file-with-index.md-link.md | 6 ++++++ tests/instance/pages/file-with-md-link.md | 4 ++++ tests/test_markdown.py | 20 +++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 tests/instance/pages/file-with-index.md-link.md create mode 100644 tests/instance/pages/file-with-md-link.md diff --git a/incorporealcms/markdown.py b/incorporealcms/markdown.py index 3999457..8a36784 100644 --- a/incorporealcms/markdown.py +++ b/incorporealcms/markdown.py @@ -58,7 +58,18 @@ def parse_md(path: str, pages_root: str): with open(absolute_path, 'r') as input_file: mtime = datetime.datetime.fromtimestamp(os.path.getmtime(input_file.name), tz=datetime.timezone.utc) entry = input_file.read() + logger.debug("path '%s' read", absolute_path) + + # remove .md extensions used for navigating in vim and replace them with + # the pattern we use for HTML output here + # foo/index.md -> foo/, foo/index.md#anchor -> foo/#anchor + # ../index.md -> ../, ../index.md#anchor -> ../#anchor + entry = re.sub(r'\[([^]]+)\]\(([^)]+)index.md(#[^)]*)?\)', r'[\1](\2\3)', entry) + # index.md -> ., index.md#anchor -> .#anchor + entry = re.sub(r'\[([^]]+)\]\(index.md(#[^)]*)?\)', r'[\1](.\2)', entry) + # bar.md -> bar, foo/bar.md -> foo/bar, bar.md#anchor -> bar#anchor + entry = re.sub(r'\[([^]]+)\]\(([^)]+).md(#[^)]*)?\)', r'[\1](\2\3)', entry) md = init_md() content = Markup(md.convert(entry)) # nosec B704 except (OSError, FileNotFoundError): diff --git a/tests/instance/pages/file-with-index.md-link.md b/tests/instance/pages/file-with-index.md-link.md new file mode 100644 index 0000000..6cfae0b --- /dev/null +++ b/tests/instance/pages/file-with-index.md-link.md @@ -0,0 +1,6 @@ +[Cool](cool/index.md) +[Anchored Cool](cool/index.md#anchor) +[This Index](index.md) +[Anchored This Index](index.md#anchor) +[Parent](../index.md) +[Anchored Parent](../index.md#anchor) diff --git a/tests/instance/pages/file-with-md-link.md b/tests/instance/pages/file-with-md-link.md new file mode 100644 index 0000000..b59d55b --- /dev/null +++ b/tests/instance/pages/file-with-md-link.md @@ -0,0 +1,4 @@ +[Foo](foo.md) +[Anchored Foo](foo.md#anchor) +[Sub Foo](sub/foo.md) +[Anchored Sub Foo](sub/foo.md#anchor) diff --git a/tests/test_markdown.py b/tests/test_markdown.py index 13c6312..71932a0 100644 --- a/tests/test_markdown.py +++ b/tests/test_markdown.py @@ -163,3 +163,23 @@ def test_parse_md_bad_file(): """Test the direct results of parsing a markdown file.""" with pytest.raises(ValueError): content, md, page_name, page_title, mtime = parse_md(os.path.join(PAGES_DIR, 'actually-a-png.md'), PAGES_DIR) + + +def test_md_extension_in_source_link_is_stripped(): + """Test that if a foo.md file link is specified in the Markdown, it is foo in the HTML.""" + content, _, _, _, _ = parse_md(os.path.join(PAGES_DIR, 'file-with-md-link.md'), PAGES_DIR) + assert 'Foo' in content + assert 'Anchored Foo' in content + assert 'Sub Foo' in content + assert 'Anchored Sub Foo' in content + + +def test_index_in_source_link_is_stripped(): + """Test that if a index.md file link is specified in the Markdown, it is just the dir in the HTML.""" + content, _, _, _, _ = parse_md(os.path.join(PAGES_DIR, 'file-with-index.md-link.md'), PAGES_DIR) + assert 'Cool' in content + assert 'Anchored Cool' in content + assert 'This Index' in content + assert 'Anchored This Index' in content + assert 'Parent' in content + assert 'Anchored Parent' in content