PDF: Font-Fallback für Emoji und Sonderzeichen - 2070 Missing-character-Faelle behoben
This commit is contained in:
parent
9b461426fc
commit
abc7a5693f
8 changed files with 198 additions and 1 deletions
91
pandoc/emoji_fallback.lua
Normal file
91
pandoc/emoji_fallback.lua
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
-- emoji_fallback.lua
|
||||
-- Pandoc-Filter für den PDF-Bau (nur `-t latex`, nur PDF, nicht für die Website).
|
||||
--
|
||||
-- Problem: Der Haupttext steht in Times New Roman — diese Schrift kennt weder
|
||||
-- Emoji noch die Darstellungssymbole der Lernelemente (⭐ ✏ ❓ 🧠 …) und auch
|
||||
-- keine hoch-/tiefgestellten Ziffern. XeLaTeX besitzt keine automatische
|
||||
-- Font-Fallback-Kette: Fehlt einem Zeichen der Glyph, wird es stillschweigend
|
||||
-- weggelassen ("Missing character" nur im Protokoll). Die pandoc-Variable
|
||||
-- "emoji-font" wird vom LaTeX-Writer (pandoc 3.1.3) nicht ausgewertet — die
|
||||
-- Zeichen fehlten daher in der gesamten PDF-Fassung, während die Website sie
|
||||
-- über den Browser-Fontstack korrekt zeigte.
|
||||
--
|
||||
-- Lösung: Dieser Filter wickelt alle betreffenden Zeichen in
|
||||
-- {\texorpdfstring{\symfont{<Zeichen>}}{<Zeichen>}}
|
||||
-- ein. \symfont ist in pandoc/header-includes.tex auf Symbola gesetzt — die
|
||||
-- einzige auf dem Bausystem vorhandene Schrift, die das komplette Set abdeckt
|
||||
-- (Noto Color Emoji funktioniert unter XeTeX nicht, die Zeichen landen im
|
||||
-- nullfont). Symbola ist monochrom — für den Drucksatz ohnehin passend.
|
||||
--
|
||||
-- Der \texorpdfstring-Anteil hält hyperref ruhig: In PDF-Lesezeichen und im
|
||||
-- Inhaltsverzeichnis steht das schlichte Zeichen statt des Fontwechsels.
|
||||
--
|
||||
-- Codeblöcke werden nicht angetastet (Code/CodeBlock sind eigene
|
||||
-- AST-Elemente): Der Mono-Font DejaVu Sans Mono deckt die dort vorkommenden
|
||||
-- Symbole (✓ ✗ ★, Sub-/Superskripte) selbst ab.
|
||||
|
||||
local function braucht_symfont(cp)
|
||||
return (cp >= 0x1F000 and cp <= 0x1FAFF) -- Emoji-Blöcke (🎯 📌 🚀 …)
|
||||
or (cp >= 0x2600 and cp <= 0x27BF) -- Misc Symbols + Dingbats (★ ⚠ ✅ ✏ ✓ ✗ ❌ ❓)
|
||||
or (cp >= 0x2B00 and cp <= 0x2BFF) -- Misc Symbols and Arrows (⭐)
|
||||
or (cp >= 0x27F5 and cp <= 0x27FF) -- Supplemental Arrows-A (⟵ ⟶ ⟹)
|
||||
or (cp >= 0x2070 and cp <= 0x209F) -- hoch-/tiefgestellte Ziffern (⁶ ₀ ₁ ₂ ₜ ₙ)
|
||||
or cp == 0x21D2 -- ⇒
|
||||
or cp == 0x1D40 -- ᵀ (Modifier Letter Capital T)
|
||||
end
|
||||
|
||||
local function ersetze(text)
|
||||
local teile = {}
|
||||
local normal = {}
|
||||
local symbole = nil -- Puffer für aufeinanderfolgende Fallback-Zeichen
|
||||
|
||||
local function flush_normal()
|
||||
if #normal > 0 then
|
||||
teile[#teile + 1] = pandoc.Str(table.concat(normal))
|
||||
normal = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function flush_symbole()
|
||||
if symbole and #symbole > 0 then
|
||||
local zeichen = table.concat(symbole)
|
||||
teile[#teile + 1] = pandoc.RawInline("latex",
|
||||
"{\\texorpdfstring{\\symfont{" .. zeichen .. "}}{"
|
||||
.. zeichen .. "}}")
|
||||
symbole = nil
|
||||
end
|
||||
end
|
||||
|
||||
for _, cp in utf8.codes(text) do
|
||||
if cp == 0xFE0F then
|
||||
-- Variationsselektor (Emoji- vs. Textdarstellung): für das PDF ohne
|
||||
-- Bedeutung, Symbola enthält keinen sichtbaren Glyphen — weglassen.
|
||||
elseif braucht_symfont(cp) then
|
||||
flush_normal()
|
||||
symbole = symbole or {}
|
||||
symbole[#symbole + 1] = utf8.char(cp)
|
||||
else
|
||||
flush_symbole()
|
||||
normal[#normal + 1] = utf8.char(cp)
|
||||
end
|
||||
end
|
||||
flush_normal()
|
||||
flush_symbole()
|
||||
|
||||
return teile
|
||||
end
|
||||
|
||||
-- pandoc 3.1.3 ruft Filterhandler ausschließlich als globale Funktionen auf;
|
||||
-- ein zurückgegebenes Handler-Table würde stillschweigend ignoriert.
|
||||
function Str(el)
|
||||
-- Schneller Ausstieg: nur anfassen, wenn überhaupt Multibyte drin ist.
|
||||
if not el.text:find("[\194-\244]") then
|
||||
return nil
|
||||
end
|
||||
local ok, teile = pcall(ersetze, el.text)
|
||||
if not ok then
|
||||
-- Kaputtes UTF-8 o. ä.: Element unverändert durchreichen.
|
||||
return nil
|
||||
end
|
||||
return teile
|
||||
end
|
||||
Loading…
Reference in a new issue