Partials are now also isolated in output TeX and KaTeX. Also language is now so special it pops out to TeX as a macro at the start of each group.

This commit is contained in:
Jan Černohorský 2023-02-05 17:13:50 +01:00
parent da30967d12
commit 5e475f6881
11 changed files with 75 additions and 24 deletions

View file

@ -51,6 +51,8 @@ class Context:
return None return None
def set_metadata(self, key, value): def set_metadata(self, key, value):
if key == "language":
print("WARN: Setting language this way doesn't propagate to TeX. Either use the Front Matter or specify it additionally using the \\languagexx macro.")
meta = self.doc.metadata meta = self.doc.metadata
key = key.split(".") key = key.split(".")
for k in key[:-1]: for k in key[:-1]:

View file

@ -9,6 +9,7 @@ from typing import List
from transform import transform from transform import transform
from util import * from util import *
from context import Context from context import Context
from group import Group
from katex import KatexClient from katex import KatexClient
from html import html from html import html
from tex import tex from tex import tex
@ -16,15 +17,17 @@ from tex import tex
from mj_show import show from mj_show import show
doc = import_md(open(sys.argv[1], "r").read()) doc = import_md(open(sys.argv[1], "r").read())
language = doc.get_metadata("language", None, True)
print(show(doc)) print(show(doc))
context = Context(doc, sys.argv[1]) context = Context(doc, sys.argv[1])
doc = doc.walk(transform, context) doc = doc.walk(transform, context)
print("---------------------") doc.content = [Group(*doc.content, metadata={"language":language})]
print(show(doc)) #print("---------------------")
#print(show(doc))
#print(convert_text(doc, input_format="panflute", output_format="markdown")) #print(convert_text(doc, input_format="panflute", output_format="markdown"))
katexClient = KatexClient() katexClient = KatexClient()
#print(katexClient.render("\\def\\Bruh{K^A\\TeX}"))
#print(katexClient.render("\\Bruh"))
open("output.html", "w").write("<head> <meta charset='utf-8'> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css' integrity='sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0' crossorigin='anonymous'> </head>" + html(doc, katexClient)) open("output.html", "w").write("<head> <meta charset='utf-8'> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css' integrity='sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0' crossorigin='anonymous'> </head>" + html(doc, katexClient))
open("output.tex", "w").write("\input formatitko.tex\n" + tex(doc)) open("output.tex", "w").write("\input formatitko.tex\n" + tex(doc))
#print(tex(doc)) #print(tex(doc))

View file

@ -35,6 +35,8 @@
\def\figure#1#2{\vskip5pt\centerline{#1}\centerline{#2}\vskip5pt} \def\figure#1#2{\vskip5pt\centerline{#1}\centerline{#2}\vskip5pt}
\def\caption#1{{\it #1}} \def\caption#1{{\it #1}}
\let\image\putimage \let\image\putimage
\def\languagecs{} % KSP should define this to \cze probably
\def\languageen{} % KSP should define this to \eng probably
\def\table#1{#1} \def\table#1{#1}
\def\tablebody#1{#1} \def\tablebody#1{#1}
\def\tablerow#1{#1} \def\tablerow#1{#1}

8
group.py Normal file
View file

@ -0,0 +1,8 @@
from panflute import Block
from typing import Dict
class Group(Block):
def __init__(self, *args, identifier='', classes=[], attributes={}, metadata={}):
self._set_ica(identifier, classes, attributes)
self._set_content(args, Block)
self.metadata = metadata

View file

