pptx-embed-fonts
Version:
Embed fonts in pptx files
294 lines (289 loc) • 10.2 kB
JavaScript
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/parse.ts
import JSZip from "jszip";
function toZip(file) {
return __async(this, null, function* () {
const zip = new JSZip();
return zip.loadAsync(file);
});
}
// src/index.ts
import opentype from "opentype.js";
import { DOMParser } from "@xmldom/xmldom";
// src/utils.ts
import { Font } from "fonteditor-core";
import pako from "pako";
function fontToEot(type, fontBuffer) {
const font = Font.create(fontBuffer, {
type,
hinting: true,
inflate: pako.inflate
});
const eotBuffer = font.write({
type: "eot",
toBuffer: true
});
return new Uint8Array(eotBuffer).buffer;
}
// src/index.ts
var _a, _b;
var isNode = typeof process !== "undefined" && !!((_a = process.versions) == null ? void 0 : _a.node) && ((_b = process.release) == null ? void 0 : _b.name) === "node";
var START_RID = 201314;
var PPTXEmbedFonts = class {
constructor(zip) {
this.rId = START_RID;
this._notLoadedError = "pptx file not loaded";
this.fonts = [];
if (zip) {
this.zip = zip;
}
}
loadZip(zip) {
return __async(this, null, function* () {
this.zip = zip;
});
}
load(fileBuffer) {
return __async(this, null, function* () {
this.zip = yield toZip(fileBuffer);
});
}
getFontInfo(fontBuffer) {
const font = opentype.parse(fontBuffer);
return font;
}
updateContentTypesXML() {
return __async(this, null, function* () {
if (!this.zip) {
throw new Error(this._notLoadedError);
}
const contentTypes = this.zip.file("[Content_Types].xml");
if (!contentTypes) {
throw new Error("[Content_Types].xml not found");
}
const contentTypesXml = yield contentTypes.async("string");
const domParser = new DOMParser();
const doc = domParser.parseFromString(contentTypesXml, "text/xml");
const Types = doc.getElementsByTagName(`Types`)[0];
if (!Types) {
throw new Error("Types not found");
}
const defaultElements = doc.getElementsByTagName(`Default`);
const fntdataExtensionElement = Array.from(defaultElements).find(
(element) => {
if (element.getAttribute("Extension") === "fntdata") {
return element;
}
}
);
if (!fntdataExtensionElement) {
const fntdataExtensionElement2 = doc.createElement("Default");
fntdataExtensionElement2.setAttribute("Extension", "fntdata");
fntdataExtensionElement2.setAttribute(
"ContentType",
"application/x-fontdata"
);
Types.insertBefore(fntdataExtensionElement2, Types.firstChild);
}
this.zip.file("[Content_Types].xml", doc.toString());
});
}
updatePresentationXML() {
return __async(this, null, function* () {
if (!this.zip) throw new Error(this._notLoadedError);
const presentation = this.zip.file("ppt/presentation.xml");
if (!presentation) throw new Error("presentation.xml not found");
const presentationXml = yield presentation.async("string");
const domParser = new DOMParser();
const doc = domParser.parseFromString(presentationXml, "text/xml");
const presentationNode = doc.getElementsByTagName(`p:presentation`)[0];
if (!presentationNode) throw new Error("presentationNode not found");
presentationNode.setAttribute("saveSubsetFonts", "true");
presentationNode.setAttribute("embedTrueTypeFonts", "true");
const createEmbeddedFontNode = (font) => {
const embeddedFontNode = doc.createElement("p:embeddedFont");
const fontNode = doc.createElement("p:font");
fontNode.setAttribute("typeface", font.name);
embeddedFontNode.appendChild(fontNode);
const regularNode = doc.createElement("p:regular");
regularNode.setAttribute("r:id", `rId${font.rid}`);
embeddedFontNode.appendChild(regularNode);
return embeddedFontNode;
};
let embeddedFontLstNode = presentationNode.getElementsByTagName("p:embeddedFontLst")[0];
if (!embeddedFontLstNode) {
embeddedFontLstNode = doc.createElement("p:embeddedFontLst");
const defaultTextStyleNode = presentationNode.getElementsByTagName("p:defaultTextStyle")[0];
if (defaultTextStyleNode) {
presentationNode.insertBefore(
embeddedFontLstNode,
defaultTextStyleNode
);
} else {
const sldSzNode = presentationNode.getElementsByTagName("p:sldSz")[0];
const notesSzNode = presentationNode.getElementsByTagName("p:notesSz")[0];
const referenceNode = notesSzNode || sldSzNode || presentationNode.lastChild;
if (referenceNode) {
presentationNode.insertBefore(
embeddedFontLstNode,
referenceNode.nextSibling
);
} else {
presentationNode.appendChild(embeddedFontLstNode);
}
}
}
this.fonts.forEach((font) => {
const existingFont = Array.from(
embeddedFontLstNode.getElementsByTagName("p:font")
).find((node) => node.getAttribute("typeface") === font.name);
if (!existingFont) {
embeddedFontLstNode.appendChild(createEmbeddedFontNode(font));
}
});
this.zip.file("ppt/presentation.xml", doc.toString());
});
}
updateRelsPresentationXML() {
return __async(this, null, function* () {
if (!this.zip) {
throw new Error(this._notLoadedError);
}
const relsPresentation = this.zip.file("ppt/_rels/presentation.xml.rels");
if (!relsPresentation) {
throw new Error("presentation.xml.rels not found");
}
const relsPresentationXml = yield relsPresentation.async("string");
const domParser = new DOMParser();
const doc = domParser.parseFromString(relsPresentationXml, "text/xml");
const relationshipsNode = doc.getElementsByTagName(`Relationships`)[0];
if (!relationshipsNode) {
throw new Error("Relationships not found");
}
this.fonts.forEach((font) => {
const relationshipNode = doc.createElement("Relationship");
relationshipNode.setAttribute("Id", `rId${font.rid}`);
relationshipNode.setAttribute("Target", `fonts/${font.rid}.fntdata`);
relationshipNode.setAttribute(
"Type",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/font"
);
relationshipsNode.appendChild(relationshipNode);
});
this.zip.file("ppt/_rels/presentation.xml.rels", doc.toString());
});
}
updateFontFiles() {
if (!this.zip) {
throw new Error(this._notLoadedError);
}
this.fonts.forEach((font) => {
this.zip.file(`ppt/fonts/${font.rid}.fntdata`, font.data, {
binary: true,
compression: "DEFLATE"
});
});
}
uniqueId() {
return this.rId++;
}
eot2FntData(eotFile) {
return __async(this, null, function* () {
const unit8Array = new Uint8Array(eotFile);
const blob = new Blob([unit8Array], {
type: "font/opentype"
});
return yield blob.arrayBuffer();
});
}
addFont(fontFace, fntData) {
return __async(this, null, function* () {
const rid = this.uniqueId();
this.fonts.push({ name: fontFace, data: fntData, rid });
});
}
addFontFromEOT(fontFace, eotFile) {
return __async(this, null, function* () {
const fontData = yield this.eot2FntData(eotFile);
yield this.addFont(fontFace, fontData);
});
}
addFontFromTTF(fontFace, ttfFile) {
return __async(this, null, function* () {
const eotFile = fontToEot("ttf", ttfFile);
yield this.addFontFromEOT(fontFace, eotFile);
});
}
addFontFromWOFF(fontFace, woffFile) {
return __async(this, null, function* () {
const eotFile = fontToEot("woff", woffFile);
yield this.addFontFromEOT(fontFace, eotFile);
});
}
addFontFromOTF(fontFace, otfFile) {
return __async(this, null, function* () {
const eotFile = fontToEot("otf", otfFile);
yield this.addFontFromEOT(fontFace, eotFile);
});
}
updateFiles() {
return __async(this, null, function* () {
yield this.updateContentTypesXML();
yield this.updatePresentationXML();
yield this.updateRelsPresentationXML();
this.updateFontFiles();
});
}
save() {
return __async(this, null, function* () {
if (!this.zip) {
throw new Error(this._notLoadedError);
}
yield this.updateFiles();
const outputType = isNode ? "nodebuffer" : "arraybuffer";
return this.zip.generateAsync({
type: outputType,
compression: "DEFLATE",
compressionOptions: {
level: 6
// 或 9
}
});
});
}
};
var index_default = PPTXEmbedFonts;
export {
__privateGet,
__privateAdd,
__privateSet,
__async,
index_default
};
//# sourceMappingURL=chunk-3SSGPEOK.js.map