2026-07-18 18:48:23 +02:00
|
|
|
import re
|
|
|
|
|
import os
|
|
|
|
|
import tempfile
|
|
|
|
|
import sys
|
|
|
|
|
import klammer_base
|
|
|
|
|
import urllib
|
|
|
|
|
import kutil
|
|
|
|
|
|
|
|
|
|
def html_link(target, link_text, is_section, no_quotation_marks):
|
|
|
|
|
# [__link__target__text__]
|
|
|
|
|
if not link_text:
|
|
|
|
|
if is_section:
|
|
|
|
|
link_text = target if no_quotation_marks else f"“{target}”"
|
|
|
|
|
else:
|
|
|
|
|
# Allow long URLs to break at a slash:
|
|
|
|
|
link_text = re.sub('/', '/<wbr>', target)
|
|
|
|
|
link_text = re.sub('/<wbr>/<wbr>', '//', link_text)
|
|
|
|
|
link_text = f'<tt>{link_text}</tt>'
|
|
|
|
|
target = f"[{target}]" if is_section else target
|
|
|
|
|
#result = f"[__link__{target}__{link_text}__]"
|
|
|
|
|
#return result
|
|
|
|
|
|
|
|
|
|
if target.startswith("http") or ".html" in target:
|
|
|
|
|
url = target
|
|
|
|
|
elif is_section:
|
|
|
|
|
url = f"__sectionlink__{target}__"
|
|
|
|
|
else:
|
|
|
|
|
url = f"^#{target}"
|
|
|
|
|
result = f'<a href="{url}">{link_text}</a>'
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def add_latex_footnote_if_necessary(url, link_text):
|
|
|
|
|
result = ""
|
|
|
|
|
if (('http://' in url or 'https://' in url) and
|
|
|
|
|
('http://' not in link_text and 'https://' not in link_text)):
|
|
|
|
|
escaped_url = re.sub('#', '\\#', url)
|
|
|
|
|
escaped_url = re.sub('%', '\\%', escaped_url)
|
|
|
|
|
result += f'\\footnote{{\\\rule{{0pt}}{{12pt}}\\texttt{{{escaped_url}}}}}'
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def latex_link(target, link_text, is_section, no_quotation_marks, add_footnote):
|
|
|
|
|
if target.startswith("http"):
|
|
|
|
|
if link_text and link_text != "URL":
|
|
|
|
|
result = f"#/ \\href{{{target}}}{{{link_text}}} #/"
|
|
|
|
|
else:
|
|
|
|
|
#result = f"\\\url{{{target}}}"
|
|
|
|
|
result = f"#/ \\href{{{target}}}{{{target}}} #/"
|
|
|
|
|
elif is_section:
|
|
|
|
|
if not link_text:
|
|
|
|
|
link_text = target if no_quotation_marks else f"``{target}''"
|
|
|
|
|
result = f"\\hyperlink{{__seclink__{target}__}}{{{link_text}}}"
|
|
|
|
|
else:
|
|
|
|
|
result = f"\\hyperlink{{{target}}}{{{link_text}}}"
|
|
|
|
|
# if add_footnote:
|
|
|
|
|
# if self.footnote:
|
|
|
|
|
# result += add_latex_footnote_if_necessary(target, link_text)
|
|
|
|
|
# print(result)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
class Link(klammer_base.Klammer_base):
|
|
|
|
|
def __init__(self, K):
|
|
|
|
|
super().__init__(K)
|
|
|
|
|
# self.show("Link")
|
|
|
|
|
|
|
|
|
|
def html(self):
|
Typed arguments, calculated tables, spans, closed-world fonts, top-level fnt/ and env/
Sync with klammertext-dev through b90b0e09:
- Argument types end to end: :python_cast values are applied (Python
@eval receives real bools/numbers/lists), argument values are
validated against their argtype patterns with the argtype's
description as the error message, argtypes can declare :default
(overridable per declaration), and parameterized type families are
supported: rest(N) casts a rest argument to an N-dimensional list
(bar-count = dimension).
- Unified indexed_range syntax (selector with parenthesized subsets,
composable mnemonic names) for table lines and spans.
- Table klammer: caption fonts fixed in both targets, :column_width /
:leading / :colsep wired, :colspan and :rowspan render (HTML
attributes; \multicolumn / \multirow), calculated cell values (:calc)
with prefix operators, display-precision semantics, :calc_format and
:decimal period|comma.
- Fonts: closed-world resolution on the Klammertext font store
(infrastructure in mac/font_store; no Google Fonts links or fetch).
Default fonts live in the top-level fnt/; additional fonts install
into KLAMMERTEXT_FONTS directories via kdesc --font (list, samples,
preview, install — classification by font metadata). CSS font family
names are quoted (digit-initial families were silently lost).
- Environment files moved from mac/env/ to the top-level env/; shell
profiles source env/runtime.env. Dead per-host variants removed.
- Container: fnt/ ships in the image; curl removed (no network use).
2026-07-22 18:17:43 +02:00
|
|
|
return html_link(self.target, self.text, self.section, self.nq)
|
2026-07-18 18:48:23 +02:00
|
|
|
|
|
|
|
|
def tex(self):
|
|
|
|
|
return latex_link(self.target, self.text, self.section, self.nq, self.footnote)
|
|
|
|
|
|
|
|
|
|
def txt(self):
|
|
|
|
|
text = f'{self.text} ' if self.text else ''
|
|
|
|
|
return f'{text}[{self.url}]'
|
|
|
|
|
|
|
|
|
|
class Target(klammer_base.Klammer_base):
|
|
|
|
|
def __init__(self, K):
|
|
|
|
|
super().__init__(K)
|
|
|
|
|
id = K.id.strip()
|
|
|
|
|
id = re.compile(r'\s+', re.S).sub('-', id)
|
|
|
|
|
self.id = re.sub('_', '-', id)
|
|
|
|
|
|
|
|
|
|
def html(self):
|
|
|
|
|
id = self.id.split(':')[-1]
|
|
|
|
|
return f'<span id="{id}">{self.text}</span>'
|
|
|
|
|
|
|
|
|
|
def tex(self):
|
|
|
|
|
result = f'\\hypertarget{{{self.id}}}{{{self.text}}}'
|
|
|
|
|
#result += '\\label{{{}-label}}'.format(id)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def txt(self):
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Email(klammer_base.Klammer_base):
|
|
|
|
|
def __init__(self, K):
|
|
|
|
|
super().__init__(K)
|
|
|
|
|
|
|
|
|
|
def html(self):
|
|
|
|
|
def val(attr, s):
|
|
|
|
|
return "{}={}&".format(attr, re.sub(" ", "%20", s))
|
|
|
|
|
domain = "&^#46;".join(self.domain.split("."))
|
|
|
|
|
address = "{}&^#64;{}".format(self.name, domain)
|
|
|
|
|
href = "mailto&^#58;{}?".format(address)
|
|
|
|
|
if self.subject:
|
|
|
|
|
href += val("subject", self.subject)
|
|
|
|
|
if self.body:
|
|
|
|
|
href += val("body", self.body)
|
|
|
|
|
href = href[:-1]
|
2026-07-25 21:16:21 +02:00
|
|
|
result = '<a href="{}" class="monospace">{}</a>'.format(href, address)
|
2026-07-18 18:48:23 +02:00
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def tex(self):
|
|
|
|
|
return r'\texttt{{{}^@{}}}'.format(self.name, self.domain)
|
|
|
|
|
|