Initial commit
This commit is contained in:
149
md.py
Executable file
149
md.py
Executable file
@@ -0,0 +1,149 @@
|
||||
#!/bin/python3
|
||||
# hrtime - transgender research website
|
||||
# Copyright (C) 2025 Olive <hello@grasswren.net>
|
||||
# see LICENCE file for licensing information
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def ch(st: str) -> str:
|
||||
st = re.sub(r'&', r'&', st)
|
||||
st = re.sub(r'>', r'>', st)
|
||||
st = re.sub(r'<', r'<', st)
|
||||
return st
|
||||
|
||||
|
||||
def qch(st: str) -> str:
|
||||
return re.sub('\'', r''', ch(st))
|
||||
|
||||
|
||||
def mdh(line: str) -> str:
|
||||
ret = ''
|
||||
while len(line) > 0:
|
||||
match = re.match(r'!\[(.*?)\]\((.*?)\)', line)
|
||||
if match != None:
|
||||
line = line[match.span()[1]:]
|
||||
ret += f"<span class='n' title='{qch(match.group(2))}'>" + \
|
||||
f'{ch(match.group(1))}</span>'
|
||||
continue
|
||||
|
||||
match = re.match(r'\[(.*?)\]\(([^ ]*)\)', line)
|
||||
if match != None:
|
||||
line = line[match.span()[1]:]
|
||||
ret += f"<a href='{qch(match.group(2))}' target='_blank'" \
|
||||
+ f'>{ch(match.group(1))}</a>'
|
||||
continue
|
||||
|
||||
match = re.match(r'`(.)(.*?)`', line)
|
||||
if match != None:
|
||||
line = line[match.span()[1]:]
|
||||
ret += r"<code" + (f" class='{match.group(1)}'" if match.group(1) \
|
||||
!= '/' else '') + f'>{ch(match.group(2))}</code>'
|
||||
continue
|
||||
|
||||
ret += ch(line[0])
|
||||
line = line[1:]
|
||||
|
||||
ret = re.sub(r'NOBREAK', r'⁠', ret)
|
||||
return ret
|
||||
|
||||
|
||||
def md(line: str) -> str:
|
||||
# allows '|' and '||' escaping to work
|
||||
ret, do = '', True
|
||||
for sec in line.strip().split('|'):
|
||||
if len(sec) == 0:
|
||||
ret += '|'
|
||||
else:
|
||||
ret += mdh(sec) if do else sec
|
||||
do = not do
|
||||
return ret
|
||||
|
||||
|
||||
def media(line: str):
|
||||
file, alt = tuple(line.strip().split('|'))
|
||||
file = qch(file)
|
||||
if file[-5:] in ('.webp'):
|
||||
print(f"<img src='{file}' alt='{qch(alt)}'>")
|
||||
if file[-4:] in ('.mp4'):
|
||||
print('<video controls>')
|
||||
print(f"<source src='{file}' type='video/mp4' alt='{qch(alt)}'>")
|
||||
print('</video>')
|
||||
if file[-4:] in ('.pdf'):
|
||||
print(f"<object data='{file}' type='application/pdf' height='80%'>")
|
||||
print(f"<a href='{file}'>{ch(alt)}</a>")
|
||||
print('</object>')
|
||||
|
||||
|
||||
def doc(lines: list[str]):
|
||||
head = ''
|
||||
with open('head.html', 'r') as file:
|
||||
head = file.read()
|
||||
|
||||
lines[0] = lines[0].strip()
|
||||
if len(lines[0]) > 0:
|
||||
lines[0] = ' — ' + lines[0]
|
||||
head = re.sub(r'TITLE', lines[0], head, count=2)
|
||||
print(head, end='')
|
||||
lines = lines[1:]
|
||||
|
||||
mode=''
|
||||
for line in lines:
|
||||
if line[1:4] == ' ':
|
||||
if mode != '</code></pre>':
|
||||
if line[0] != '/':
|
||||
cls = f" class='{line[0]}'"
|
||||
print(f'<pre><code{cls}>', end='')
|
||||
mode = '</code></pre>'
|
||||
print(ch(line[4:].rstrip()))
|
||||
continue
|
||||
elif line[:2] == ' ':
|
||||
if mode != '</ul>':
|
||||
print("<ul class='l'>")
|
||||
mode = '</ul>'
|
||||
print(f'<li>{md(line[2:])}</li>')
|
||||
continue
|
||||
elif line[:2] == '- ':
|
||||
if mode != '</ul>':
|
||||
print('<ul>')
|
||||
mode = '</ul>'
|
||||
print(f'<li>{md(line[2:])}</li>')
|
||||
continue
|
||||
|
||||
if mode != '':
|
||||
print(mode)
|
||||
mode = ''
|
||||
|
||||
if len(line) == 1:
|
||||
print('</section>\n<section>')
|
||||
elif line[:2] == '# ':
|
||||
print(f'<h1>{md(line[2:])}</h1>')
|
||||
elif line[:3] == '## ':
|
||||
print(f'<h2>{md(line[3:])}</h2>')
|
||||
elif line[:2] == '! ':
|
||||
media(line[2:])
|
||||
elif line[:2] == '@ ':
|
||||
title, link, desc, date = tuple(line[2:].split('|'))
|
||||
print('<article>\n<div>')
|
||||
print(f"<h1><a href='{qch(link)}'>{md(title)}</a></h1>")
|
||||
print('</div>\n<div>')
|
||||
print(f'<p>{md(desc)}</p>')
|
||||
print(f'<p>(<time>{date.strip()}</time>)</p>')
|
||||
print('</div>\n</article>')
|
||||
else:
|
||||
print('<p>' + md(line) + '</p>')
|
||||
|
||||
if mode != '':
|
||||
print(mode)
|
||||
|
||||
with open('foot.html', 'r') as file:
|
||||
print(file.read(), end='')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 2:
|
||||
print('usage: md [file]')
|
||||
else:
|
||||
with open(sys.argv[1], 'r') as file:
|
||||
doc(list(file))
|
||||
Reference in New Issue
Block a user