import html
import os
import re
import shutil
from collections import defaultdict
SRC_DIR = "src"
DST_DIR = "dst"
IMG_DIR = "img"
INCLUDE_DIR = "inc"
os.makedirs(DST_DIR, exist_ok=True)
def copy_file(src, dst):
try:
shutil.copy(src, dst)
except FileNotFoundError:
print(f"Warning: {src} not found. Skipping.")
def copy_folder(src, dst):
try:
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst)
except Exception as e:
print(f"Error copying folder {src} to {dst}: {e}")
def read_file(filepath, encoding="utf-8"):
try:
with open(filepath, "r", encoding=encoding) as file:
return file.read()
except FileNotFoundError:
print(f"Warning: {filepath} not found.")
return ""
def write_file(filepath, content, encoding="utf-8"):
with open(filepath, "w", encoding=encoding) as file:
file.write(content)
def set_permissions(DST_DIR):
for root, dirs, files in os.walk(DST_DIR):
for dir_name in dirs:
dir_path = os.path.join(root, dir_name)
os.chmod(dir_path, 0o755)
for file_name in files:
file_path = os.path.join(root, file_name)
os.chmod(file_path, 0o644)
backlink_map = defaultdict(set)
def find_internal_links(text, current_file):
re.sub(r"{([a-zA-Z0-9_]+)(?:\s+([^}]*))?}",
lambda m: backlink_map[m.group(1)].add(current_file),
text)
def process_internal_links(text):
return re.sub(
r"{([a-zA-Z0-9_]+)(?:\s+([^}]+))?}",
lambda m: f'{m.group(2) if m.group(2) else m.group(1)}',
text,)
def include_image(image_file):
for ext in ["jpg", "png"]:
img_path = os.path.join(IMG_DIR, f"{image_file}.{ext}")
if os.path.exists(img_path):
return f'
'
return ""
def include_file(file_type, reference):
dir_map = {"code": "code", "text": "text"}
parts = reference.split(":")
filename = parts[0]
line_ranges = parts[1:]
file_path = os.path.join(
INCLUDE_DIR, dir_map[file_type], filename if file_type == "code" else f"{filename}.txt"
)
content = read_file(file_path)
if not content:
return f"
File not found: {filename}
==> {file_path}
'
content_lines = content.splitlines()
selected_lines = []
for line_range in line_ranges:
try:
if "-" in line_range:
start, end = map(int, line_range.split("-"))
selected_lines.append("\n".join(content_lines[start - 1:end]))
else:
line = int(line_range)
selected_lines.append(content_lines[line - 1])
except (ValueError, IndexError):
selected_lines.append(f"Error processing range: {line_range}")
formatted_content = "\n\n[...]\n\n".join(selected_lines)
escaped_content = html.escape(formatted_content)
return f"\n{escaped_content}
"
def convert_inline_markup(text):
text = re.sub(
r"`(.*?)`",
lambda m: f"{html.escape(m.group(1))}
",
text
)
text = re.sub(r"\*(.*?)\*", r"\1", text)
text = re.sub(r"~(.*?)~", r"\1", text)
text = re.sub(r"`(.*?)`", r"\1
", text)
text = re.sub(r"(?)=(?!>)",r"\1",text)
return text
def handle_list(html_lines, line, in_list):
if not in_list:
html_lines.append("" + "\n".join(block_code_buffer) + "
")
html_lines.append(handle_backlinks(filename))
html_lines.append('Back to top')
html_lines += ["", ""]
html_lines.append(read_file(os.path.join(INCLUDE_DIR, "foot.tpl")))
return "\n".join(html_lines)
for file in os.listdir(SRC_DIR):
if file.endswith(".txt"):
content = read_file(os.path.join(SRC_DIR, file))
find_internal_links(content, os.path.splitext(file)[0])
for file in os.listdir(SRC_DIR):
if file.endswith(".txt"):
lines = read_file(os.path.join(SRC_DIR, file)).splitlines()
html_content = convert_markup_to_html(lines, os.path.splitext(file)[0])
write_file(os.path.join(DST_DIR, file.replace(".txt", ".html")), html_content)
copy_file(os.path.join(INCLUDE_DIR, "style.css"), os.path.join(DST_DIR, "style.css"))
copy_file(os.path.join(INCLUDE_DIR, "atom.xsl"), os.path.join(DST_DIR, "atom.xsl"))
copy_folder(INCLUDE_DIR, os.path.join(DST_DIR, "inc"))
set_permissions(DST_DIR)