from fetch import CachingFetcher
from glowfic import BesideIconLayout, BelowIconLayout, Layout
from htmlfilter import ApplyHTMLFilters, HTMLFilters
+from texfilter import ApplyTexFilters, TexFilters
from images import DiskImageStore
from spec import Spec
from texify import PandocTexifier
'(eg: "%(default)s" produces %(default)s.tex, %(default)s.pdf, etc.)',
default='book')
parser.add_argument('--pandoc', help='Location of the pandoc executable')
+ parser.add_argument(
+ '--texfilters',
+ help='Which TeX filters to use (default: %(default)s)',
+ default=','.join(f[0] for f in TexFilters))
parser.add_argument(
'--timeout',
help='How long to wait for HTTP requests, in seconds',
DiskImageStore(args.out + '_images', fetcher),
lambda x: ApplyHTMLFilters(args.htmlfilters, x),
lambda x: ApplyDOMFilters(args.domfilters, x),
+ lambda x: ApplyTexFilters(args.texfilters, x),
layout,
args.geometry,
texout)
for r in chunkDOMs(html):
spec.domfilter(r)
chunk = makeChunk(r, spec.images)
- spec.texout.write(spec.layout.renderChunk(chunk))
+ spec.texout.write(spec.texfilter(spec.layout.renderChunk(chunk)))
spec.texout.write(b'\\end{document}\n')
FakeImageStore(),
lambda x: x,
lambda x: ApplyDOMFilters('NoEdit,NoFooter', x),
+ lambda x: x,
ContentOnlyLayout(PandocTexifier('pandoc')),
'margin=20mm',
buf)
FakeImageStore(),
lambda x: x,
lambda x: ApplyDOMFilters('NoEdit,NoFooter', x),
+ lambda x: x,
ContentOnlyLayout(texifier),
None,
buf)
FakeImageStore(),
lambda x: x,
lambda x: ApplyDOMFilters('NoEdit,NoFooter', x),
+ lambda x: x,
BelowIconLayout(PandocTexifier('pandoc'), 20),
None,
out)
'images',
'paperdoorknob',
'spec',
+ 'texfilter',
'texify',
'version',
],
images: ImageStore
htmlfilter: Callable[[bytes], bytes]
domfilter: Callable[[Tag], None]
+ texfilter: Callable[[bytes], bytes]
layout: Layout
geometry: str | None
texout: IO[bytes]
--- /dev/null
+# paperdoorknob: Print glowfic
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, version 3.
+
+import re
+
+from typing import Callable, List, Tuple
+
+
+TexFilters: List[Tuple[str, Callable[[bytes], bytes]]] = [
+ # Work around `Extra }, or forgotten \endgroup.`
+ ("FixBareEmph", lambda x: re.sub(
+ b'(^|\n)(\\\\emph{)', b'\\1\\\\hspace{0pt}\\2', x)),
+]
+
+
+class TexFilterError(Exception):
+ pass
+
+
+def ApplyTexFilters(filter_list: str, data: bytes) -> bytes:
+ for filter_name in filter_list.split(','):
+ filters = [f for (name, f) in TexFilters if name == filter_name]
+ if len(filters) == 0:
+ raise TexFilterError(f"Unknown Tex filter: {filter_name}")
+ if len(filters) > 1:
+ raise TexFilterError(
+ f"Multiple Tex filters with the same name!?: {filter_name}")
+ data = filters[0](data)
+ return data
--- /dev/null
+# paperdoorknob: Print glowfic
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, version 3.
+
+
+import unittest
+from texfilter import ApplyTexFilters
+
+
+class TestTexFilters(unittest.TestCase):
+
+ def testStripNBSP(self) -> None:
+ self.assertEqual(
+ ApplyTexFilters("FixBareEmph", b'\\emph{Yes?}'),
+ b'\\hspace{0pt}\\emph{Yes?}')
+ self.assertEqual(
+ ApplyTexFilters("FixBareEmph", b'Reassuring.\n\n\\emph{Yes?}'),
+ b'Reassuring.\n\n\\hspace{0pt}\\emph{Yes?}')
+
+
+if __name__ == '__main__':
+ unittest.main()