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
@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(
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)
# Free Software Foundation, version 3.
+from abc import ABC, abstractmethod
from dataclasses import dataclass
import itertools
from bs4.element import Tag
from images import ImageStore
+from texify import Texifier
@dataclass(frozen=True)
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))
from bs4 import BeautifulSoup
from args import spec_from_commandline_args
-from glowfic import chunkDOMs
+from glowfic import chunkDOMs, makeChunk
from spec import Spec
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') +
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')
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
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}
FakeImageStore(),
lambda x: x,
lambda x: ApplyDOMFilters('NoEdit,NoFooter', x),
- texifier,
+ ContentOnlyLayout(texifier),
None,
buf)
paperdoorknob.process(spec)
FakeImageStore(),
lambda x: x,
lambda x: ApplyDOMFilters('NoEdit,NoFooter', x),
- PandocTexifier('pandoc'),
+ BelowIconLayout(PandocTexifier('pandoc')),
None,
out)
paperdoorknob.process(spec)
from bs4.element import Tag
from fetch import Fetcher
-from texify import Texifier
+from glowfic import Layout
from images import ImageStore
images: ImageStore
htmlfilter: Callable[[bytes], bytes]
domfilter: Callable[[Tag], None]
- texifier: Texifier
+ layout: Layout
geometry: str | None
texout: IO[bytes]
<body>
<div class="post-container post-post">
<div class="post-edit-box">We don't want edit boxes</div>
- This is glowfic
+ <div class="post-content">This is glowfic</div>
<div class="post-footer">We don't want footers</div>
</div>
<div class="flat-post-replies">
<div class="post-container post-reply">
<div class="post-edit-box">We don't want edit boxes</div>
- You <em>sure</em>?
+ <div class="post-content">You <em>sure</em>?</div>
<div class="post-footer">We don't want footers</div>
</div>
<div class="post-container post-reply">
- Pretty sure.
+ <div class="post-content">Pretty sure.</div>
</div>
</div>
</body>