about summary refs log tree commit diff stats
path: root/wikme.py
diff options
context:
space:
mode:
Diffstat (limited to 'wikme.py')
-rw-r--r--wikme.py106
1 files changed, 106 insertions, 0 deletions
diff --git a/wikme.py b/wikme.py new file mode 100644 index 0000000..2df5a03 --- /dev/null +++ b/wikme.py
@@ -0,0 +1,106 @@
1import os
2import re
3import argparse
4import markdown
5import datetime
6import subprocess
7import shutil
8from typing import Optional
9
10def kebab_case(s: str) -> str:
11 return re.sub(r"[ _]", "-", s).lower()
12
13def get_title(filename: str, content: Optional[str] = None) -> str:
14 if content:
15 # Check for a top-level header in the content
16 top_level_header = re.search(r"^#\s(.+)$", content, re.MULTILINE)
17 if top_level_header:
18 return top_level_header.group(1).strip()
19
20 # Extract the inferred title from the filename
21 title = filename.replace(".md", "").replace("_", " ")
22 return title.capitalize()
23
24def parse_wikilinks(content: str) -> str:
25 # Convert wikilinks with tildes and custom titles
26 content = re.sub(r'\[\[(~[^|\]]+?)\|([^|\]]+?)\]\]', r'<a href="/\1">\2</a>', content)
27
28 # Convert wikilinks with tildes and without custom titles
29 content = re.sub(r'\[\[(~[^|\]]+?)\]\]', r'<a href="/\1">\1</a>', content)
30
31 # Convert regular wikilinks with custom titles
32 content = re.sub(r'\[\[([^~|\]]+?)\|([^~|\]]+?)\]\]', lambda match: f'<a href="./{kebab_case(match.group(1))}.html">{match.group(2)}</a>', content)
33
34 # Convert regular wikilinks without custom titles
35 content = re.sub(r'\[\[([^~|\]]+?)\]\]', lambda match: f'<a href="./{kebab_case(match.group(1))}.html">{match.group(1)}</a>', content)
36
37 return content
38
39def render_template(template: str, title: str, content: str, last_edited: str) -> str:
40 # Insert title, content, and last_edited into the template
41 rendered = template.replace("{{ title }}", title)
42 rendered = rendered.replace("{{ content }}", content)
43 rendered = rendered.replace("{{ last_edited }}", last_edited)
44 return rendered
45
46def get_last_edited(path: str) -> str:
47 try:
48 # Attempt to get the last Git commit date of the file
49 last_edited = subprocess.check_output(
50 ["git", "log", "-1", "--format=%cd", "--date=local", path])
51 return last_edited.decode("utf-8").strip()
52 except Exception:
53 # Fallback to the file's modified timestamp
54 return str(datetime.datetime.fromtimestamp(os.path.getmtime(path)))
55
56def main(input_folder: str, output_folder: str, template_file: str):
57 # Load the template
58 with open(template_file, "r") as template_f:
59 template = template_f.read()
60
61 # Go through each markdown file
62 for root, dirs, files in os.walk(input_folder):
63 for file in files:
64 if file.endswith(".md"):
65 # Process the markdown file
66 input_file = os.path.join(root, file)
67 output_subfolder = os.path.join(
68 output_folder, os.path.relpath(root, input_folder))
69 output_file = os.path.join(
70 output_subfolder, f"{kebab_case(file.replace('.md', ''))}.html")
71
72 # Read the source file
73 with open(input_file, "r") as source:
74 markdown_content = source.read()
75 html_content = markdown.markdown(
76 parse_wikilinks(markdown_content), extensions=['codehilite']
77 )
78
79 # Create the output folder if needed
80 if not os.path.exists(output_subfolder):
81 os.makedirs(output_subfolder)
82
83 # Render the result
84 title = get_title(file, markdown_content)
85 last_edited = get_last_edited(input_file)
86 rendered_content = render_template(template, title, html_content, last_edited)
87
88 # Save the rendered HTML file
89 with open(output_file, "w") as output_f:
90 output_f.write(rendered_content)
91
92def cmd():
93 parser = argparse.ArgumentParser(
94 description="Convert a folder of Markdown files into a simple wiki-style website.")
95 parser.add_argument('--input', dest='input_folder',
96 required=True, help='input folder containing Markdown files')
97 parser.add_argument('--output', dest='output_folder',
98 required=True, help='output folder for generated HTML files')
99 parser.add_argument('--template', dest='template_file',
100 required=True, help='HTML template for the generated files')
101 args = parser.parse_args()
102
103 main(args.input_folder, args.output_folder, args.template_file)
104
105if __name__ == "__main__":
106 cmd() \ No newline at end of file