Compare commits
48 commits
master
...
jk-bakalar
Author | SHA1 | Date | |
---|---|---|---|
27ff4b7d58 | |||
ef18947916 | |||
7ee84470e9 | |||
9255f77d93 | |||
a9f41eb83e | |||
17920077da | |||
5a61ea5fac | |||
73af3473c7 | |||
6bfb62fcdd | |||
4e2ea4173e | |||
8bcb087979 | |||
2a5fd812e3 | |||
c46a1f0302 | |||
9a993676dc | |||
87961754e8 | |||
08df4dbd78 | |||
57e69cbee4 | |||
f86815e8ff | |||
bb05a3c913 | |||
9dcf87915e | |||
ac2c3475e4 | |||
2fd0efe3a7 | |||
4bd05b098b | |||
86839a9269 | |||
774af0fedf | |||
38029e3587 | |||
6d629137fb | |||
ed40bc4db8 | |||
292fcba574 | |||
d783c7ae9c | |||
71e5c5bbdc | |||
fb80c61139 | |||
7230d87f6b | |||
bf46105db8 | |||
41f51bf6fe | |||
f1f2f63cb5 | |||
a2468b54e1 | |||
945bb760e8 | |||
88d653af15 | |||
4dd1eb0314 | |||
48e34eaf8e | |||
37c8ec4e2e | |||
62263fbe0f | |||
f97ee7de52 | |||
7783dc25f4 | |||
405a4f396c | |||
affc2c4279 | |||
a15a711d0f |
18 changed files with 546 additions and 98 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -2,5 +2,5 @@
|
||||||
path = ucwmac
|
path = ucwmac
|
||||||
url = git://git.ucw.cz/ucwmac.git
|
url = git://git.ucw.cz/ucwmac.git
|
||||||
[submodule "src/formatitko/katex-server"]
|
[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
|
url = https://gitea.ks.matfyz.cz:/KSP/formatitko-katex-server
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
\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}
|
|
|
@ -33,11 +33,19 @@ dependencies = [
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
formatitko = "formatitko.formatitko:main"
|
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_scm]
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["src"]
|
where = ["src"]
|
||||||
exclude = ["src/formatitko/katex-server/node_modules"]
|
|
||||||
|
|
||||||
[tool.pyright]
|
[tool.pyright]
|
||||||
strictParameterNoneValue = false
|
strictParameterNoneValue = false
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from panflute import Doc, Element, Div, Span
|
from panflute import Doc, Element, Div, Span, Header, Figure
|
||||||
|
|
||||||
from typing import Union, Callable
|
from typing import Union, Callable
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
|
@ -19,6 +19,23 @@ CommandCallable = Callable[[Command, 'Context', 'NOPProcessor'], list[Element]]
|
||||||
#
|
#
|
||||||
# This class is basically an extension to panflute's doc, this is why metadata
|
# This class is basically an extension to panflute's doc, this is why metadata
|
||||||
# is read directly from it.
|
# 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:
|
class Context:
|
||||||
parent: Union["Context", None]
|
parent: Union["Context", None]
|
||||||
_commands: dict[str, Union[CommandCallable, None]]
|
_commands: dict[str, Union[CommandCallable, None]]
|
||||||
|
@ -32,6 +49,9 @@ class Context:
|
||||||
rel_dir: str # Relative path to the current dir from the root dir
|
rel_dir: str # Relative path to the current dir from the root dir
|
||||||
deps: set[str]
|
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):
|
def __init__(self, doc: Doc, path: str, parent: Union['Context', None]=None, trusted: bool=True):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self._commands = {}
|
self._commands = {}
|
||||||
|
@ -47,6 +67,12 @@ class Context:
|
||||||
self.add_dep(path)
|
self.add_dep(path)
|
||||||
if self.get_metadata("flags", immediate=True) is None:
|
if self.get_metadata("flags", immediate=True) is None:
|
||||||
self.set_metadata("flags", {})
|
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]:
|
def get_command(self, command: str) -> Union[CommandCallable, None]:
|
||||||
if command in self._commands:
|
if command in self._commands:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from panflute import Quoted, Link
|
from panflute import Quoted, Emph, Link, Div
|
||||||
|
|
||||||
|
|
||||||
from .command import Command, InlineCommand, BlockCommand, CodeCommand
|
from .command import Command, InlineCommand, BlockCommand, CodeCommand
|
||||||
|
@ -14,6 +14,22 @@ class FQuoted(Quoted):
|
||||||
del kwargs["style"]
|
del kwargs["style"]
|
||||||
super().__init__(*args, **kwargs)
|
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):
|
class FileLink(Link):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class FLineMarkup(Div):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.color = kwargs["color"]
|
||||||
|
del kwargs["color"]
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
# Import local files
|
# Import local files
|
||||||
from .util import import_md
|
from .util import import_md
|
||||||
|
@ -112,7 +114,12 @@ def main():
|
||||||
else:
|
else:
|
||||||
filename = args.output_tex
|
filename = args.output_tex
|
||||||
outdir = tempfile.TemporaryDirectory(prefix="formatitko")
|
outdir = tempfile.TemporaryDirectory(prefix="formatitko")
|
||||||
subprocess.run(["pdfcsplain", "-halt-on-error", "-output-directory="+outdir.name, "-jobname=formatitko", filename], check=True)
|
|
||||||
|
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)
|
||||||
shutil.move(outdir.name+"/formatitko.pdf", args.output_pdf)
|
shutil.move(outdir.name+"/formatitko.pdf", args.output_pdf)
|
||||||
|
|
||||||
if args.deps is not None:
|
if args.deps is not None:
|
||||||
|
|
|
@ -111,7 +111,7 @@ class HTMLGenerator(OutputGenerator):
|
||||||
|
|
||||||
def generate_CodeBlock(self, e: CodeBlock):
|
def generate_CodeBlock(self, e: CodeBlock):
|
||||||
lexer = None
|
lexer = None
|
||||||
if e.classes and len(e.classes) > 0 and (e.attributes["highlight"] == True or e.attributes["highlight"] == 'True'):
|
if e.classes and len(e.classes) > 0 and (e.attributes.get("highlight", False) in [True, 'True']):
|
||||||
# Syntax highlighting using pygments
|
# Syntax highlighting using pygments
|
||||||
for cl in e.classes:
|
for cl in e.classes:
|
||||||
try:
|
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)
|
warnings.warn(f"Syntax highligher does not have lexer for element with these classes: {e.classes}", UserWarning)
|
||||||
|
|
||||||
if lexer:
|
if lexer:
|
||||||
formatter = HtmlFormatter(style=e.attributes["style"], noclasses=True)
|
formatter = HtmlFormatter(style=e.attributes.get("style", self.context.get_metadata("highlight-style")), noclasses=True)
|
||||||
result = highlight(e.text, lexer, formatter)
|
result = highlight(e.text, lexer, formatter)
|
||||||
self.writeraw(result)
|
self.writeraw(result)
|
||||||
else:
|
else:
|
||||||
|
@ -344,6 +344,9 @@ class HTMLGenerator(OutputGenerator):
|
||||||
def generate_DefinitionList(self, e: DefinitionList):
|
def generate_DefinitionList(self, e: DefinitionList):
|
||||||
self.writeln("<!-- FIXME: DefinitionLists not implemented -->")
|
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):
|
class StandaloneHTMLGenerator(HTMLGenerator):
|
||||||
def generate_Doc(self, e: Doc):
|
def generate_Doc(self, e: Doc):
|
||||||
|
|
|
@ -46,20 +46,20 @@ class KatexClient:
|
||||||
srcdir = os.path.dirname(os.path.realpath(__file__))
|
srcdir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
# Test if `node_modules` directory exists and if not, run `npm install`
|
# 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...")
|
print("Installing node dependencies for the first time...")
|
||||||
npm = shutil.which("npm") or shutil.which("yarnpkg")
|
npm = shutil.which("npm") or shutil.which("yarnpkg")
|
||||||
if npm is None:
|
if npm is None:
|
||||||
raise NPMNotFoundError("npm not found. Node.js is required to use KaTeX.")
|
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)
|
self._server_process = subprocess.Popen(["node", self._katex_server_path, self._socket_file], stdout=subprocess.PIPE)
|
||||||
|
|
||||||
ok = self._server_process.stdout.readline()
|
ok = self._server_process.stdout.readline()
|
||||||
if ok != b"OK\n":
|
if ok != b"OK\n":
|
||||||
raise KatexServerError("Failed to connect to katex-server")
|
raise KatexServerError("Failed to connect to katex_server")
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self._client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
self._client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
|
|
@ -6,7 +6,7 @@ from panflute import MetaValue
|
||||||
from typing import Union, Callable
|
from typing import Union, Callable
|
||||||
|
|
||||||
from .whitespace import NBSP
|
from .whitespace import NBSP
|
||||||
from .elements import FQuoted, FileLink
|
from .elements import FQuoted, Slanted, FLink, FileLink
|
||||||
from .context import Group, InlineGroup, BlockGroup, Context
|
from .context import Group, InlineGroup, BlockGroup, Context
|
||||||
from .whitespace import Whitespace
|
from .whitespace import Whitespace
|
||||||
from .command import BlockCommand, InlineCommand, CodeCommand, Command
|
from .command import BlockCommand, InlineCommand, CodeCommand, Command
|
||||||
|
@ -69,6 +69,7 @@ class NOPProcessor:
|
||||||
Cite: self.transform_Cite,
|
Cite: self.transform_Cite,
|
||||||
Code: self.transform_Code,
|
Code: self.transform_Code,
|
||||||
Emph: self.transform_Emph,
|
Emph: self.transform_Emph,
|
||||||
|
Slanted: self.transform_Slanted,
|
||||||
Image: self.transform_Image,
|
Image: self.transform_Image,
|
||||||
LineBreak: self.transform_LineBreak,
|
LineBreak: self.transform_LineBreak,
|
||||||
Link: self.transform_Link,
|
Link: self.transform_Link,
|
||||||
|
@ -88,6 +89,7 @@ class NOPProcessor:
|
||||||
Underline: self.transform_Underline,
|
Underline: self.transform_Underline,
|
||||||
NBSP: self.transform_NBSP,
|
NBSP: self.transform_NBSP,
|
||||||
FQuoted: self.transform_FQuoted,
|
FQuoted: self.transform_FQuoted,
|
||||||
|
FLink: self.transform_FLink,
|
||||||
FileLink: self.transform_FileLink,
|
FileLink: self.transform_FileLink,
|
||||||
|
|
||||||
InlineCommand: self.transform_InlineCommand,
|
InlineCommand: self.transform_InlineCommand,
|
||||||
|
@ -264,6 +266,10 @@ class NOPProcessor:
|
||||||
e.content = self.transform(e.content)
|
e.content = self.transform(e.content)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
|
def transform_Slanted(self, e: Slanted) -> Slanted:
|
||||||
|
e.content = self.transform(e.content)
|
||||||
|
return e
|
||||||
|
|
||||||
def transform_Link(self, e: Link) -> Link:
|
def transform_Link(self, e: Link) -> Link:
|
||||||
e.content = self.transform(e.content)
|
e.content = self.transform(e.content)
|
||||||
return e
|
return e
|
||||||
|
@ -300,6 +306,9 @@ class NOPProcessor:
|
||||||
e.content = self.transform(e.content)
|
e.content = self.transform(e.content)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
|
def transform_FLink(self, e: FLink) -> FLink:
|
||||||
|
return self.transform_Link(e)
|
||||||
|
|
||||||
def transform_FileLink(self, e: FileLink) -> FileLink:
|
def transform_FileLink(self, e: FileLink) -> FileLink:
|
||||||
e.content = self.transform(e.content)
|
e.content = self.transform(e.content)
|
||||||
return e
|
return e
|
||||||
|
|
|
@ -7,7 +7,7 @@ from panflute import stringify
|
||||||
from typing import Union, Callable
|
from typing import Union, Callable
|
||||||
|
|
||||||
from .whitespace import NBSP
|
from .whitespace import NBSP
|
||||||
from .elements import FQuoted, FileLink
|
from .elements import FQuoted, Slanted, FLink, FileLink, FLineMarkup
|
||||||
from .context import Group, InlineGroup, BlockGroup, Context
|
from .context import Group, InlineGroup, BlockGroup, Context
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ class OutputGenerator:
|
||||||
DefinitionItem: self.generate_DefinitionItem,
|
DefinitionItem: self.generate_DefinitionItem,
|
||||||
DefinitionList: self.generate_DefinitionList,
|
DefinitionList: self.generate_DefinitionList,
|
||||||
Div: self.generate_Div,
|
Div: self.generate_Div,
|
||||||
|
FLineMarkup: self.generate_FLineMarkup,
|
||||||
Figure: self.generate_Figure,
|
Figure: self.generate_Figure,
|
||||||
Header: self.generate_Header,
|
Header: self.generate_Header,
|
||||||
HorizontalRule: self.generate_HorizontalRule,
|
HorizontalRule: self.generate_HorizontalRule,
|
||||||
|
@ -108,6 +109,7 @@ class OutputGenerator:
|
||||||
Cite: self.generate_Cite,
|
Cite: self.generate_Cite,
|
||||||
Code: self.generate_Code,
|
Code: self.generate_Code,
|
||||||
Emph: self.generate_Emph,
|
Emph: self.generate_Emph,
|
||||||
|
Slanted: self.generate_Slanted,
|
||||||
Image: self.generate_Image,
|
Image: self.generate_Image,
|
||||||
LineBreak: self.generate_LineBreak,
|
LineBreak: self.generate_LineBreak,
|
||||||
Link: self.generate_Link,
|
Link: self.generate_Link,
|
||||||
|
@ -127,6 +129,7 @@ class OutputGenerator:
|
||||||
Underline: self.generate_Underline,
|
Underline: self.generate_Underline,
|
||||||
NBSP: self.generate_NBSP,
|
NBSP: self.generate_NBSP,
|
||||||
FQuoted: self.generate_FQuoted,
|
FQuoted: self.generate_FQuoted,
|
||||||
|
FLink: self.generate_FLink,
|
||||||
FileLink: self.generate_FileLink,
|
FileLink: self.generate_FileLink,
|
||||||
InlineGroup: self.generate_InlineGroup
|
InlineGroup: self.generate_InlineGroup
|
||||||
}
|
}
|
||||||
|
@ -379,11 +382,17 @@ class OutputGenerator:
|
||||||
def generate_Emph(self, e: Emph):
|
def generate_Emph(self, e: Emph):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
|
||||||
|
def generate_Slanted(self, e: Slanted):
|
||||||
|
self.generate_Emph(e)
|
||||||
|
|
||||||
def generate_Image(self, e: Image):
|
def generate_Image(self, e: Image):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
|
||||||
def generate_Link(self, e: Link):
|
def generate_Link(self, e: Link):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
|
||||||
|
def generate_FLink(self, e: FLink):
|
||||||
|
self.generate_Link(e)
|
||||||
|
|
||||||
def generate_Note(self, e: Note):
|
def generate_Note(self, e: Note):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
@ -454,6 +463,9 @@ class OutputGenerator:
|
||||||
def generate_Div(self, e: Div):
|
def generate_Div(self, e: Div):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
|
||||||
|
def generate_FLineMarkup(self, e: FLineMarkup):
|
||||||
|
self.generate_Div(e)
|
||||||
|
|
||||||
def generate_Header(self, e: Header):
|
def generate_Header(self, e: Header):
|
||||||
self.generate_simple_tag(e)
|
self.generate_simple_tag(e)
|
||||||
|
|
||||||
|
|
189
src/formatitko/tex/formatitko.tex
Normal file
189
src/formatitko/tex/formatitko.tex
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
\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\cr
|
||||||
|
\noalign{\medskip\smallskip}
|
||||||
|
#2\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%
|
||||||
|
}
|
79
src/formatitko/tex/formatitkolib.tex
Normal file
79
src/formatitko/tex/formatitkolib.tex
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
\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%
|
||||||
|
}
|
22
src/formatitko/tex/table_of_contents.tex
Normal file
22
src/formatitko/tex/table_of_contents.tex
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
|
||||||
|
\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
|
||||||
|
}
|
18
src/formatitko/tex/table_of_contents_pictures.tex
Normal file
18
src/formatitko/tex/table_of_contents_pictures.tex
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
|
||||||
|
\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
|
||||||
|
}
|
|
@ -11,10 +11,14 @@ from .output_generator import OutputGenerator
|
||||||
from .images import ImageProcessor, ImageProcessorNamespaceSearcher
|
from .images import ImageProcessor, ImageProcessorNamespaceSearcher
|
||||||
|
|
||||||
from .whitespace import NBSP
|
from .whitespace import NBSP
|
||||||
from .elements import FQuoted
|
from .elements import FQuoted, FLineMarkup
|
||||||
from .context import Group, InlineGroup, BlockGroup, Context
|
from .context import Group, InlineGroup, BlockGroup, Context
|
||||||
from .util import inlinify
|
from .util import inlinify
|
||||||
|
|
||||||
|
def color_to_rgb(color):
|
||||||
|
import matplotlib.colors
|
||||||
|
return matplotlib.colors.to_rgb(color)
|
||||||
|
|
||||||
class UCWTexGenerator(OutputGenerator):
|
class UCWTexGenerator(OutputGenerator):
|
||||||
imageProcessor: ImageProcessor
|
imageProcessor: ImageProcessor
|
||||||
_bold: int
|
_bold: int
|
||||||
|
@ -24,22 +28,30 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.imageProcessor = imageProcessor
|
self.imageProcessor = imageProcessor
|
||||||
self._bold = 0
|
self._bold = 0
|
||||||
self._italic = 0
|
self._italic = 0
|
||||||
|
|
||||||
|
self._floatpages = {}
|
||||||
super().__init__(output_file, *args, **kwargs)
|
super().__init__(output_file, *args, **kwargs)
|
||||||
|
|
||||||
def escape_special_chars(self, text: str) -> str:
|
def escape_special_chars(self, text: str) -> str:
|
||||||
text = text.replace("&", r"\&")
|
if '\\' in text:
|
||||||
text = text.replace("%", r"\%")
|
print("ESCAPE", text)
|
||||||
text = text.replace("$", r"\$")
|
out = ""
|
||||||
text = text.replace("#", r"\#")
|
for char in text:
|
||||||
text = text.replace("_", r"\_")
|
out += {
|
||||||
text = text.replace("{", r"\{")
|
'&': r"\&",
|
||||||
text = text.replace("}", r"\}")
|
'%': r"\%",
|
||||||
text = text.replace("~", r"\textasciitilde{}")
|
'$': r"\$",
|
||||||
text = text.replace("^", r"\textasciicircum{}")
|
'#': r"\#",
|
||||||
text = text.replace("\\", r"\textbackslash{}")
|
'_': r"\_",
|
||||||
text = text.replace(" ", "~") # We use unicode no-break spaces to force nbsp in output
|
'{': r"\{",
|
||||||
text = text.replace("", "")
|
'}': r"\}",
|
||||||
return text
|
'~': r"\textasciitilde{}",
|
||||||
|
'^': r"\textasciicircum{}",
|
||||||
|
'\\': r"\textbackslash{}",
|
||||||
|
' ': r"~",
|
||||||
|
'': r"",
|
||||||
|
}.get(char, char)
|
||||||
|
return out
|
||||||
|
|
||||||
def generate(self, e: Union[Element, ListContainer]):
|
def generate(self, e: Union[Element, ListContainer]):
|
||||||
if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex":
|
if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex":
|
||||||
|
@ -67,21 +79,17 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.writepar(r"\vskip5pt\hrule\hfil\vskip5pt{}")
|
self.writepar(r"\vskip5pt\hrule\hfil\vskip5pt{}")
|
||||||
|
|
||||||
def generate_Doc(self, e: Doc):
|
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.writeln(r"\input formatitko.tex")
|
||||||
self.generate(e.content)
|
self.generate(e.content)
|
||||||
self.writeln(r"\bye")
|
self.writeln(r"\bye")
|
||||||
|
|
||||||
def get_language_macro(self, lang: str):
|
def get_language_macro(self, lang: str):
|
||||||
if lang == "cs":
|
if lang == "cs":
|
||||||
return r"\chyph\lefthyphenmin=2\righthyphenmin=2{}"
|
return r"\uselanguage{czech}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
|
||||||
elif lang == "sk":
|
elif lang == "sk":
|
||||||
return r"\shyph\lefthyphenmin=2\righthyphenmin=2{}"
|
return r"\uselanguage{slovak}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
|
||||||
elif lang == "en":
|
elif lang == "en":
|
||||||
return r"\ehyph\lefthyphenmin=2\righthyphenmin=2{}"
|
return r"\uselanguage{USenglish}\nonfrenchspacing\lefthyphenmin=2\righthyphenmin=2{}"
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -101,7 +109,7 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
|
|
||||||
def generate_Header(self, e: Header):
|
def generate_Header(self, e: Header):
|
||||||
self.ensure_empty(2)
|
self.ensure_empty(2)
|
||||||
self.write("\\"+"sub"*(e.level-1)+"section{")
|
self.write("\\"+"sub"*(e.level-1)+"section{"+".".join(map(str, e.attributes["number"]))+"}{")
|
||||||
self.generate(e.content)
|
self.generate(e.content)
|
||||||
self.write(r"}")
|
self.write(r"}")
|
||||||
self.ensure_empty(2)
|
self.ensure_empty(2)
|
||||||
|
@ -147,31 +155,58 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
width = str(int(e.attributes["width"][:-1])/100) + "\\hsize"
|
width = str(int(e.attributes["width"][:-1])/100) + "\\hsize"
|
||||||
width = "width " + width
|
width = "width " + width
|
||||||
|
|
||||||
if isinstance(e.parent.parent, Figure):
|
self.writeln(f'\\centerline{{\\putimage{{{width}}}{{{url}}}}}')
|
||||||
self.writeln(f'\\putimage{{{width}}}{{{url}}}')
|
|
||||||
else:
|
|
||||||
self.writepar(f'\\putimage{{{width}}}{{{url}}}')
|
|
||||||
|
|
||||||
def generate_Code(self, e: Code):
|
def generate_Code(self, e: Code):
|
||||||
self.write(r"\verb`")
|
self.write(r"\verb`")
|
||||||
self.write(e.text)
|
self.write(e.text)
|
||||||
self.write(r"`")
|
self.write(r"`")
|
||||||
|
|
||||||
def generate_Figure(self, e: Figure):
|
def generate_nonfloat_Figure(self, e: Figure):
|
||||||
self.ensure_empty(2)
|
self.writeln(r"\figure{")
|
||||||
self.writeln(r"\vskip5pt")
|
|
||||||
self.writeln(r"\centerline{")
|
|
||||||
self.indent_more()
|
self.indent_more()
|
||||||
self.generate(e.content)
|
self.generate(e.content)
|
||||||
self.indent_less()
|
self.indent_less()
|
||||||
self.writeln(r"}")
|
self.writeln(r"}{")
|
||||||
self.writeln(r"\centerline{")
|
|
||||||
self.indent_more()
|
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)
|
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.indent_less()
|
||||||
self.writeln(r"}")
|
self.writeln(r"}{}{}")
|
||||||
self.writeln(r"\vskip5pt{}")
|
|
||||||
self.ensure_empty(2)
|
|
||||||
|
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)
|
||||||
|
|
||||||
def generate_Emph(self, e: Emph):
|
def generate_Emph(self, e: Emph):
|
||||||
if self._bold > 0:
|
if self._bold > 0:
|
||||||
|
@ -183,6 +218,11 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self._italic-=1
|
self._italic-=1
|
||||||
self.write(r"}")
|
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):
|
def generate_Strong(self, e: Strong):
|
||||||
if self._italic > 0:
|
if self._italic > 0:
|
||||||
self.write(r"{\bi{}")
|
self.write(r"{\bi{}")
|
||||||
|
@ -194,15 +234,15 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.write(r"}")
|
self.write(r"}")
|
||||||
|
|
||||||
def generate_Caption(self, e: Caption):
|
def generate_Caption(self, e: Caption):
|
||||||
self.generate_Emph(e)
|
self.generate(e.content)
|
||||||
|
|
||||||
def generate_Math(self, e: Math):
|
def generate_Math(self, e: Math):
|
||||||
if e.format == "DisplayMath":
|
if e.format == "DisplayMath":
|
||||||
self.ensure_empty(2)
|
self.ensure_empty(1)
|
||||||
self.writeraw("$$")
|
self.writeraw("$$")
|
||||||
self.writeraw(e.text.strip())
|
self.writeraw(e.text.strip())
|
||||||
self.writeraw("$$")
|
self.writeraw("$$")
|
||||||
self.ensure_empty(2)
|
self.ensure_empty(1)
|
||||||
else:
|
else:
|
||||||
self.write("$")
|
self.write("$")
|
||||||
self.write(e.text)
|
self.write(e.text)
|
||||||
|
@ -214,22 +254,23 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.write(r"}")
|
self.write(r"}")
|
||||||
|
|
||||||
def generate_Table(self, e: Table):
|
def generate_Table(self, e: Table):
|
||||||
|
hskip = r"\hskip 0.6em\relax"
|
||||||
aligns = {
|
aligns = {
|
||||||
"AlignLeft": r"\quad#\quad\hfil",
|
"AlignLeft": hskip+r"\relax#\hfil"+hskip,
|
||||||
"AlignRight": r"\quad\hfil#\quad",
|
"AlignRight": hskip+r"\hfil#"+hskip,
|
||||||
"AlignCenter": r"\quad\hfil#\hfil\quad",
|
"AlignCenter": hskip+r"\hfil#\hfil"+hskip,
|
||||||
"AlignDefault": r"\quad#\quad\hfil"
|
"AlignDefault": hskip+r"#\hfil"+hskip,
|
||||||
}
|
}
|
||||||
self.writeln(r"\vskip1em")
|
self.writeln(r"\vskip1em")
|
||||||
self.writeln(r"\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr")
|
self.writeln(r"\leavevmode\vbox{\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr")
|
||||||
self.indent_more()
|
self.indent_more()
|
||||||
self.generate(e.head.content)
|
self.generate(e.head.content)
|
||||||
self.writeln(r"\noalign{\hrule}")
|
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}")
|
||||||
self.generate(e.content[0].content)
|
self.generate(e.content[0].content)
|
||||||
self.writeln(r"\noalign{\hrule}")
|
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}")
|
||||||
self.generate(e.foot.content)
|
self.generate(e.foot.content)
|
||||||
self.indent_less()
|
self.indent_less()
|
||||||
self.writeln("}")
|
self.writeln("}}")
|
||||||
self.writeln(r"\vskip1em")
|
self.writeln(r"\vskip1em")
|
||||||
|
|
||||||
def generate_TableRow(self, e: TableRow):
|
def generate_TableRow(self, e: TableRow):
|
||||||
|
@ -263,6 +304,16 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
|
|
||||||
def generate_Div(self, e: Div):
|
def generate_Div(self, e: Div):
|
||||||
self.generate(e.content)
|
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):
|
def generate_LineBlock(self, e: LineBlock):
|
||||||
self.writeln()
|
self.writeln()
|
||||||
|
@ -323,6 +374,11 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.writeln(r"}")
|
self.writeln(r"}")
|
||||||
|
|
||||||
def generate_Link(self, e: Link):
|
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:
|
if len(e.content) == 1 and isinstance(e.content[0], Str) and e.content[0].text == e.url:
|
||||||
self.write(r"\url{")
|
self.write(r"\url{")
|
||||||
else:
|
else:
|
||||||
|
@ -348,7 +404,7 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
self.writeln("% FIXME: Citations not implemented")
|
self.writeln("% FIXME: Citations not implemented")
|
||||||
|
|
||||||
def generate_Cite(self, e: Cite):
|
def generate_Cite(self, e: Cite):
|
||||||
self.writeln("% FIXME: Cites not implemented")
|
self.generate(e.content)
|
||||||
|
|
||||||
def generate_Definition(self, e: Definition):
|
def generate_Definition(self, e: Definition):
|
||||||
self.writeln("% FIXME: Definitions not implemented")
|
self.writeln("% FIXME: Definitions not implemented")
|
||||||
|
@ -364,3 +420,8 @@ class UCWTexGenerator(OutputGenerator):
|
||||||
|
|
||||||
def generate_Strikeout(self, e: Strikeout):
|
def generate_Strikeout(self, e: Strikeout):
|
||||||
self.writeln("% FIXME: Strikeouts not implemented")
|
self.writeln("% FIXME: Strikeouts not implemented")
|
||||||
|
|
||||||
|
def generate_SmallCaps(self, e: Strikeout):
|
||||||
|
self.write(r"{\csc{}")
|
||||||
|
self.generate(e.content)
|
||||||
|
self.write(r"}")
|
||||||
|
|
|
@ -14,7 +14,7 @@ import importlib
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from .whitespace import NBSP
|
from .whitespace import NBSP
|
||||||
from .elements import FQuoted
|
from .elements import FQuoted, Slanted, FLink
|
||||||
from .context import Group, InlineGroup, BlockGroup
|
from .context import Group, InlineGroup, BlockGroup
|
||||||
from .util import nullify, import_md
|
from .util import nullify, import_md
|
||||||
from .context import Context, CommandCallable
|
from .context import Context, CommandCallable
|
||||||
|
@ -228,12 +228,12 @@ class TransformProcessor(NOPProcessor):
|
||||||
importedDoc = import_md(open(filename, "r").read())
|
importedDoc = import_md(open(filename, "r").read())
|
||||||
self.transform(importedDoc.content)
|
self.transform(importedDoc.content)
|
||||||
elif e.attributes["type"] == "module":
|
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:
|
if not matches:
|
||||||
raise SyntaxError(f"`{e.content[0].text[1:]}`: invalid syntax")
|
raise SyntaxError(f"`{e.content[0].text[1:]}`: invalid syntax")
|
||||||
module = importlib.import_module(matches.group(1))
|
module = importlib.import_module(matches.group(1))
|
||||||
module_name = matches.group(1) if matches.group(2) is None else matches.group(2)
|
module_name = matches.group(1) if matches.group(2) is None else matches.group(2)
|
||||||
self.context.add_commands_from_module(module, module_name)
|
self.context.add_commands_from_module(module, "")
|
||||||
elif e.attributes["type"] == "metadata":
|
elif e.attributes["type"] == "metadata":
|
||||||
filename = self.context.dir + "/" + e.content[0].text[1:]
|
filename = self.context.dir + "/" + e.content[0].text[1:]
|
||||||
self.context.add_dep(filename)
|
self.context.add_dep(filename)
|
||||||
|
@ -260,6 +260,11 @@ class TransformProcessor(NOPProcessor):
|
||||||
raise TypeError(f"Cannot print value of metadatum '{e.content[0].text[1:]}' of type '{type(val)}'")
|
raise TypeError(f"Cannot print value of metadatum '{e.content[0].text[1:]}' of type '{type(val)}'")
|
||||||
return e
|
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)
|
return super().transform_Span(e)
|
||||||
|
|
||||||
def transform_CodeBlock(self, e: CodeBlock) -> Union[CodeBlock, Div, Null]:
|
def transform_CodeBlock(self, e: CodeBlock) -> Union[CodeBlock, Div, Null]:
|
||||||
|
@ -306,3 +311,26 @@ class TransformProcessor(NOPProcessor):
|
||||||
else:
|
else:
|
||||||
return e
|
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)
|
||||||
|
|
|
@ -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.svg){width=25%}What
|
||||||
|
|
||||||
![This is a figure, go figure...](logo.pdf){width=50%}
|
![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...](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}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue