Compare commits

..

No commits in common. "jk-bakalarka" and "master" have entirely different histories.

18 changed files with 98 additions and 546 deletions

2
.gitmodules vendored
View file

@ -2,5 +2,5 @@
path = ucwmac
url = git://git.ucw.cz/ucwmac.git
[submodule "src/formatitko/katex-server"]
path = src/formatitko/katex_server
path = src/formatitko/katex-server
url = https://gitea.ks.matfyz.cz:/KSP/formatitko-katex-server

30
formatitko.tex Normal file
View file

@ -0,0 +1,30 @@
\input luatex85.sty
\input ucwmac2.tex
\parskip=5pt plus 3pt minus 2pt
\parindent=0sp
\def\strong#1{{%
\def\emph##1{{\bi{}##1}}%
\bf{}#1%
}}
\def\emph#1{{%
\def\strong##1{{\bi{}##1}}%
\it{}#1%
}}
\def\superscript#1{\leavevmode\raise3pt\hbox{\fiverm#1}}
\def\subscript#1{\leavevmode\lower1pt\hbox{\fiverm#1}}
\newcount\fncount
\fncount=1
\def\fnmark{\superscript{\the\fncount}}
\def\fn#1{\footnote\fnmark{#1}\advance\fncount by 1}
\def\section#1{{\parskip1em\settextsize{18}\bf #1}}
\def\subsection#1{{\parskip1em\settextsize{16}\bf #1}}
\def\subsubsection#1{{\parskip1em\settextsize{14}\bf #1}}
\def\subsubsubsection#1{{\parskip1em\settextsize{12}\bf #1}}
\def\subsubsubsubsection#1{{\parskip1em\settextsize{10}\bf #1}}
\def\subsubsubsubsubsection#1{{\parskip1em\settextsize{10}\bi #1}}
\long\def\blockquote#1{\vskip\lineskip\vskip\parskip\hbox{\vrule\hskip5pt\vbox{#1}}}
\def\strikeout#1{FIXME: Strikeout not implemented}
\def\underline#1{FIXME: Underline not implemented}

View file

