FossilRepo

Expand Fossil wiki markup: enumeration lists, interwiki links, anchors, nowiki - # enumeration lists rendered as <ol> (separate from * bullet <ul>) - [wikipedia:Article] interwiki links → en.wikipedia.org - [#anchor] internal anchor links - [PageName] bare wiki links - <nowiki> tags stripped (content passes through) - Proper list type tracking (ul vs ol, switches correctly)

lmata 2026-04-07 00:02 trunk
Commit b311b008e340339b6e6a650ed1996314914323c6cdff62a21ab1bc1863d19d2c
1 file changed +24 -6
+24 -6
--- fossil/views.py
+++ fossil/views.py
@@ -57,31 +57,49 @@
5757
path = "/" + base_path + path
5858
return f'<a href="{path}">{text}</a>'
5959
6060
# Match [path | text] with flexible whitespace around the pipe
6161
content = re.sub(r"\[([^\]\|]+?)\s*\|\s*([^\]]+?)\]", _fossil_link_replace, content)
62
+ # Interwiki links: [wikipedia:Article] -> external link
63
+ content = re.sub(r"\[wikipedia:([^\]]+)\]", r'<a href="https://en.wikipedia.org/wiki/\1">\1</a>', content)
64
+ # Anchor links: [#anchor-name] -> local anchor
65
+ content = re.sub(r"\[#([^\]]+)\]", r'<a href="#\1">\1</a>', content)
66
+ # Bare wiki links: [PageName] (no pipe, not a URL)
67
+ content = re.sub(r"\[([A-Z][a-zA-Z0-9_]+)\]", r'<a href="\1">\1</a>', content)
68
+ # Verbatim blocks
6269
content = re.sub(r"<verbatim>(.*?)</verbatim>", r"<pre><code>\1</code></pre>", content, flags=re.DOTALL)
70
+ # <nowiki> blocks — strip the tags, content passes through as-is
71
+ content = re.sub(r"<nowiki>(.*?)</nowiki>", r"\1", content, flags=re.DOTALL)
6372
64
- # Convert Fossil wiki list syntax: lines starting with " * " to <ul><li>
73
+ # Convert Fossil wiki list syntax: * bullets and # enumeration
6574
lines = content.split("\n")
6675
result = []
6776
in_list = False
77
+ list_type = "ul"
6878
for line in lines:
6979
stripped_line = line.strip()
70
- if re.match(r"^\*\s", stripped_line) or re.match(r"^\d+\.\s", stripped_line):
80
+ is_bullet = re.match(r"^\*\s", stripped_line)
81
+ is_enum = re.match(r"^#\s", stripped_line) or re.match(r"^\d+[\.\)]\s", stripped_line)
82
+ if is_bullet or is_enum:
83
+ new_type = "ol" if is_enum else "ul"
7184
if not in_list:
72
- result.append("<ul>")
85
+ list_type = new_type
86
+ result.append(f"<{list_type}>")
7387
in_list = True
74
- item_text = re.sub(r"^[\*\d+\.]\s*", "", stripped_line)
88
+ elif new_type != list_type:
89
+ result.append(f"</{list_type}>")
90
+ list_type = new_type
91
+ result.append(f"<{list_type}>")
92
+ item_text = re.sub(r"^[\*#\d+\.\)]\s*", "", stripped_line)
7593
result.append(f"<li>{item_text}</li>")
7694
else:
7795
if in_list:
78
- result.append("</ul>")
96
+ result.append(f"</{list_type}>")
7997
in_list = False
8098
result.append(line)
8199
if in_list:
82
- result.append("</ul>")
100
+ result.append(f"</{list_type}>")
83101
84102
content = "\n".join(result)
85103
86104
# Wrap bare text blocks in <p> tags (lines not inside HTML tags)
87105
content = re.sub(r"\n\n(?!<)", "\n\n<p>", content)
88106
--- fossil/views.py
+++ fossil/views.py
@@ -57,31 +57,49 @@
57 path = "/" + base_path + path
58 return f'<a href="{path}">{text}</a>'
59
60 # Match [path | text] with flexible whitespace around the pipe
61 content = re.sub(r"\[([^\]\|]+?)\s*\|\s*([^\]]+?)\]", _fossil_link_replace, content)
 
 
 
 
 
 
 