@ -8,6 +8,7 @@ from whitespace import NBSP
from transform import FQuoted from transform import FQuoted
from katex import KatexClient from katex import KatexClient
from util import inlinify from util import inlinify
from group import Group
def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t") -> str: def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t") -> str:
@ -174,6 +175,12 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
else: else:
return f'"{html(e.content, k, 0, "")}"' return f'"{html(e.content, k, 0, "")}"'
if isinstance(e, Group):
k.begingroup()
ret = html(e.content, k, indent_level, indent_str)
k.endgroup()
return ret
if isinstance(e, Math): if isinstance(e, Math):
formats = { formats = {
"DisplayMath": True, "DisplayMath": True,

View file

@ -77,17 +77,29 @@ function socketWrite(socket, data) {
* */ * */
async function handleClient(client) { async function handleClient(client) {
const rl = readline.createInterface({ input: client }) const rl = readline.createInterface({ input: client })
const macroStack = [{}]
for await (const line of rl) { for await (const line of rl) {
try { try {
if (line === "begingroup") {
macroStack.push({...macroStack.slice(-1)[0]})
continue
} else if (line === "endgroup") {
macroStack.pop()
continue
}
const query = JSON.parse(line) const query = JSON.parse(line)
const results = [] const results = []
for (const input of query.formulas) { for (const input of query.formulas) {
const options = input.options ?? query.options ?? defaultOptions const options = input.options ?? query.options ?? defaultOptions
if (options.macros) {
for (const macro of Object.keys(options.macros)) {
macroStack.slice(-1)[macro] = options.macros[macro]
}
}
options.macros = macroStack.slice(-1)[0]
try { try {
const html = katex.renderToString(input.tex, options) const html = katex.renderToString(input.tex, options)
results.push({ html }) results.push({ html })
} catch (e) { } catch (e) {
results.push({ error: String(e) }) results.push({ error: String(e) })

View file

@ -25,8 +25,9 @@ class KatexClient:
break break
def render(self, tex: str, options: Dict={}): def render(self, tex: str, options: Dict={}):
self._client.sendall((json.dumps({"formulas":[{"tex":tex, "options": options}]})+"\n").encode("utf-8")) options["globalGroup"] = True
data = self._client.recv(128) self._client.sendall((json.dumps({"formulas":[{"tex":tex}], "options":options})+"\n").encode("utf-8"))
data = self._client.recv(1024)
while data[-1] != 0x0a: while data[-1] != 0x0a:
data += self._client.recv(128) data += self._client.recv(128)
response = json.loads(data) response = json.loads(data)
@ -37,3 +38,8 @@ class KatexClient:
else: else:
return response["results"][0]["html"] return response["results"][0]["html"]
def begingroup(self):
self._client.sendall("begingroup\n".encode("utf-8"))
def endgroup(self):
self._client.sendall("endgroup\n".encode("utf-8"))

View file

@ -1,5 +1,6 @@
--- ---
title: A subfile! title: A subfile!
language: "cs"
--- ---
I am a little piece of content I am a little piece of content
@ -45,3 +46,8 @@ I am a duck.
This should be only shown to included cats. This should be only shown to included cats.
::: :::
$$
\def\eqalign#1{NO, just, nooooo}
\eqalign{}
$$

23
test.md
View file

@ -2,6 +2,7 @@
title: 'Wooooo a title' title: 'Wooooo a title'
subtitle: 'A subtitle' subtitle: 'A subtitle'
are_we_there_yet: False are_we_there_yet: False
language: "en"
--- ---
[#test-import.md]{} [#test-import.md]{}
@ -52,14 +53,14 @@ This should only be shown to cats the second time
![This is a figure, go figure...](/tmp/logo.png){width=10em} ![This is a figure, go figure...](/tmp/logo.png){width=10em}
![This is a figure, go figure...](/tmp/logo.svg){width=10em} ![Fakt epesní reproduktor](/tmp/reproduktor.jpeg){width=10em}
```python {.run} ```python {.run}
ctx.set_metadata("language", "cs") ctx.set_metadata("language", "cs")
``` ```
[!opendatatask]{} [!opendatatask]{}
```python {.run} ```python {.run}
ctx.unset_metadata("language") ctx.set_metadata("language","en")
``` ```
[This too!]{if=cat} [This too!]{if=cat}
@ -86,28 +87,22 @@ H~2~O is a liquid. 2^10^ is 1024.
[Underline]{.underline} [Underline]{.underline}
:::{only=tex}
$$
\eqalign{
2 x_2 + 6 x_3 &= 14 \cr
x_1 - 3 x_2 + 2 x_3 &= 5 \cr
-x_1 + 4 x_2 + \phantom{1} x_3 &= 2
}
$$
:::
:::{only=html} :::{only=html}
$$ $$
\def\eqalign#1{\begin{align*}#1\end{align*}} \def\eqalign#1{\begin{align*}#1\end{align*}}
$$
:::
$$
\eqalign{ \eqalign{
2 x_2 + 6 x_3 &= 14 \cr 2 x_2 + 6 x_3 &= 14 \cr
x_1 - 3 x_2 + 2 x_3 &= 5 \cr x_1 - 3 x_2 + 2 x_3 &= 5 \cr
-x_1 + 4 x_2 + \phantom{1} x_3 &= 2 -x_1 + 4 x_2 + \phantom{1} x_3 &= 2
} }
$$ $$
:::
<!-- TODO: This sucks --> :::{partial=test-partial.md}
:::
--- ---

8
tex.py
View file

@ -3,6 +3,7 @@ from panflute import *
from whitespace import NBSP from whitespace import NBSP
from transform import FQuoted from transform import FQuoted
from util import inlinify from util import inlinify
from group import Group
# Heavily inspired by: git://git.ucw.cz/labsconf2022.git # Heavily inspired by: git://git.ucw.cz/labsconf2022.git
def tex(e, indent_level: int=0, indent_str: str="\t") -> str: def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
@ -156,6 +157,13 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
if isinstance(e, LineBlock): if isinstance(e, LineBlock):
return f'{tex(e.content, indent_level+1, indent_str)}\n' return f'{tex(e.content, indent_level+1, indent_str)}\n'
if isinstance(e, Group):
tag = "begingroup"
open = ""
if "language" in e.metadata and e.metadata["language"] is not None:
open = "\\language"+e.metadata["language"]
close = "\\endgroup"
if isinstance(e, Div): if isinstance(e, Div):
return f'{tex(e.content, indent_level+1, indent_str)}' return f'{tex(e.content, indent_level+1, indent_str)}'

View file

@ -6,6 +6,7 @@ from whitespace import *
from command import * from command import *
from util import * from util import *
from context import * from context import *
from group import Group
class FQuoted(Quoted): class FQuoted(Quoted):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -41,8 +42,9 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
if (isinstance(e, Div)) and "partial" in e.attributes: if (isinstance(e, Div)) and "partial" in e.attributes:
includedDoc = import_md(open(e.attributes["partial"], "r").read()) includedDoc = import_md(open(e.attributes["partial"], "r").read())
nContext = Context(includedDoc, e.attributes["partial"], c) nContext = Context(includedDoc, e.attributes["partial"], c)
language = includedDoc.get_metadata("language")
includedDoc = includedDoc.walk(transform, nContext) includedDoc = includedDoc.walk(transform, nContext)
e = Div(*includedDoc.content) e = Group(*includedDoc.content, metadata={"language": language})
if isinstance(e, Quoted): if isinstance(e, Quoted):