@ -33,19 +33,11 @@ dependencies = [
[project.scripts]
formatitko = "formatitko.formatitko:main"
[tool.setuptools.package-data]
"formatitko.katex_server" = [
"*",
"node_modules/*",
"node_modules/katex/*",
"node_modules/katex/src/*",
"node_modules/katex/dist/*",
]
[tool.setuptools_scm]
[tool.setuptools.packages.find]
where = ["src"]
exclude = ["src/formatitko/katex-server/node_modules"]
[tool.pyright]
strictParameterNoneValue = false

View file

@ -1,4 +1,4 @@
from panflute import Doc, Element, Div, Span, Header, Figure
from panflute import Doc, Element, Div, Span
from typing import Union, Callable
from types import ModuleType
@ -19,23 +19,6 @@ CommandCallable = Callable[[Command, 'Context', 'NOPProcessor'], list[Element]]
#
# This class is basically an extension to panflute's doc, this is why metadata
# is read directly from it.
def default_section_number_generator(e: Header, context: 'Context') -> list[Union[str, int]]:
l = e.level
section_counters = context.get_data("section_counters")
section_counters[l-1] += 1
for i in range(l, len(section_counters)):
section_counters[i] = 0
return list(section_counters[:l])
def default_figure_number_generator(e: Figure, context: 'Context') -> Union[str, int]:
figure_type = e.attributes.get("type", "img")
figure_counters = context.get_data("figure_counters")
figure_counters.setdefault(figure_type, 0)
figure_counters[figure_type] += 1
return figure_counters[figure_type]
class Context:
parent: Union["Context", None]
_commands: dict[str, Union[CommandCallable, None]]
@ -49,9 +32,6 @@ class Context:
rel_dir: str # Relative path to the current dir from the root dir
deps: set[str]
section_counters: list[int]
number_generator: Callable[[Header, 'Context'], str]
def __init__(self, doc: Doc, path: str, parent: Union['Context', None]=None, trusted: bool=True):
self.parent = parent
self._commands = {}
@ -67,12 +47,6 @@ class Context:
self.add_dep(path)
if self.get_metadata("flags", immediate=True) is None:
self.set_metadata("flags", {})
if not parent:
self.set_data('section_number_generator', default_section_number_generator)
self.set_data('figure_number_generator', default_figure_number_generator)
self.set_data('section_counters', [0 for i in range(6)])
self.set_data('figure_counters', {})
self.set_data('obj_map', {})
def get_command(self, command: str) -> Union[CommandCallable, None]:
if command in self._commands:

View file

@ -1,4 +1,4 @@
from panflute import Quoted, Emph, Link, Div
from panflute import Quoted, Link
from .command import Command, InlineCommand, BlockCommand, CodeCommand
@ -14,22 +14,6 @@ class FQuoted(Quoted):
del kwargs["style"]
super().__init__(*args, **kwargs)
class Slanted(Emph):
pass
class FLink(Link):
obj_map: map
def __init__(self, *args, **kwargs):
self.obj_map = kwargs["obj_map"]
del kwargs["obj_map"]
super().__init__(*args, **kwargs)
class FileLink(Link):
pass
class FLineMarkup(Div):
def __init__(self, *args, **kwargs):
self.color = kwargs["color"]
del kwargs["color"]
super().__init__(*args, **kwargs)

View file

@ -2,11 +2,9 @@
import argparse
import sys
import os
import tempfile
import subprocess
import shutil
from pathlib import Path
# Import local files
from .util import import_md
@ -114,12 +112,7 @@ def main():
else:
filename = args.output_tex
outdir = tempfile.TemporaryDirectory(prefix="formatitko")
env = os.environ.copy()
d = Path("/".join(__file__.split("/")[:-1]))
env["TEXINPUTS"]=".:"+str(d/"tex")+":"+env.get("TEXINPUTS", "")
subprocess.run(["luatex", "-halt-on-error", "-output-directory="+outdir.name, "-jobname=formatitko", filename], check=True, env=env)
subprocess.run(["pdfcsplain", "-halt-on-error", "-output-directory="+outdir.name, "-jobname=formatitko", filename], check=True)
shutil.move(outdir.name+"/formatitko.pdf", args.output_pdf)
if args.deps is not None:

View file

@ -111,7 +111,7 @@ class HTMLGenerator(OutputGenerator):
def generate_CodeBlock(self, e: CodeBlock):
lexer = None
if e.classes and len(e.classes) > 0 and (e.attributes.get("highlight", False) in [True, 'True']):
if e.classes and len(e.classes) > 0 and (e.attributes["highlight"] == True or e.attributes["highlight"] == 'True'):
# Syntax highlighting using pygments
for cl in e.classes:
try:
@ -123,7 +123,7 @@ class HTMLGenerator(OutputGenerator):
warnings.warn(f"Syntax highligher does not have lexer for element with these classes: {e.classes}", UserWarning)
if lexer:
formatter = HtmlFormatter(style=e.attributes.get("style", self.context.get_metadata("highlight-style")), noclasses=True)
formatter = HtmlFormatter(style=e.attributes["style"], noclasses=True)
result = highlight(e.text, lexer, formatter)
self.writeraw(result)
else:
@ -344,9 +344,6 @@ class HTMLGenerator(OutputGenerator):
def generate_DefinitionList(self, e: DefinitionList):
self.writeln("<!-- FIXME: DefinitionLists not implemented -->")
def generate_SmallCaps(self, e: SmallCaps):
self.generate_simple_tag(e, attributes=self.common_attributes(e) | {"style": "font-variant: small-caps;"})
class StandaloneHTMLGenerator(HTMLGenerator):
def generate_Doc(self, e: Doc):

View file

@ -46,20 +46,20 @@ class KatexClient:
srcdir = os.path.dirname(os.path.realpath(__file__))
# Test if `node_modules` directory exists and if not, run `npm install`
if not os.path.isdir(srcdir + "/katex_server/node_modules"):
if not os.path.isdir(srcdir + "/katex-server/node_modules"):
print("Installing node dependencies for the first time...")
npm = shutil.which("npm") or shutil.which("yarnpkg")
if npm is None:
raise NPMNotFoundError("npm not found. Node.js is required to use KaTeX.")
subprocess.run([npm, "install"], cwd=srcdir+"/katex_server", check=True)
subprocess.run([npm, "install"], cwd=srcdir+"/katex-server", check=True)
self._katex_server_path = srcdir + "/katex_server/index.mjs"
self._katex_server_path = srcdir + "/katex-server/index.mjs"
self._server_process = subprocess.Popen(["node", self._katex_server_path, self._socket_file], stdout=subprocess.PIPE)
ok = self._server_process.stdout.readline()
if ok != b"OK\n":
raise KatexServerError("Failed to connect to katex_server")
raise KatexServerError("Failed to connect to katex-server")
def connect(self):
self._client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

View file

@ -6,7 +6,7 @@ from panflute import MetaValue
from typing import Union, Callable
from .whitespace import NBSP
from .elements import FQuoted, Slanted, FLink, FileLink
from .elements import FQuoted, FileLink
from .context import Group, InlineGroup, BlockGroup, Context
from .whitespace import Whitespace
from .command import BlockCommand, InlineCommand, CodeCommand, Command
@ -69,7 +69,6 @@ class NOPProcessor:
Cite: self.transform_Cite,
Code: self.transform_Code,
Emph: self.transform_Emph,
Slanted: self.transform_Slanted,
Image: self.transform_Image,
LineBreak: self.transform_LineBreak,
Link: self.transform_Link,
@ -89,7 +88,6 @@ class NOPProcessor:
Underline: self.transform_Underline,
NBSP: self.transform_NBSP,
FQuoted: self.transform_FQuoted,
FLink: self.transform_FLink,
FileLink: self.transform_FileLink,
InlineCommand: self.transform_InlineCommand,
@ -266,10 +264,6 @@ class NOPProcessor:
e.content = self.transform(e.content)
return e
def transform_Slanted(self, e: Slanted) -> Slanted:
e.content = self.transform(e.content)
return e
def transform_Link(self, e: Link) -> Link:
e.content = self.transform(e.content)
return e
@ -306,9 +300,6 @@ class NOPProcessor:
e.content = self.transform(e.content)
return e
def transform_FLink(self, e: FLink) -> FLink:
return self.transform_Link(e)
def transform_FileLink(self, e: FileLink) -> FileLink:
e.content = self.transform(e.content)
return e

View file

@ -7,7 +7,7 @@ from panflute import stringify
from typing import Union, Callable
from .whitespace import NBSP
from .elements import FQuoted, Slanted, FLink, FileLink, FLineMarkup
from .elements import FQuoted, FileLink
from .context import Group, InlineGroup, BlockGroup, Context
@ -88,7 +88,6 @@ class OutputGenerator:
DefinitionItem: self.generate_DefinitionItem,
DefinitionList: self.generate_DefinitionList,
Div: self.generate_Div,
FLineMarkup: self.generate_FLineMarkup,
Figure: self.generate_Figure,
Header: self.generate_Header,
HorizontalRule: self.generate_HorizontalRule,
@ -109,7 +108,6 @@ class OutputGenerator:
Cite: self.generate_Cite,
Code: self.generate_Code,
Emph: self.generate_Emph,
Slanted: self.generate_Slanted,
Image: self.generate_Image,
LineBreak: self.generate_LineBreak,
Link: self.generate_Link,
@ -129,7 +127,6 @@ class OutputGenerator:
Underline: self.generate_Underline,
NBSP: self.generate_NBSP,
FQuoted: self.generate_FQuoted,
FLink: self.generate_FLink,
FileLink: self.generate_FileLink,
InlineGroup: self.generate_InlineGroup
}
@ -382,17 +379,11 @@ class OutputGenerator:
def generate_Emph(self, e: Emph):
self.generate_simple_tag(e)
def generate_Slanted(self, e: Slanted):
self.generate_Emph(e)
def generate_Image(self, e: Image):
self.generate_simple_tag(e)
def generate_Link(self, e: Link):
self.generate_simple_tag(e)
def generate_FLink(self, e: FLink):
self.generate_Link(e)
def generate_Note(self, e: Note):
self.generate_simple_tag(e)
@ -463,9 +454,6 @@ class OutputGenerator:
def generate_Div(self, e: Div):
self.generate_simple_tag(e)
def generate_FLineMarkup(self, e: FLineMarkup):
self.generate_Div(e)
def generate_Header(self, e: Header):
self.generate_simple_tag(e)

