Feat/embedded fonts (#2174)

* #239 Embedded fonts

* Add boilerplate for font table

* Fix linting

* Fix linting

* Fix odttf naming

* Correct writing of fonts to relationships and font table

new uuid function

* Add font to run

* Add demo

Fix tests

* Add character set support

* Add tests

* Write tests
This commit is contained in:
Dolan
2023-12-30 02:23:54 +00:00
committed by GitHub
parent fa401297da
commit 010ef05ce3
28 changed files with 794 additions and 30 deletions

View File

@ -36,7 +36,7 @@ describe("Compiler", () => {
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
expect(fileNames).is.an.instanceof(Array);
expect(fileNames).has.length(17);
expect(fileNames).has.length(19);
expect(fileNames).to.include("word/document.xml");
expect(fileNames).to.include("word/styles.xml");
expect(fileNames).to.include("docProps/core.xml");
@ -47,7 +47,9 @@ describe("Compiler", () => {
expect(fileNames).to.include("word/_rels/footnotes.xml.rels");
expect(fileNames).to.include("word/settings.xml");
expect(fileNames).to.include("word/comments.xml");
expect(fileNames).to.include("word/fontTable.xml");
expect(fileNames).to.include("word/_rels/document.xml.rels");
expect(fileNames).to.include("word/_rels/fontTable.xml.rels");
expect(fileNames).to.include("[Content_Types].xml");
expect(fileNames).to.include("_rels/.rels");
},
@ -94,7 +96,7 @@ describe("Compiler", () => {
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
expect(fileNames).is.an.instanceof(Array);
expect(fileNames).has.length(25);
expect(fileNames).has.length(27);
expect(fileNames).to.include("word/header1.xml");
expect(fileNames).to.include("word/_rels/header1.xml.rels");
@ -127,12 +129,10 @@ describe("Compiler", () => {
const spy = vi.spyOn(compiler["formatter"], "format");
compiler.compile(file);
expect(spy).toBeCalledTimes(13);
expect(spy).toBeCalledTimes(15);
});
it("should work with media datas", () => {
// This test is required because before, there was a case where Document was formatted twice, which was inefficient
// This also caused issues such as running prepForXml multiple times as format() was ran multiple times.
const file = new File({
sections: [
{
@ -182,5 +182,14 @@ describe("Compiler", () => {
compiler.compile(file);
});
it("should work with fonts", () => {
const file = new File({
sections: [],
fonts: [{ name: "Pacifico", data: Buffer.from("") }],
});
compiler.compile(file);
});
});
});

View File

@ -2,6 +2,7 @@ import JSZip from "jszip";
import xml from "xml";
import { File } from "@file/file";
import { obfuscate } from "@file/fonts/obfuscate-ttf-to-odttf";
import { Formatter } from "../formatter";
import { ImageReplacer } from "./image-replacer";
@ -31,6 +32,8 @@ interface IXmlifyedFileMapping {
readonly FootNotesRelationships: IXmlifyedFile;
readonly Settings: IXmlifyedFile;
readonly Comments?: IXmlifyedFile;
readonly FontTable?: IXmlifyedFile;
readonly FontTableRelationships?: IXmlifyedFile;
}
export class Compiler {
@ -63,6 +66,11 @@ export class Compiler {
zip.file(`word/media/${fileName}`, stream);
}
for (const { data: buffer, name, fontKey } of file.FontTable.fontOptionsWithKey) {
const [nameWithoutExtension] = name.split(".");
zip.file(`word/fonts/${nameWithoutExtension}.odttf`, obfuscate(buffer, fontKey));
}
return zip;
}
@ -439,6 +447,40 @@ export class Compiler {
),
path: "word/comments.xml",
},
FontTable: {
data: xml(
this.formatter.format(file.FontTable.View, {
viewWrapper: file.Document,
file,
stack: [],
}),
{
indent: prettify,
declaration: {
standalone: "yes",
encoding: "UTF-8",
},
},
),
path: "word/fontTable.xml",
},
FontTableRelationships: {
data: (() =>
xml(
this.formatter.format(file.FontTable.Relationships, {
viewWrapper: file.Document,
file,
stack: [],
}),
{
indent: prettify,
declaration: {
encoding: "UTF-8",
},
},
))(),
path: "word/_rels/fontTable.xml.rels",
},
};
}
}