@openpresentation/opf-pptx 0.12.1 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/script-fonts.js +23 -3
- package/package.json +1 -1
package/dist/script-fonts.js
CHANGED
|
@@ -90,6 +90,22 @@ function contentEastAsianFonts(presentation, deck, report) {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// RR-17 (RR-42 native run, 2026-10-02): Office's theme carries per-language script entries that core's script model does
|
|
94
|
+
// not name, because the language is written in a script core treats as Latin or as the plain complex-script slot:
|
|
95
|
+
// `Viet` (Vietnamese, `vi`) and `Uigh` (Uyghur, `ug`). PowerPoint applies the entry to runs in that language and lists its
|
|
96
|
+
// family in Presentation.Fonts, so the Office default (Viet: Times New Roman / Arial) named a font the deck never uses.
|
|
97
|
+
// The deck's own language entry names the family the deck uses for its text: the theme latin family (major latin in
|
|
98
|
+
// majorFont, minor latin in minorFont); for Uyghur, the complex-script family when the deck selects one. Entries for
|
|
99
|
+
// other languages stay as vendored.
|
|
100
|
+
const LANGUAGE_SCRIPT_SUPPLEMENTS = [[/^vi(?:-|$)/i, "Viet"], [/^ug(?:-|$)/i, "Uigh"]];
|
|
101
|
+
function languageScriptSupplement(deck) {
|
|
102
|
+
const match = LANGUAGE_SCRIPT_SUPPLEMENTS.find(([tag]) => tag.test(String(deck.lang ?? "")));
|
|
103
|
+
if (!match) return undefined;
|
|
104
|
+
const script = match[1];
|
|
105
|
+
const role = script === "Uigh" && deck.sources?.complexScript && deck.sources.complexScript !== "latin" ? "complexScript" : "latin";
|
|
106
|
+
return {script, heading: deck.heading?.[role], body: deck.body?.[role]};
|
|
107
|
+
}
|
|
108
|
+
|
|
93
109
|
const escapeAttribute = value => String(value).replace(/[&<>"']/g, char => ({"&": "&", "<": "<", ">": ">", "\"": """, "'": "'"}[char]));
|
|
94
110
|
|
|
95
111
|
/**
|
|
@@ -108,8 +124,10 @@ const escapeAttribute = value => String(value).replace(/[&<>"']/g, char => ({"&"
|
|
|
108
124
|
* Japanese deck writes `ea` only.
|
|
109
125
|
*/
|
|
110
126
|
export function themeScriptFonts(xml, plan) {
|
|
111
|
-
const {heading, body
|
|
112
|
-
|
|
127
|
+
const {heading, body} = plan.deck;
|
|
128
|
+
// Core's supplement (the language's script entry, such as Arab for Uyghur) and the language's own entry (Viet, Uigh).
|
|
129
|
+
const supplements = [plan.deck.supplement, languageScriptSupplement(plan.deck)].filter((entry, index, all) => entry && all.findIndex(other => other?.script === entry.script) === index);
|
|
130
|
+
for (const [tag, slots, role] of [["majorFont", heading, "heading"], ["minorFont", body, "body"]]) {
|
|
113
131
|
xml = xml.replace(new RegExp(`<a:${tag}>[\\s\\S]*?</a:${tag}>`), block => {
|
|
114
132
|
for (const [element, slot] of SCRIPT_SLOTS) {
|
|
115
133
|
// FF-05: the East Asian slot always names a font (a script font, a font for the East Asian text, else the latin
|
|
@@ -120,7 +138,9 @@ export function themeScriptFonts(xml, plan) {
|
|
|
120
138
|
const face = escapeAttribute(content ?? slots[slot]);
|
|
121
139
|
block = block.replace(new RegExp(`<a:${element}\\b[^>]*/>`), `<a:${element} typeface="${face}"/>`);
|
|
122
140
|
}
|
|
123
|
-
|
|
141
|
+
for (const supplement of supplements) {
|
|
142
|
+
const family = supplement[role];
|
|
143
|
+
if (!family) continue;
|
|
124
144
|
const entry = `<a:font script="${supplement.script}" typeface="${escapeAttribute(family)}"/>`;
|
|
125
145
|
const existing = new RegExp(`<a:font script="${supplement.script}" typeface="[^"]*"/>`);
|
|
126
146
|
block = existing.test(block) ? block.replace(existing, entry) : block.replace(`</a:${tag}>`, `${entry}</a:${tag}>`);
|