From: Scott Worley Date: Wed, 20 Dec 2023 23:42:32 +0000 (-0800) Subject: Reify Layout X-Git-Url: http://git.scottworley.com/paperdoorknob/commitdiff_plain/d2a41ff4f433a29173259359dcf477fd59ee3c78?ds=inline Reify Layout --- diff --git a/args.py b/args.py index f966ba9..62b9404 100644 --- a/args.py +++ b/args.py @@ -15,6 +15,7 @@ from xdg_base_dirs import xdg_cache_home from domfilter import ApplyDOMFilters, DOMFilters from fetch import CachingFetcher +from glowfic import BelowIconLayout from htmlfilter import ApplyHTMLFilters, HTMLFilters from images import DiskImageStore from spec import Spec @@ -62,6 +63,7 @@ See https://faculty.bard.edu/bloch/geometry.pdf for details @contextmanager def spec_from_commandline_args() -> Iterator[Spec]: args = _command_line_parser().parse_args() + texifier = PandocTexifier(args.pandoc or 'pandoc') with CachingFetcher(args.cache_path, args.timeout) as fetcher: with open(args.out + '.tex', 'wb') as texout: yield Spec( @@ -70,6 +72,6 @@ def spec_from_commandline_args() -> Iterator[Spec]: DiskImageStore(args.out + '_images', fetcher), lambda x: ApplyHTMLFilters(args.htmlfilters, x), lambda x: ApplyDOMFilters(args.domfilters, x), - PandocTexifier(args.pandoc or 'pandoc'), + BelowIconLayout(texifier), args.geometry, texout) diff --git a/glowfic.py b/glowfic.py index 4169786..0eab425 100644 --- a/glowfic.py +++ b/glowfic.py @@ -5,6 +5,7 @@ # Free Software Foundation, version 3. +from abc import ABC, abstractmethod from dataclasses import dataclass import itertools @@ -14,6 +15,7 @@ from bs4 import BeautifulSoup from bs4.element import Tag from images import ImageStore +from texify import Texifier @dataclass(frozen=True) @@ -77,3 +79,47 @@ def makeChunk(chunk_dom: Tag, image_store: ImageStore) -> Chunk: getTextByClass('post-screenname'), getTextByClass('post-author'), content) + + +def renderIcon(icon_path: str | None) -> bytes: + return b'\\includegraphics{%s}' % icon_path.encode( + 'UTF-8') if icon_path else b'' + + +class Layout(ABC): + + @abstractmethod + def renderChunk(self, chunk: Chunk) -> bytes: + raise NotImplementedError() + + +class ContentOnlyLayout(Layout): + + def __init__(self, texifier: Texifier) -> None: + self._texifier = texifier + + def renderChunk(self, chunk: Chunk) -> bytes: + return self._texifier.texify(chunk.content) + + +class BelowIconLayout(Layout): + + def __init__(self, texifier: Texifier) -> None: + self._texifier = texifier + + def renderChunk(self, chunk: Chunk) -> bytes: + icon_width = b'0.25\\textwidth' # TODO: Make this configurable + return b'''\\begin{wrapfigure}{l}{%s} +%s +%s +%s +%s +\\end{wrapfigure} +%s +''' % ( + icon_width, + renderIcon(chunk.icon), + chunk.character.encode('UTF-8') if chunk.character else b'', + chunk.screen_name.encode('UTF-8') if chunk.screen_name else b'', + chunk.author.encode('UTF-8') if chunk.author else b'', + self._texifier.texify(chunk.content)) diff --git a/paperdoorknob.py b/paperdoorknob.py index 160f0db..f8b3361 100644 --- a/paperdoorknob.py +++ b/paperdoorknob.py @@ -8,7 +8,7 @@ from bs4 import BeautifulSoup from args import spec_from_commandline_args -from glowfic import chunkDOMs +from glowfic import chunkDOMs, makeChunk from spec import Spec @@ -17,7 +17,10 @@ def parse(content: bytes) -> BeautifulSoup: def process(spec: Spec) -> None: - spec.texout.write(b'\\documentclass{article}\n\\usepackage{wrapfig}\n') + spec.texout.write(b'''\\documentclass{article} +\\usepackage{graphicx} +\\usepackage{wrapfig} +''') if spec.geometry is not None: spec.texout.write(b'\\usepackage[' + spec.geometry.encode('UTF-8') + @@ -26,7 +29,8 @@ def process(spec: Spec) -> None: html = parse(spec.htmlfilter(spec.fetcher.fetch(spec.url))) for r in chunkDOMs(html): spec.domfilter(r) - spec.texout.write(spec.texifier.texify(r)) + chunk = makeChunk(r, spec.images) + spec.texout.write(spec.layout.renderChunk(chunk)) spec.texout.write(b'\\end{document}\n') diff --git a/paperdoorknob_test.py b/paperdoorknob_test.py index 4291bb4..c1f8b60 100644 --- a/paperdoorknob_test.py +++ b/paperdoorknob_test.py @@ -15,6 +15,7 @@ import paperdoorknob from testing.fakeserver import FakeGlowficServer from domfilter import ApplyDOMFilters from fetch import DirectFetcher, FakeFetcher, Fetcher +from glowfic import ContentOnlyLayout, BelowIconLayout from images import FakeImageStore from spec import Spec from texify import DirectTexifier, PandocTexifier, VerifyingTexifier @@ -40,11 +41,12 @@ class BaseTestProcess(ABC): FakeImageStore(), lambda x: x, lambda x: ApplyDOMFilters('NoEdit,NoFooter', x), - PandocTexifier('pandoc'), + ContentOnlyLayout(PandocTexifier('pandoc')), 'margin=20mm', buf) paperdoorknob.process(spec) assert buf.getvalue() == b'''\\documentclass{article} +\\usepackage{graphicx} \\usepackage{wrapfig} \\usepackage[margin=20mm]{geometry} \\begin{document} @@ -64,7 +66,7 @@ Pretty sure. FakeImageStore(), lambda x: x, lambda x: ApplyDOMFilters('NoEdit,NoFooter', x), - texifier, + ContentOnlyLayout(texifier), None, buf) paperdoorknob.process(spec) @@ -77,7 +79,7 @@ Pretty sure. FakeImageStore(), lambda x: x, lambda x: ApplyDOMFilters('NoEdit,NoFooter', x), - PandocTexifier('pandoc'), + BelowIconLayout(PandocTexifier('pandoc')), None, out) paperdoorknob.process(spec) diff --git a/spec.py b/spec.py index 2b80f16..34e2e6b 100644 --- a/spec.py +++ b/spec.py @@ -12,7 +12,7 @@ from typing import Callable, IO from bs4.element import Tag from fetch import Fetcher -from texify import Texifier +from glowfic import Layout from images import ImageStore @@ -24,6 +24,6 @@ class Spec: images: ImageStore htmlfilter: Callable[[bytes], bytes] domfilter: Callable[[Tag], None] - texifier: Texifier + layout: Layout geometry: str | None texout: IO[bytes] diff --git a/testdata/this-is-glowfic.html b/testdata/this-is-glowfic.html index 22c7a37..207cdd1 100644 --- a/testdata/this-is-glowfic.html +++ b/testdata/this-is-glowfic.html @@ -2,17 +2,17 @@
We don't want edit boxes
- This is glowfic +
This is glowfic
We don't want edit boxes
- You sure? +
You sure?
- Pretty sure. +
Pretty sure.