View file

@ -1,189 +0,0 @@
\input ltluatex.tex
\input luatex85.sty
\input ucwmac2.tex
\ucwmodule{luaofs}
\ucwmodule{verb}
\ucwmodule{link}
\clickablefalse
\pdfglyphtounicode{summationtext}{2211}
\pdfglyphtounicode{summationdisplay}{2211}
\pdfglyphtounicode{summation}{2211}
\pdfglyphtounicode{parenleftbig}{0028}
\pdfglyphtounicode{parenrightbig}{0029}
\pdfglyphtounicode{parenleftBig}{0028}
\pdfglyphtounicode{parenrightBig}{0029}
\pdfglyphtounicode{parenleftbigg}{0028}
\pdfglyphtounicode{parenrightbigg}{0029}
\pdfglyphtounicode{parenleftBigg}{0028}
\pdfglyphtounicode{parenrightBigg}{0029}
\pdfglyphtounicode{radicalbig}{221A}
\pdfglyphtounicode{radicalBig}{221A}
\pdfglyphtounicode{radicalbigg}{221A}
\pdfglyphtounicode{radicalBigg}{221A}
\pdfglyphtounicode{hatwidest}{0302}
\input formatitkolib.tex
\input minim-xmp.tex
\startmetadata
pdfaid:part 2
pdfaid:conformance U
stopmetadata
\pdfcompresslevel=0
\pdfobjcompresslevel=0
% \pdfobj{/Alternate /DeviceRGB}
\input glyphtounicode.tex
\pdfgentounicode=1
%Create an OutputIntent in order to correctly specify colours
\immediate\pdfobj stream attr{/N 3} file{sRGB.icc}
\pdfcatalog{%
/OutputIntents [
<<
/Type /OutputIntent
/S /GTS_PDFA1
/DestOutputProfile \the\pdflastobj\space 0 R
/OutputConditionIdentifier (sRGB)
/Info (sRGB)
>>
]
}
\parskip=5pt plus 3pt minus 2pt
\parindent=0sp
% Fonty
\ofsdeclarefamily [Pagella] {%
\loadtextfam qplr;%
qplb;%
qpli;%
qplbi;;%
}
% doporučen je horní, dolní a pravý okraj 25 mm, levý okraj 40 mm.
% Protože doba tisknutí prací je už pryč, my máme stejně velkou stránku uprostřed papíru
\voffset 25mm
\hoffset 32.5mm
\vsize\pdfpageheight
\advance\vsize -2\voffset
\hsize\pdfpagewidth
\advance\hsize -2\hoffset
\advance\voffset -\pdfvorigin
\advance\hoffset -\pdfhorigin
\def\MSfeat#1{:mode=node;script=latn;+tlig}
\registertfm qplr - file:texgyrepagella-regular.otf\MSfeat{}
\registertfm qplb - file:texgyrepagella-bold.otf\MSfeat{}
\registertfm qpli - file:texgyrepagella-italic.otf\MSfeat{}
\registertfm qplbi - file:texgyrepagella-bolditalic.otf\MSfeat{}
%\setfonts[Pagella/10]
%\def\h{\it} % hint
%\def\bh{\bi} % bold hint
\def\mod{\mathrel{\rm mod}}
\settextsize{12}
\long\def\floatinsert#1{\par{
\setbox0=\vbox{\boxmaxdepth=2pt\relax #1}
\dimen0=\dimexpr \ht0 + \dp0 + \baselineskip + \pagetotal - \pageshrink \relax
\ifdim\dimen0 > \pagegoal
\insert\topins{
\penalty 100
\splittopskip=0pt
\splitmaxdepth=\maxdimen
\floatingpenalty=0
\box0
\nobreak\bigskip\medskip
}
\else
\goodbreak\bigskip
\box0
\goodbreak\bigskip
\unparskip
\fi
}}
% Obecny plovouci objekt: \float{objekt}{popisek}{mezera pred}{mezera po}
\long\def\figure#1#2#3#4{
\medskip#3
\hbox to \hsize{\hfil\vtop{
\parindent=0pt
\leftskip=0pt plus 0.2\hsize
\rightskip=0pt plus 0.2\hsize
\parfillskip=0pt
\spaceskip=0.3333em
\settextsize{10}
#1
}\hfil}#4
\medskip
\smallskip
{
\setbox0=\hbox{\settextsize{10}#2}
\ifdim\wd0 < 0.8\hsize
\centerline{\box0}
\else
\centerline{\vtop{
\hsize=0.8\hsize
\parindent=0pt
\leftskip=0pt plus 0.3\hsize
\rightskip=0pt plus 0.3\hsize
\parfillskip=0pt
\spaceskip=0.3333em
\settextsize{10}#2
}}
\fi
}}
\long\def\floatpage#1{
\pageinsert
\vbox to \vsize{#1}
\endinsert
}
% Dva floaty vedle sebe: \float{objekt1}{popisek1}{id1}{objekt2}{popisek2}{id2}
\def\twofloats#1#2#3#4#5#6{\floatinsert{
\medskip
\centerline{\vbox{\halign{\hss##\hss&\qquad\hss##\hss\cr
#1&#4\cr
\noalign{\medskip\smallskip}
#2&#5\cr
}}}
}}
% Obsah a odkazy
\newwrite\tocfile
\immediate\openout\tocfile=toc-new.aux
% Voláme: \addtoc\tocmacro{number}{asterisks}{title}
\long\def\addtoc#1#2#3#4{%
\edef\brum{%
\write\tocfile{\string#1{\noexpand\the\noexpand\count0}{#2}{#3}{#4}}%
}
\brum%
}

