91 lines
3.6 KiB
Lua
91 lines
3.6 KiB
Lua
-- 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
|