62 content = re.sub(r"<verbatim>(.*?)</verbatim>", r"<pre><code>\1</code></pre>", content, flags=re.DOTALL)
 
 
63
64 # Convert Fossil wiki list syntax: lines starting with " * " to <ul><li>
65 lines = content.split("\n")
66 result = []
67 in_list = False
 
68 for line in lines:
69 stripped_line = line.strip()
70 if re.match(r"^\*\s", stripped_line) or re.match(r"^\d+\.\s", stripped_line):
 
 
 
71 if not in_list:
72 result.append("<ul>")
 
73 in_list = True
74 item_text = re.sub(r"^[\*\d+\.]\s*", "", stripped_line)
 
 
 
 
75 result.append(f"<li>{item_text}</li>")
76 else:
77 if in_list:
78 result.append("</ul>")
79 in_list = False
80 result.append(line)
81 if in_list:
82 result.append("</ul>")
83
84 content = "\n".join(result)
85
86 # Wrap bare text blocks in <p> tags (lines not inside HTML tags)
87 content = re.sub(r"\n\n(?!<)", "\n\n<p>", content)
88
--- fossil/views.py
+++ fossil/views.py
@@ -57,31 +57,49 @@
57 path = "/" + base_path + path
58 return f'<a href="{path}">{text}</a>'
59
60 # Match [path | text] with flexible whitespace around the pipe
61 content = re.sub(r"\[([^\]\|]+?)\s*\|\s*([^\]]+?)\]", _fossil_link_replace, content)
62 # Interwiki links: [wikipedia:Article] -> external link
63 content = re.sub(r"\[wikipedia:([^\]]+)\]", r'<a href="https://en.wikipedia.org/wiki/\1">\1</a>', content)
64 # Anchor links: [#anchor-name] -> local anchor
65 content = re.sub(r"\[#([^\]]+)\]", r'<a href="#\1">\1</a>', content)
66 # Bare wiki links: [PageName] (no pipe, not a URL)
67 content = re.sub(r"\[([A-Z][a-zA-Z0-9_]+)\]", r'<a href="\1">\1</a>', content)
68 # Verbatim blocks
69 content = re.sub(r"<verbatim>(.*?)</verbatim>", r"<pre><code>\1</code></pre>", content, flags=re.DOTALL)
70 # <nowiki> blocks — strip the tags, content passes through as-is
71 content = re.sub(r"<nowiki>(.*?)</nowiki>", r"\1", content, flags=re.DOTALL)
72
73 # Convert Fossil wiki list syntax: * bullets and # enumeration
74 lines = content.split("\n")
75 result = []
76 in_list = False
77 list_type = "ul"
78 for line in lines:
79 stripped_line = line.strip()
80 is_bullet = re.match(r"^\*\s", stripped_line)
81 is_enum = re.match(r"^#\s", stripped_line) or re.match(r"^\d+[\.\)]\s", stripped_line)
82 if is_bullet or is_enum:
83 new_type = "ol" if is_enum else "ul"
84 if not in_list:
85 list_type = new_type
86 result.append(f"<{list_type}>")
87 in_list = True
88 elif new_type != list_type:
89 result.append(f"</{list_type}>")
90 list_type = new_type
91 result.append(f"<{list_type}>")
92 item_text = re.sub(r"^[\*#\d+\.\)]\s*", "", stripped_line)
93 result.append(f"<li>{item_text}</li>")
94 else:
95 if in_list:
96 result.append(f"</{list_type}>")
97 in_list = False
98 result.append(line)
99 if in_list:
100 result.append(f"</{list_type}>")
101
102 content = "\n".join(result)
103
104 # Wrap bare text blocks in <p> tags (lines not inside HTML tags)
105 content = re.sub(r"\n\n(?!<)", "\n\n<p>", content)
106

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button