View file

@ -1,79 +0,0 @@
\def\strong#1{{%
\def\emph##1{{\bi{}##1}}%
\bf{}#1%
}}
\def\emph#1{{%
\def\strong##1{{\bi{}##1}}%
\it{}#1%
}}
\def\textasciitilde{$\sim$}
\def\N{{\bb N}}
\def\R{{\bb R}}
\def\E{{\bb E}}
\def\O{{\cal O}}
\def\SYM{{\rm SYM}}
\def\frac#1#2{{{#1} \over {#2}}}
\def\superscript#1{$^{\hbox{\settextsize{0.8\textsize}#1}}$}
\def\subscript#1{$_{\hbox{\settextsize{0.8\textsize}#1}}$}
\newcount\fncount
\fncount=1
\def\fnmark{$^{\the\fncount}$}
\def\fn#1{\footnote\fnmark{#1}\advance\fncount by 1}
\def\sectioneject{\vfil\supereject}
\def\section#1#2{
\sectioneject
\vskip 16pt\vbox{\settextsize{20}\bf #1\kern 1em\relax#2%
\addtoc\tocsection{#1}{}{#2}%
}\nobreak\vskip 12pt
}
\def\subsection#1#2{
\vskip 12pt\vbox{\settextsize{18}\bf #1\kern 1em\relax#2%
\addtoc\tocsubsection{#1}{}{#2}%
}\nobreak\vskip 7pt
}
\def\subsubsection#1#2{
\vskip 10pt\vbox{\settextsize{16}\bf #1\kern 1em\relax#2%
\addtoc\tocsubsubsection{#1}{}{#2}%
}\nobreak\vskip 6pt
}
\def\subsubsubsection#1#2{
\vskip 8pt\vbox{\settextsize{14}\bf #1\kern 1em\relax#2}\nobreak\vskip 5pt
}
\def\subsubsubsubsection#1#2{
\vskip 7pt\vbox{\settextsize{12}\bf #1\kern 1em\relax#2}\nobreak\vskip 5pt
}
\def\subsubsubsubsubsection#1#2{
\vskip 7pt\vbox{\settextsize{12}\bf #1\kern 1em\relax#2}\nobreak\vskip 5pt
}
\long\def\blockquote#1{\vskip\lineskip\vskip\parskip\hbox{\vrule\hskip5pt\vbox{#1}}}
\def\strikeout#1{FIXME: Strikeout not implemented}
\def\underline#1{FIXME: Underline not implemented}
\def\mathbb#1{\hbox{\bb #1}}
\def\unparskip{\vskip-\parskip}
\catcode`@=11
\def\vecoverrightarrow#1{\mathpalette\vecoverrightarrowtmp{#1}}
\def\vecoverrightarrowtmp#1#2{\vbox{\m@th\ialign{##\crcr
\vecrightarrowfill\crcr\noalign{\kern-\p@\kern 0.09em\nointerlineskip}
$\hfil#1{#2\,}\hfil$\crcr}}}
\def\vecrightarrowfill{$\settextsize{5}\m@th\smash-\mkern-7mu%
\cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
\settextsize{5}\mkern-7mu\mathord\rightarrow$}
\catcode`@=12
\long\def\linemarkup#1#2{%
\par\noindent\hbox{%
\hbox{}\hskip -6pt {\colorlocal{#1}\vrule width 1pt \hskip 5pt}%
\hbox to \hsize{\vbox{#2}\hfil}%
%\hbox{}\hskip 5pt {\colorlocal{#1}\vrule width 1pt \hskip -6pt}%
}\par%
}

View file

@ -1,22 +0,0 @@
{
\def\pagelink#1{#1}
\def\toclink#1#2{%
#2
}
\def\stdskip{\vskip 3pt}
\def\tocsection#1#2#3#4{
\line{\bf\hbox to 2em{#2\hfil}#4~\hfil\pagelink{#1}}
}
\def\tocsubsection#1#2#3#4{
\line{\hskip 1.5cm \hbox to 3em{#2\hfil}#4~\hfil\pagelink{#1}}
}
\def\tocsubsubsection#1#2#3#4{
\line{\hskip 3cm \hbox to 4em{#2\hfil}#4~\hfil\pagelink{#1}}
}
\def\tocpicture#1#2#3#4{}
\vskip 1cm
\input toc.aux
}

View file

@ -1,18 +0,0 @@
{
\def\pagelink#1{#1}
\def\toclink#1#2{%
#2
}
\def\stdskip{\vskip 3pt}
\def\tocsection#1#2#3#4{}
\def\tocsubsection#1#2#3#4{}
\def\tocsubsubsection#1#2#3#4{}
\def\tocpicture#1#2#3#4{
\line{\hbox to 2em{#2\hfil}#4~\hfil\pagelink{#1}}\stdskip
}
\vskip 1cm
\input toc.aux
}

View file

@ -11,14 +11,10 @@ from .output_generator import OutputGenerator
from .images import ImageProcessor, ImageProcessorNamespaceSearcher
from .whitespace import NBSP
from .elements import FQuoted, FLineMarkup
from .elements import FQuoted
from .context import Group, InlineGroup, BlockGroup, Context
from .util import inlinify
def color_to_rgb(color):
import matplotlib.colors
return matplotlib.colors.to_rgb(color)
class UCWTexGenerator(OutputGenerator):
imageProcessor: ImageProcessor
_bold: int
@ -28,30 +24,22 @@ class UCWTexGenerator(OutputGenerator):
self.imageProcessor = imageProcessor
self._bold = 0
self._italic = 0
self._floatpages = {}
super().__init__(output_file, *args, **kwargs)
def escape_special_chars(self, text: str) -> str:
if '\\' in text:
print("ESCAPE", text)
out = ""
for char in text:
out += {
'&': r"\&",
'%': r"\%",
'$': r"\$",
'#': r"\#",
'_': r"\_",
'{': r"\{",
'}': r"\}",
'~': r"\textasciitilde{}",
'^': r"\textasciicircum{}",
'\\': r"\textbackslash{}",
' ': r"~",
'': r"",
}.get(char, char)
return out
text = text.replace("&", r"\&")
text = text.replace("%", r"\%")
text = text.replace("$", r"\$")
text = text.replace("#", r"\#")
text = text.replace("_", r"\_")
text = text.replace("{", r"\{")
text = text.replace("}", r"\}")
text = text.replace("~", r"\textasciitilde{}")
text = text.replace("^", r"\textasciicircum{}")
text = text.replace("\\", r"\textbackslash{}")
text = text.replace(" ", "~") # We use unicode no-break spaces to force nbsp in output
text = text.replace("", "")
return text
def generate(self, e: Union[Element, ListContainer]):
if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex":
@ -79,17 +67,21 @@ class UCWTexGenerator(OutputGenerator):
self.writepar(r"\vskip5pt\hrule\hfil\vskip5pt{}")
def generate_Doc(self, e: Doc):
self.writeln(r"\input ucwmac2.tex")
self.writeln(r"\ucwmodule{ofs}")
self.writeln(r"\ucwmodule{verb}")
self.writeln(r"\ucwmodule{link}")
self.writeln(r"\input formatitko.tex")
self.generate(e.content)
self.writeln(r"\bye")
def get_language_macro(self, lang: str):
if lang == "cs":
return r"\uselanguage{czech}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
return r"\chyph\lefthyphenmin=2\righthyphenmin=2{}"
elif lang == "sk":
return r"\uselanguage{slovak}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
return r"\shyph\lefthyphenmin=2\righthyphenmin=2{}"
elif lang == "en":
return r"\uselanguage{USenglish}\nonfrenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
return r"\ehyph\lefthyphenmin=2\righthyphenmin=2{}"
else:
return ""
@ -109,7 +101,7 @@ class UCWTexGenerator(OutputGenerator):
def generate_Header(self, e: Header):
self.ensure_empty(2)
self.write("\\"+"sub"*(e.level-1)+"section{"+".".join(map(str, e.attributes["number"]))+"}{")
self.write("\\"+"sub"*(e.level-1)+"section{")
self.generate(e.content)
self.write(r"}")
self.ensure_empty(2)
@ -155,58 +147,31 @@ class UCWTexGenerator(OutputGenerator):
width = str(int(e.attributes["width"][:-1])/100) + "\\hsize"
width = "width " + width
self.writeln(f'\\centerline{{\\putimage{{{width}}}{{{url}}}}}')
if isinstance(e.parent.parent, Figure):
self.writeln(f'\\putimage{{{width}}}{{{url}}}')
else:
self.writepar(f'\\putimage{{{width}}}{{{url}}}')
def generate_Code(self, e: Code):
self.write(r"\verb`")
self.write(e.text)
self.write(r"`")
def generate_nonfloat_Figure(self, e: Figure):
self.writeln(r"\figure{")
def generate_Figure(self, e: Figure):
self.ensure_empty(2)
self.writeln(r"\vskip5pt")
self.writeln(r"\centerline{")
self.indent_more()
self.generate(e.content)
self.indent_less()
self.writeln(r"}{")
self.writeln(r"}")
self.writeln(r"\centerline{")
self.indent_more()
if 'number' in e.attributes:
type_text = e.attributes.get("type_text", "Obrázek")
self.writeln(f"{type_text} {e.attributes['number']}:")
self.generate(e.caption)
if 'number' in e.attributes:
tocmac = e.attributes.get("tocmac", "tocpicture")
if tocmac:
self.writeln("\\addtoc\\"+tocmac+r"{"+str(e.attributes['number'])+"}{}{")
self.indent_more()
self.generate(e.caption.content)
self.indent_less()
self.writeln("}")
self.indent_less()
self.writeln(r"}{}{}")
def generate_Figure(self, e: Figure):
if "floatpage" in e.attributes:
fp = e.attributes["floatpage"]
flush = fp[-1]=="!"
if flush:
fp = fp[:-1]
self._floatpages.setdefault(fp, [])
self._floatpages[fp].append(e)
if flush:
self.writeln(r"\floatpage{")
self.writeln(r"\vfill")
for x in self._floatpages[fp]:
self.generate_nonfloat_Figure(x)
self.writeln(r"\vfill")
self.writeln(r"}")
del self._floatpages[fp]
else:
self.ensure_empty(2)
self.writeln(r"\floatinsert{")
self.generate_nonfloat_Figure(e)
self.writeln(r"}")
self.ensure_empty(2)
self.writeln(r"}")
self.writeln(r"\vskip5pt{}")
self.ensure_empty(2)
def generate_Emph(self, e: Emph):
if self._bold > 0:
@ -218,11 +183,6 @@ class UCWTexGenerator(OutputGenerator):
self._italic-=1
self.write(r"}")
def generate_Slanted(self, e: Emph):
self.write(r"{\sl{}")
self.generate(e.content)
self.write(r"}")
def generate_Strong(self, e: Strong):
if self._italic > 0:
self.write(r"{\bi{}")
@ -234,15 +194,15 @@ class UCWTexGenerator(OutputGenerator):
self.write(r"}")
def generate_Caption(self, e: Caption):
self.generate(e.content)
self.generate_Emph(e)
def generate_Math(self, e: Math):
if e.format == "DisplayMath":
self.ensure_empty(1)
self.ensure_empty(2)
self.writeraw("$$")
self.writeraw(e.text.strip())
self.writeraw("$$")
self.ensure_empty(1)
self.ensure_empty(2)
else:
self.write("$")
self.write(e.text)
@ -254,23 +214,22 @@ class UCWTexGenerator(OutputGenerator):
self.write(r"}")
def generate_Table(self, e: Table):
hskip = r"\hskip 0.6em\relax"
aligns = {
"AlignLeft": hskip+r"\relax#\hfil"+hskip,
"AlignRight": hskip+r"\hfil#"+hskip,
"AlignCenter": hskip+r"\hfil#\hfil"+hskip,
"AlignDefault": hskip+r"#\hfil"+hskip,
"AlignLeft": r"\quad#\quad\hfil",
"AlignRight": r"\quad\hfil#\quad",
"AlignCenter": r"\quad\hfil#\hfil\quad",
"AlignDefault": r"\quad#\quad\hfil"
}
self.writeln(r"\vskip1em")
self.writeln(r"\leavevmode\vbox{\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr")
self.writeln(r"\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr")
self.indent_more()
self.generate(e.head.content)
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}")
self.writeln(r"\noalign{\hrule}")
self.generate(e.content[0].content)
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}")
self.writeln(r"\noalign{\hrule}")
self.generate(e.foot.content)
self.indent_less()
self.writeln("}}")
self.writeln("}")
self.writeln(r"\vskip1em")
def generate_TableRow(self, e: TableRow):
@ -304,16 +263,6 @@ class UCWTexGenerator(OutputGenerator):
def generate_Div(self, e: Div):
self.generate(e.content)
def generate_FLineMarkup(self, e: FLineMarkup):
self.ensure_empty(2)
r,g,b = color_to_rgb(e.color)
self.writeln(r"\linemarkup{\rgb{"+f"{r} {g} {b}"+"}}{")
self.indent_more()
self.generate(e.content)
self.indent_less()
self.writeln(r"}")
self.ensure_empty(2)
def generate_LineBlock(self, e: LineBlock):
self.writeln()
@ -374,11 +323,6 @@ class UCWTexGenerator(OutputGenerator):
self.writeln(r"}")
def generate_Link(self, e: Link):
if len(e.content) == 0:
if e.url.startswith('#'):
obj = e.obj_map[e.url[1:]]
self.write(str(obj.attributes["number"]))
return
if len(e.content) == 1 and isinstance(e.content[0], Str) and e.content[0].text == e.url:
self.write(r"\url{")
else:
@ -404,7 +348,7 @@ class UCWTexGenerator(OutputGenerator):
self.writeln("% FIXME: Citations not implemented")
def generate_Cite(self, e: Cite):
self.generate(e.content)
self.writeln("% FIXME: Cites not implemented")
def generate_Definition(self, e: Definition):
self.writeln("% FIXME: Definitions not implemented")
@ -420,8 +364,3 @@ class UCWTexGenerator(OutputGenerator):
def generate_Strikeout(self, e: Strikeout):
self.writeln("% FIXME: Strikeouts not implemented")
def generate_SmallCaps(self, e: Strikeout):
self.write(r"{\csc{}")
self.generate(e.content)
self.write(r"}")

View file

@ -14,7 +14,7 @@ import importlib
import json
from .whitespace import NBSP
from .elements import FQuoted, Slanted, FLink
from .elements import FQuoted
from .context import Group, InlineGroup, BlockGroup
from .util import nullify, import_md
from .context import Context, CommandCallable
@ -228,12 +228,12 @@ class TransformProcessor(NOPProcessor):
importedDoc = import_md(open(filename, "r").read())
self.transform(importedDoc.content)
elif e.attributes["type"] == "module":
matches = re.match(r"^([\w\.]+)(?: as (\w+))?$", e.content[0].text[1:])
matches = re.match(r"^(\w+)(?: as (\w+))?$", e.content[0].text[1:])
if not matches:
raise SyntaxError(f"`{e.content[0].text[1:]}`: invalid syntax")
module = importlib.import_module(matches.group(1))
module_name = matches.group(1) if matches.group(2) is None else matches.group(2)
self.context.add_commands_from_module(module, "")
self.context.add_commands_from_module(module, module_name)
elif e.attributes["type"] == "metadata":
filename = self.context.dir + "/" + e.content[0].text[1:]
self.context.add_dep(filename)
@ -260,11 +260,6 @@ class TransformProcessor(NOPProcessor):
raise TypeError(f"Cannot print value of metadatum '{e.content[0].text[1:]}' of type '{type(val)}'")
return e
if "slanted" in e.classes:
# `.slanted` class for Span
# Content of Span is enclosed into Slanted (subclass os Emph)
return self.transform(Slanted(*e.content))
return super().transform_Span(e)
def transform_CodeBlock(self, e: CodeBlock) -> Union[CodeBlock, Div, Null]:
@ -311,26 +306,3 @@ class TransformProcessor(NOPProcessor):
else:
return e
def transform_Header(self, e: Header) -> Header:
if "number" not in e.attributes:
if 'unnumbered' in e.classes:
e.attributes["number"] = ""
else:
e.attributes["number"] = self.context.get_data("section_number_generator")(e, self.context)
return e
def transform_Figure(self, e: Figure) -> Figure:
if "number" not in e.attributes:
if 'unnumbered' in e.classes:
e.attributes["number"] = ""
else:
e.attributes["number"] = self.context.get_data("figure_number_generator")(e, self.context)
self.context.get_data("obj_map")[e.identifier] = e
self.context.set_data("current_figure", e)
r = super().transform_Figure(e)
self.context.unset_data("current_figure")
return r
def transform_Link(self, e: Link) -> Link:
e = FLink(*e.content, url=e.url, identifier=e.identifier, attributes=e.attributes, classes=e.classes, obj_map=self.context.get_data("obj_map"))
return super().transform_Link(e)

View file

@ -66,14 +66,14 @@ raise Exception("Jsem piča")
-->
![This is a figure, go figure...](logo.svg){width=25%}What
![This is a figure, go figure...](logo.pdf){width=50%}
![Fakt epesní reproduktor](reproduktor.jpeg){width=10em}
![Fakt epesní reproduktor](reproduktor.png "Hodně rozpixelovaný obrázek reproduktoru"){width=10em file-width=1000}
```
![This is a figure, go figure...](logo.jpg){width=50%}
![This is a figure, go figure...](logo1.png){width=10em}
![Fakt epesní reproduktor](reproduktor.jpeg){width=10em}
![Fakt epesní reproduktor](reproduktor.png "Hodně rozpixelovaný obrázek reproduktoru"){width=10em file-width=1000}