Typographic transforms (---, quote pairs, ~) no longer touch verbatim text: @c/@code/@source_listing content and ^'...'^ spans show exactly the characters written. "^" before any punctuation character quotes it in every target (the apostrophe excepted: ^' opens a literal span), with the new :resolve option on @@@target declaring per-target renderings. The ^UUUU^ code-point form accepts 4-6 hex digits, the full Unicode range. The html output and transform spellings are polyglot (XML-valid), in preparation for an EPUB target. New suites: transform_test, character_test (engine), typography_test (SKS). (from dev 07ce5ea86a0a)
94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
import re
|
|
import textwrap
|
|
|
|
# Emitted by @vspace.txt (sks/block/block.k), one marker per line of space.
|
|
# An @eval result consisting only of whitespace is trimmed away by the
|
|
# Klammermachine, so vertical space must travel as markers and become
|
|
# newlines here, after blank-line runs have been normalized.
|
|
|
|
def txt_nl_marker():
|
|
return "__KTEXTNEWLINE__"
|
|
|
|
def txt_vspace_marker():
|
|
return "__KTEXTVSPACE__"
|
|
|
|
def txt_justify_blocks(text, K):
|
|
delim = '__DIVIDE__'
|
|
text = re.sub("\n\n+", delim, text)
|
|
result = ""
|
|
for par in text.split(delim):
|
|
stripped = par.strip()
|
|
n = stripped.count(txt_vspace_marker())
|
|
if n and stripped == txt_vspace_marker() * n:
|
|
# A paragraph of only @vspace markers: n blank lines in addition
|
|
# to the normal paragraph separation.
|
|
result += "\n" * n
|
|
continue
|
|
|
|
if par and par[0] != ' ':
|
|
label = re.match(r"~*\[\d+\] ", par)
|
|
par = "\n".join(textwrap.wrap(
|
|
par, width=int(K.Target_txt_width), break_long_words=False,
|
|
subsequent_indent=" " * len(label.group(0)) if label else ""))
|
|
# if par and par[0] != ' ':
|
|
# par = "\n".join(textwrap.wrap(
|
|
# par, width=int(K.Target_txt_width), break_long_words=False))
|
|
result += par + "\n\n"
|
|
result = re.sub(" *" + txt_vspace_marker() + " *", "\n", result)
|
|
result = re.sub(r"\n? *" + txt_nl_marker() + r" *\n?", "\n", result)
|
|
result = re.sub("~", " ", result)
|
|
return result
|
|
|
|
def txt_footnote_marker():
|
|
return "KTEXTFOOTNOTE"
|
|
|
|
def txt_format_footnotes(text, K):
|
|
footnote_number = 0
|
|
footnotes = []
|
|
def replace(m):
|
|
nonlocal footnote_number, footnotes
|
|
footnote_number += 1
|
|
footnotes.append(m.group(1))
|
|
return f"[{footnote_number}]"
|
|
start_mark = "__" + txt_footnote_marker()
|
|
end_mark = txt_footnote_marker() + "__"
|
|
footnote_rgx = re.compile(rf"\s*{start_mark}\s+(.*?)\s+{end_mark}", re.S)
|
|
result = footnote_rgx.sub(replace, text).rstrip() + "\n\n"
|
|
if footnotes:
|
|
rule_count = int(round(float(K.Target_txt_width) * 0.4))
|
|
result += "-" * rule_count + "\n\n"
|
|
# Calculate maximum width for right-justified numbers:
|
|
width = len(f"[{len(footnotes)}]")
|
|
for n, footnote in enumerate(footnotes, 1):
|
|
label = f"[{n}]"
|
|
result += "~" * (width - len(label)) + label + " " + footnote + "\n\n"
|
|
return result
|
|
|
|
def html_footnote_marker():
|
|
return "kt-footnote"
|
|
|
|
def html_format_footnotes(text, K=None):
|
|
fnum = 0
|
|
footnotes = []
|
|
def replace(m):
|
|
nonlocal fnum, footnotes
|
|
fnum += 1
|
|
footnotes.append(m.group(1))
|
|
href = f'href ="#_footnote_{fnum}"'
|
|
id = f'id="_footnote_src_{fnum}"'
|
|
return f'<a {id} {href}><sup class="footnote_in_text">{fnum}</sup></a>'
|
|
#return f'<a href="#_footnote_{fnum}" id="_footnote_src_{fnum}"><sup>{fnum}</sup></a>'
|
|
start_mark = f"<{html_footnote_marker()}>"
|
|
end_mark = f"</{html_footnote_marker()}>"
|
|
footnote_rgx = re.compile(rf"\s*{start_mark}\s*(.*?)\s*{end_mark}", re.S)
|
|
result = footnote_rgx.sub(replace, text).rstrip() + "\n\n"
|
|
if footnotes:
|
|
result += '<hr class="footnote_rule"/>\n'
|
|
for n, footnote in enumerate(footnotes, 1):
|
|
result += f'<a href="#_footnote_src_{n}" id="_footnote_{n}"><sup>{n} </sup></a>{footnote}<br/>\n'
|
|
# Temporarily add room for footnotes to move to the top of the window for the test:
|
|
result += '<div style="height: 100lh"></div>\n'
|
|
return result
|
|
|
|
|