Verbatim-safe typography, ^-punctuation quoting, full-range ^UUUU^, polyglot html

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)
This commit is contained in:
2026-08-23 20:48:26 +02:00
parent d982c0d6cc
commit 37b6ba1c4f
77 changed files with 1665 additions and 1608 deletions

View File

@@ -40,6 +40,21 @@ Eval_python::Eval_python(Machine& machine, const Locator& loc)
Py_DECREF(result_text);
}
import_module("inspect", false);
// The :after_apply phase dispatcher: a phase that declares a K
// parameter receives the state's class K; one that does not (a stdlib
// function like string.capwords, whose second parameter is a separator)
// is called with the text alone. Discrimination is by parameter NAME,
// not count -- capwords has two parameters and K is not one of them.
// Builtins whose signature inspect cannot read are treated as not
// wanting K.
PyRun_String(
"def K_phase_call(f, text, K):\n"
" try:\n"
" wants = 'K' in inspect.signature(f).parameters\n"
" except (ValueError, TypeError):\n"
" wants = False\n"
" return f(text, K=K) if wants else f(text)\n",
Py_file_input, m_globals, m_globals);
if (!m_machine.m_state.m_frames.empty()) {
PyRun_String(m_machine.m_state.python_code().c_str(), Py_file_input, m_globals, m_locals);
}
@@ -154,7 +169,7 @@ void Eval_python::import_module(const std::string& module_name, bool verify)
if (!detail.empty()) {
message += ":\n\n" + detail;
}
throw Argument_error(message, m_loc, false);
throw Argument_error(message, m_loc);
}
// PyDict_SetItemString steals a reference, so we don't need to DECREF module
// The dictionary will own the reference