#! /usr/bin/env python3
# Copyright 2021 Steinar Knutsen
#
# Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence"); You may
# not use this work except in compliance with the Licence. You may obtain a copy
# of the Licence at:
#
# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# Licence for the specific language governing permissions and limitations under
# the Licence.
import sys, getopt
HELP_TEXT = """litxt2html [-h] [-s]
-c
add a small CSS and Javascript snippet to make for adjustable column width
-h
print this text
-s
strip the monospace markers from the generated HTML
Convert limited ITXT to HTML. Only monospace blocks and unindented paragraphs
of text are accepted as input."""
TITLE_MISSING = "Mandatory HTML document title missing, use -h for synopsis."
HEAD = """
"""
BODY = "\n"
FOOTER = "\n"
TITLE_TEMPLATE = "{title}"
MONO = "--------------------------------------------------------------------------------"
MONO_START = "
\n"
MONO_END= "
\n"
PARA_START = "
\n"
PARA_END = "
\n"
STYLES = """
"""
BUTTONS = """
n%n%
"""
quote_table = {
'&': "&",
'<': "<",
'>': ">"
}
def cook(line):
unwritten = i = 0
buffer = []
while i < len(line):
subst = quote_table.get(line[i])
if subst != None:
if unwritten != i:
buffer.append(line[unwritten:i])
unwritten = i + 1
buffer.append(subst)
i += 1
if unwritten < len(line):
buffer.append(line[unwritten:])
return "".join(buffer)
def ismonomarker(line):
return line.rstrip() == MONO
def write_line(destination, line, stripped_output):
if not stripped_output:
destination.write(cook(line))
return
if ismonomarker(line):
return
destination.write(cook(line))
def start_para(destination, para_started):
if not para_started:
destination.write(PARA_START)
return True
def end_para(destination, para_started):
if para_started:
destination.write(PARA_END)
return False
def main(source, destination, title, stripped_output, widthbuttons):
in_mono = False
para_started = False
destination.write(HEAD)
if widthbuttons:
destination.write(STYLES)
destination.write(TITLE_TEMPLATE.format(title=cook(title)))
destination.write(BODY)
if widthbuttons:
destination.write(BUTTONS)
for line in source:
if in_mono:
write_line(destination, line, stripped_output)
if ismonomarker(line):
in_mono = False
para_started = False
destination.write(MONO_END)
else:
if len(line.strip()) == 0:
para_started = end_para(destination, para_started)
continue
elif ismonomarker(line):
para_started = end_para(destination, para_started)
in_mono = True
destination.write(MONO_START)
write_line(destination, line, stripped_output)
else:
if line[0].isspace():
raise ValueError("Indents outside monospace not supported.")
para_started = start_para(destination, para_started)
write_line(destination, line, stripped_output)
if in_mono:
raise ValueError("Unterminated monospace block.")
para_started = end_para(destination, para_started)
destination.write(FOOTER)
if __name__ == "__main__":
stripped_output = False
widthbuttons = False
options, arguments = getopt.gnu_getopt(sys.argv[1:], "chs")
for name, value in options:
if name == "-c":
widthbuttons = True
elif name == "-h":
print(HELP_TEXT)
sys.exit(0)
if name == "-s":
stripped_output = True
if len(arguments) != 1:
print(TITLE_MISSING, file=sys.stderr)
sys.exit(1)
main(sys.stdin, sys.stdout, arguments[0], stripped_output, widthbuttons)