Compare commits

..

No commits in common. "90ecb8bf64c6306eee90e288e83cb22189588d4d" and "bcbb7406f1acc7ee709b850c42ba4710766501e5" have entirely different histories.

124 changed files with 195 additions and 366 deletions

3
.gitignore vendored
View File

@ -1,4 +1,3 @@
venv/ venv/
input/ input/
output/ out/
include/main.bib

View File

@ -1,9 +1,10 @@
\NeedsTeXFormat{LaTeX2e} \NeedsTeXFormat{LaTeX2e}
\ProvidesClass{bookreport}[2022/3/12 Book Report] \ProvidesClass{bookreport}[2022/3/12 Book Report]
\LoadClass{note} \LoadClass{article}
\usepackage{iflang} \usepackage{iflang}
\usepackage[margin=1in]{geometry}
\renewcommand{\maketitle}{ \renewcommand{\maketitle}{
\IfLanguageName{portuguese} \IfLanguageName{portuguese}

View File

@ -1,46 +1,18 @@
#!/bin/env python3.9 #!/bin/python3.9
from subprocess import run import os
from datetime import date import re
from os import makedirs, environ import shutil
from os.path import relpath import subprocess
from re import findall
from glob import glob
from pathlib import Path
from sys import argv, stderr
from shutil import copy, copytree, rmtree
from html.parser import HTMLParser from html.parser import HTMLParser
from pygments import highlight from pygments import highlight
from pygments.lexers import get_lexer_by_name from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter from pygments.formatters import HtmlFormatter
import sys
base_author = 'Augusto Gunsch' if len(sys.argv) > 1 and 'clean' not in sys.argv:
print('usage: %s [clean]' % sys.argv[0])
input_root = Path('input')
output_root = Path('output')
file_output_root = output_root / Path('files')
templates_root = Path('templates')
static_root = Path('static')
if len(argv) > 1 and 'clean' not in argv:
print('usage: {} [clean]'.format(argv[0]), file=stderr)
exit(1) exit(1)
if 'clean' in argv:
print('Cleaning output root')
rmtree(output_root, ignore_errors=True)
templates = {}
for template in templates_root.glob('*.html'):
templates[template.stem] = template.read_text()
def render_template(template, **kwargs):
for var, val in kwargs.items():
template = template.replace('${%s}' % var, str(val))
return template
class CodeHighlighter(HTMLParser): class CodeHighlighter(HTMLParser):
data = '' data = ''
reading_code = False reading_code = False
@ -91,249 +63,148 @@ class CodeHighlighter(HTMLParser):
highlighter = CodeHighlighter() highlighter = CodeHighlighter()
input_ = 'input'
outroot = 'out'
output = 'Files'
templates = 'templates'
class TeXFile: if 'clean' in sys.argv:
def extract_tex_metadata(self): shutil.rmtree(outroot, ignore_errors=True)
m = findall(r'\\usepackage\[(.*)\]\{babel\}', self.raw_content)
self.lang = m[0] if m else 'english'
m = findall(r'\\title\{(.*)\}', self.raw_content) try:
self.title = m[0] if m else self.input_file.stem.replace('_', ' ') os.mkdir(outroot)
shutil.copy(templates + '/stylesheet.css', outroot + '/stylesheet.css')
m = findall(r'\\author\{(.*)\}', self.raw_content) shutil.copy(templates + '/highlight.css', outroot + '/highlight.css')
self.author = m[0] if m else base_author shutil.copy(templates + '/cabinet.png', outroot + '/cabinet.png')
shutil.copy(templates + '/jquery.js', outroot + '/jquery.js')
m = findall(r'\\date\{(.*)\}', self.raw_content) shutil.copytree(templates + '/mathjax', outroot + '/mathjax')
self.date = m[0] if m else date.today().strftime('%d/%m/%Y') shutil.copytree(templates + '/bootstrap', outroot + '/bootstrap')
except:
m = findall(r'\\documentclass\{(.*)\}', self.raw_content) pass
self.document_class = m[0] if m else 'article'
m = findall(r'\\usepackage(\[.*\])?\{biblatex\}', self.raw_content)
self.biblatex = bool(m)
def expand_macros(self):
content = self.raw_content
breadcrumbs = str(self.pretty_breadcrumbs).replace('>',
r'\textgreater\hspace{1pt}')
content = content.replace(r'\breadcrumbs', breadcrumbs)
outdir = (file_output_root/self.breadcrumbs).parent
content = content.replace(r'\outdir', str(outdir))
self.content = content
def __init__(self, input_file):
self.input_file = input_file
self.breadcrumbs = Path(*input_file.parts[len(input_root.parts):]).with_suffix('')
self.pretty_breadcrumbs = str(self.breadcrumbs) \
.replace('_', ' ') \
.replace('/', ' > ')
with open(input_file, 'r') as f:
self.raw_content = f.read()
self.mtime = input_file.stat().st_mtime
self.extract_tex_metadata()
self.expand_macros()
class FromTeX: with open(templates + '/file.html', 'r') as template:
def __init__(self, tex_file, ext): file_template = template.read()
self.tex_file = tex_file
self.output_file = file_output_root / self.tex_file.breadcrumbs.with_suffix(ext) with open(templates + '/index.html', 'r') as template:
index_template = template.read()
self.mtime = self.output_file.stat().st_mtime \
if self.output_file.exists() else 0
self.is_outdated = self.mtime < self.tex_file.mtime
class HtmlFile(FromTeX): def render_template(template, **kwargs):
def __init__(self, tex_file): for var, val in kwargs.items():
super().__init__(tex_file, '.html') template = template.replace('${%s}' % var, val)
def write_output(self): return template
args = [
class File:
def __init__(self, root, outdir, name):
self.outdir = outdir
self.basename = name[:-4]
self.pdf = self.basename + '.pdf'
self.html = self.basename + '.html'
self.path = self.outdir.removeprefix(outroot + '/') + '/' + self.html
self.pretty_path = self.path.replace('_', ' ').removesuffix('.html')
self.input_path = root + '/' + name
self.root_reference = re.sub(r'.+?/', '../', outdir)
self.root_reference = re.sub(r'/[^\.]+$', '/', self.root_reference)
path = '%s/%s' % (root, name)
with open(path, 'r') as f:
content = f.read()
m = re.findall(r'\\selectlanguage\{(.*?)\}', content)
if not m:
m = re.findall(r'\\usepackage\[(.*?)\]\{babel\}', content)
if not m:
m = re.findall(r'\\documentclass\[(.*?)\]\{.*\}', content)
lang = m[0] if len(m) > 0 else 'english'
m = re.findall(r'\\documentclass\{(.*?)\}', content)
doc_class = m[0] if len(m) > 0 else 'article'
options = [
'pandoc', 'pandoc',
'--mathjax=static/mathjax/es5/tex-mml-chtml.js', '--mathjax=templates/mathjax/es5/tex-mml-chtml.js',
'-f', 'latex', '-f', 'latex',
'-t', 'html', '-t', 'html',
'-' path
]
proc = run(args,
input=self.tex_file.content,
encoding='utf-8',
capture_output=True)
if proc.returncode != 0:
print(proc.stderr, file=stderr)
exit(proc.returncode)
body = proc.stdout
try:
template = templates[self.tex_file.document_class]
except:
print('No template named "{}.html"'.format(self.tex_file.document_class),
file=stderr)
exit(2)
root = Path(relpath(output_root, start=self.output_file)).parent
if self.tex_file.lang == 'portuguese':
lang_title = 'Título'
lang_author = 'Autor'
lang_date = 'Data da Ficha'
else:
lang_title = 'Title'
lang_author = 'Author'
lang_date = 'Report Date'
content = render_template(template,
lang_title=lang_title,
lang_author=lang_author,
lang_date=lang_date,
title=self.tex_file.title,
date=self.tex_file.date,
author=self.tex_file.author,
breadcrumbs=self.tex_file.pretty_breadcrumbs,
pdf=self.output_file.with_suffix('.pdf').name,
root=root,
body=body)
highlighter.feed(content)
content = highlighter.output()
makedirs(self.output_file.parent, exist_ok=True)
with open(self.output_file, 'w') as f:
f.write(content)
class PdfFile(FromTeX):
def __init__(self, tex_file):
super().__init__(tex_file, '.pdf')
def run_pdflatex(self):
args = [
'pdflatex',
'-jobname', self.output_file.stem,
'-output-directory', self.output_file.parent,
'-shell-escape'
] ]
env = { if doc_class == 'bookreport':
**environ, options.append('-s')
'TEXINPUTS': './include:' options.append('--template')
} options.append('templates/default.html')
proc = run(args, self.content = subprocess.check_output(options).decode()
env=env,
input=bytes(self.tex_file.content, 'utf-8'),
capture_output=True)
if proc.returncode != 0: if doc_class == 'bookreport':
print(proc.stdout, file=stderr) if lang == 'portuguese':
print(proc.stderr, file=stderr) self.content = re.sub(r'!\*\*title\*\*!', 'Título', self.content)
exit(proc.returncode) self.content = re.sub(r'!\*\*author\*\*!', 'Autor', self.content)
self.content = re.sub(r'!\*\*date\*\*!', 'Data da Ficha', self.content)
def run_biber(self):
args = [
'biber',
self.output_file.with_suffix('')
]
proc = run(args,
capture_output=True)
if proc.returncode != 0:
print(proc.stdout, file=stderr)
print(proc.stderr, file=stderr)
exit(proc.returncode)
def write_output(self):
makedirs(self.output_file.parent, exist_ok=True)
self.run_pdflatex()
if self.tex_file.biblatex:
self.run_biber()
self.run_pdflatex()
def write_files():
changed = False
for input_file in input_root.glob('**/*.tex'):
tex_file = TeXFile(input_file)
html_file = HtmlFile(tex_file)
pdf_file = PdfFile(tex_file)
if html_file.is_outdated:
print('Generating "{}"'.format(html_file.output_file))
html_file.write_output()
changed = True
if pdf_file.is_outdated:
print('Generating "{}"'.format(pdf_file.output_file))
pdf_file.write_output()
changed = True
return changed
def copy_static_files():
if not output_root.exists():
makedirs(output_root)
for entity in static_root.iterdir():
dest = output_root/Path(*entity.parts[len(static_root.parts):])
if not dest.exists():
print('Copying "{}" to "{}"'.format(entity, dest))
if entity.is_dir():
copytree(entity, dest)
else: else:
copy(entity, dest) self.content = re.sub(r'!\*\*title\*\*!', 'Title', self.content)
self.content = re.sub(r'!\*\*author\*\*!', 'Author', self.content)
self.content = re.sub(r'!\*\*date\*\*!', 'Report Date', self.content)
def make_details(directory): def expand_html(self):
html = '' title = self.basename.replace('_', ' ')
if directory != input_root: expanded = render_template(file_template,
html += '<details open>' title=title,
html += '<summary>{}</summary>'.format(directory.name.replace('_', ' ')) path=self.pretty_path,
root=self.root_reference,
pdf=self.pdf,
content=self.content)
html += '<ul>' highlighter.feed(expanded)
for file in directory.iterdir():
if file.is_file():
if file.suffix == '.tex':
outfile = Path(*file.resolve().parts[len(input_root.resolve().parts):])
outfile = ('files'/outfile).with_suffix('.html')
html += '<li><a href="{}">{}</a></li>'.format(outfile, return highlighter.output()
file.stem.replace('_', ' '))
else:
html += make_details(file)
html += '</ul>'
if directory != input_root: def write_html(self):
html += '</details>' html_content = self.expand_html()
return html with open(self.outdir + '/' + self.html, 'w') as f:
f.write(html_content)
def make_index(): def write_pdf(self):
html = '<ul id="toc">' subprocess.run(['latexmk', '-shell-escape', '-pdf', '-outdir=%s' % self.outdir, self.input_path])
html += make_details(input_root)
html += '</ul>'
index = render_template(templates['index'], subprocess.run(['latexmk', '-c', '-outdir=%s' % self.outdir, self.input_path])
toc=html)
with open(output_root / 'index.html', 'w') as f: def write(self):
f.write(index) html = self.outdir + '/' + self.html
pdf = self.outdir + '/' + self.pdf
input_time = os.path.getmtime(self.input_path)
if not os.path.isfile(html) or input_time > os.path.getmtime(html):
self.write_html()
if not os.path.isfile(pdf) or input_time > os.path.getmtime(pdf):
self.write_pdf()
copy_static_files()
outdated_index = write_files()
if outdated_index: toc = '<ul>'
print('Generating index')
make_index() for root, dirs, files in os.walk(input_, topdown=True):
outdir = outroot + '/' + output + root[len(input_):]
os.makedirs(outdir, exist_ok=True)
outfiles = []
if len(files) or len(dirs):
for file in files:
if file.endswith('.tex'):
f = File(root, outdir, file)
f.write()
toc += '<li><a href="%s">%s</a></li>' % (f.path, f.pretty_path)
toc += '</ul>'
with open(outroot + '/index.html', 'w') as f:
f.write(render_template(index_template,
toc=toc))

View File

@ -1,13 +0,0 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{note}[2022/3/14 Note]
\LoadClass{article}
\usepackage[margin=1in]{geometry}
\newcommand{\noteheader}[1]{
\noindent\large
\begin{center}
#1
\end{center}
}

View File

@ -1,48 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="${root}/bootstrap/css/bootstrap.min.css"/>
<link rel="stylesheet" href="${root}/highlight.css"/>
<link rel="stylesheet" href="${root}/stylesheet.css"/>
<script src="${root}/jquery.js"></script>
<script src="${root}/bootstrap/js/bootstrap.bundle.min.js"></script>
<script>
window.MathJax = {
options: {
enableMenu: false,
enableEnrichment: false
}
};
</script>
<script src="${root}/mathjax/es5/tex-mml-chtml.js"></script>
<title>${title}</title>
</head>
<body>
<header class="container-fluid">
<h1 id="cabinet"><img id="cabinet-icon" src="${root}/cabinet.png"/>Cabinet</h1>
</header>
<nav class="container-fluid">
<a class="button" id="back" href="${root}/index.html">&larr; Back</a>
<span id="path">${breadcrumbs}</span>
<a class="button" id="pdf" href="${pdf}">&darr; PDF</a>
</nav>
<main class="container">
<table id="meta">
<tr>
<td>${lang_title}:</td> <td>${title}</td>
</tr>
<tr>
<td>${lang_author}:</td> <td>${author}</td>
</tr>
<tr>
<td>${lang_date}:</td> <td>${date}</td>
</tr>
</table>
<hr>
${body}
</main>
</body>
</html>

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

28
templates/default.html Normal file
View File

@ -0,0 +1,28 @@
<style>
#meta {
width: 100%;
font-size: 1.3em;
}
#meta td:nth-child(2) {
text-align: right;
}
</style>
<table id="meta">
<tr>
<td>!**title**!:</td> <td>$title$</td>
</tr>
<tr>
<td>!**author**!:</td> <td>$author$</td>
</tr>
<tr>
<td>!**date**!:</td> <td>$date$</td>
</tr>
</table>
<hr>
<article>
$body$
</article>

34
templates/file.html Normal file
View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="${root}bootstrap/css/bootstrap.min.css"/>
<link rel="stylesheet" href="${root}highlight.css"/>
<link rel="stylesheet" href="${root}stylesheet.css"/>
<script src="${root}jquery.js"></script>
<script src="${root}bootstrap/js/bootstrap.bundle.min.js"></script>
<script>
window.MathJax = {
options: {
enableMenu: false,
enableEnrichment: false
}
};
</script>
<script src="${root}mathjax/es5/tex-mml-chtml.js"></script>
<title>${title}</title>
</head>
<body>
<header class="container-fluid">
<h1 id="cabinet"><img id="cabinet-icon" src="${root}cabinet.png"/>Cabinet</h1>
</header>
<nav class="container-fluid">
<a class="button" id="back" href="${root}index.html">&larr; Back</a>
<span id="path">${path}</span>
<a class="button" id="pdf" href="${pdf}">&darr; PDF</a>
</nav>
<main class="container">
${content}
</main>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More