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

@@ -160,7 +160,6 @@ strings_t group_filename_tokens(const strings_t& tokens, const std::string& base
// name exists. A name that never resolves is kept as given, so the
// missing-file error downstream reports what the user wrote.
size_t i = 0;
bool reported = false; // at most one "tried" report per list
while (i < tokens.size()) {
if (filename_exists(tokens[i], base_dir)) {
result.push_back(tokens[i]);
@@ -188,27 +187,14 @@ strings_t group_filename_tokens(const strings_t& tokens, const std::string& base
}
}
if (!found) {
// Nothing resolved. The groupings that were TRIED are what
// the user needs at verbosity 0, because the downstream error
// names only the first token and cannot say why the others
// were not joined to it. Recorded on the name so the caller
// can report them with the missing-file error.
strings_t tried {};
std::string acc2 = tokens[i];
tried.push_back(q_(acc2));
for (size_t k = i + 1; k < tokens.size(); ++k) {
acc2 += " " + tokens[k];
tried.push_back(q_(acc2));
}
// Once: the first unresolved token's list already shows
// every joining from that point on, and one report per
// leftover word buries it.
if (tried.size() > 1 && !reported) {
std::cerr << command_name << ": no file matches "
<< q_(tokens[i]) << "; tried "
<< join(tried, ", ") << "\n";
reported = true;
}
// Nothing resolved: the token passes through as written and
// its DOWNSTREAM OWNER decides -- a bare :files word is the
// kt/ shortcut (which resolves or errors there), a missing
// file is a located error. A failed rescue itself says
// NOTHING at any verbosity (2026-08-22): every outcome is
// already either the -v 1 resolution line or an error that
// stops the run, so a tried-list adds noise to the first and
// nothing to the second.
result.push_back(tokens[i]);
++i;
}
@@ -358,7 +344,7 @@ std::string find_file(const std::string& basename, strings_t search_path, bool e
std::sort(search_path.begin(), search_path.end());
ss << "File with basename \"" << basename << "\" not found in search path:\n "
<< join(search_path, "\n ");
throw File_error(ss.str(), Locator(), false);
throw File_error(ss.str(), Locator());
}
return pathname;
}