Use C8 for coverage
This commit is contained in:
@ -17,7 +17,6 @@
|
|||||||
"dolan",
|
"dolan",
|
||||||
"execa",
|
"execa",
|
||||||
"falsey",
|
"falsey",
|
||||||
"fflate",
|
|
||||||
"iife",
|
"iife",
|
||||||
"Initializable",
|
"Initializable",
|
||||||
"iroha",
|
"iroha",
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -59,6 +59,3 @@ My Document.docx
|
|||||||
|
|
||||||
# Temporary folder
|
# Temporary folder
|
||||||
tmp
|
tmp
|
||||||
|
|
||||||
# nyc
|
|
||||||
.nyc_output
|
|
||||||
|
25
.nycrc
25
.nycrc
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"check-coverage": true,
|
|
||||||
"statements": 99.87,
|
|
||||||
"branches": 98.21,
|
|
||||||
"functions": 100,
|
|
||||||
"lines": 99.86,
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"src/**/*.spec.ts",
|
|
||||||
"src/import-dotx/import-dotx.ts"
|
|
||||||
],
|
|
||||||
"reporter": [
|
|
||||||
"lcov",
|
|
||||||
"text",
|
|
||||||
"json"
|
|
||||||
],
|
|
||||||
"extension": [
|
|
||||||
".ts"
|
|
||||||
],
|
|
||||||
"cache": true,
|
|
||||||
"all": true,
|
|
||||||
"sourceMap": true
|
|
||||||
}
|
|
2503
package-lock.json
generated
2503
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@ -22,9 +22,8 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"test": "vitest run",
|
"test": "vitest",
|
||||||
"test.coverage": "nyc npm test",
|
"test.coverage": "vitest run --coverage",
|
||||||
"test.watch": "vitest",
|
|
||||||
"prepublishOnly": "npm run build --omit=dev",
|
"prepublishOnly": "npm run build --omit=dev",
|
||||||
"lint": "eslint --ext .ts src",
|
"lint": "eslint --ext .ts src",
|
||||||
"predemo": "npm run build",
|
"predemo": "npm run build",
|
||||||
@ -72,16 +71,13 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://docx.js.org",
|
"homepage": "https://docx.js.org",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.15",
|
|
||||||
"@types/chai-as-promised": "^7.1.5",
|
|
||||||
"@types/inquirer": "^9.0.3",
|
"@types/inquirer": "^9.0.3",
|
||||||
"@types/prompt": "^1.1.1",
|
"@types/prompt": "^1.1.1",
|
||||||
"@types/unzipper": "^0.10.4",
|
"@types/unzipper": "^0.10.4",
|
||||||
"@types/xml": "^1.0.8",
|
"@types/xml": "^1.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.36.1",
|
"@typescript-eslint/eslint-plugin": "^5.36.1",
|
||||||
"@typescript-eslint/parser": "^5.36.1",
|
"@typescript-eslint/parser": "^5.36.1",
|
||||||
"chai": "^4.3.6",
|
"@vitest/coverage-c8": "^0.32.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
|
||||||
"cspell": "^6.2.2",
|
"cspell": "^6.2.2",
|
||||||
"docsify-cli": "^4.3.0",
|
"docsify-cli": "^4.3.0",
|
||||||
"eslint": "^8.23.0",
|
"eslint": "^8.23.0",
|
||||||
@ -95,7 +91,6 @@
|
|||||||
"glob": "^9.3.0",
|
"glob": "^9.3.0",
|
||||||
"inquirer": "^9.2.7",
|
"inquirer": "^9.2.7",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"nyc": "^15.1.0",
|
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
/* tslint:disable:typedef space-before-function-paren */
|
|
||||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import * as fflate from "fflate";
|
|
||||||
|
|
||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
import { Footer, Header } from "@file/header";
|
import { Footer, Header } from "@file/header";
|
||||||
@ -9,21 +7,6 @@ import * as convenienceFunctions from "@util/convenience-functions";
|
|||||||
|
|
||||||
import { Compiler } from "./next-compiler";
|
import { Compiler } from "./next-compiler";
|
||||||
|
|
||||||
const unzip = (zipFile: Uint8Array): Promise<ReadonlySet<string>> => {
|
|
||||||
const set = new Set<string>();
|
|
||||||
const unzipper = new fflate.Unzip((file) => {
|
|
||||||
set.add(file.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise<ReadonlySet<string>>((resolve) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve(set);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
unzipper.push(zipFile, true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("Compiler", () => {
|
describe("Compiler", () => {
|
||||||
let compiler: Compiler;
|
let compiler: Compiler;
|
||||||
|
|
||||||
@ -42,18 +25,18 @@ describe("Compiler", () => {
|
|||||||
describe("#compile()", () => {
|
describe("#compile()", () => {
|
||||||
it(
|
it(
|
||||||
"should pack all the content",
|
"should pack all the content",
|
||||||
async () => {
|
() => {
|
||||||
const file = new File({
|
const file = new File({
|
||||||
sections: [],
|
sections: [],
|
||||||
comments: {
|
comments: {
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const zipFile = await compiler.compile(file);
|
const zipFile = compiler.compile(file);
|
||||||
const fileNames = await unzip(zipFile);
|
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
|
||||||
|
|
||||||
expect(fileNames).has.length(13);
|
expect(fileNames).is.an.instanceof(Array);
|
||||||
expect(fileNames).to.include("word/document.xml");
|
expect(fileNames).has.length(17);
|
||||||
expect(fileNames).to.include("word/document.xml");
|
expect(fileNames).to.include("word/document.xml");
|
||||||
expect(fileNames).to.include("word/styles.xml");
|
expect(fileNames).to.include("word/styles.xml");
|
||||||
expect(fileNames).to.include("docProps/core.xml");
|
expect(fileNames).to.include("docProps/core.xml");
|
||||||
@ -75,7 +58,7 @@ describe("Compiler", () => {
|
|||||||
|
|
||||||
it(
|
it(
|
||||||
"should pack all additional headers and footers",
|
"should pack all additional headers and footers",
|
||||||
async () => {
|
() => {
|
||||||
const file = new File({
|
const file = new File({
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
@ -107,10 +90,12 @@ describe("Compiler", () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const zipFile = await compiler.compile(file);
|
const zipFile = compiler.compile(file);
|
||||||
const fileNames = await unzip(zipFile);
|
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(21);
|
|
||||||
expect(fileNames).to.include("word/header1.xml");
|
expect(fileNames).to.include("word/header1.xml");
|
||||||
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
expect(fileNames).to.include("word/_rels/header1.xml.rels");
|
||||||
expect(fileNames).to.include("word/header2.xml");
|
expect(fileNames).to.include("word/header2.xml");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { strToU8, zip } from "fflate";
|
import JSZip from "jszip";
|
||||||
import xml from "xml";
|
import xml from "xml";
|
||||||
|
|
||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
@ -44,39 +44,26 @@ export class Compiler {
|
|||||||
this.numberingReplacer = new NumberingReplacer();
|
this.numberingReplacer = new NumberingReplacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public compile(file: File, prettifyXml?: PrettifyType): Promise<Uint8Array> {
|
public compile(file: File, prettifyXml?: PrettifyType): JSZip {
|
||||||
|
const zip = new JSZip();
|
||||||
const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
|
const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
|
||||||
const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping));
|
const map = new Map<string, IXmlifyedFile | readonly IXmlifyedFile[]>(Object.entries(xmlifiedFileMapping));
|
||||||
|
|
||||||
return new Promise<Uint8Array>((resolve, reject) => {
|
for (const [, obj] of map) {
|
||||||
zip(
|
|
||||||
{
|
|
||||||
...Array.from(map.entries()).reduce((acc, [, obj]) => {
|
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
for (const subFile of obj as readonly IXmlifyedFile[]) {
|
for (const subFile of obj as readonly IXmlifyedFile[]) {
|
||||||
// eslint-disable-next-line functional/immutable-data
|
zip.file(subFile.path, subFile.data);
|
||||||
acc[subFile.path] = strToU8(subFile.data);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line functional/immutable-data
|
zip.file((obj as IXmlifyedFile).path, (obj as IXmlifyedFile).data);
|
||||||
acc[(obj as IXmlifyedFile).path] = strToU8((obj as IXmlifyedFile).data);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
for (const { stream, fileName } of file.Media.Array) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
zip.file(`word/media/${fileName}`, stream);
|
||||||
}, {} as any),
|
|
||||||
...file.Media.Array.reduce((acc, { stream, fileName }) => ({ ...acc, [`word/media/${fileName}`]: stream }), {}),
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
(err, data) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(data);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
);
|
return zip;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private xmlifyFile(file: File, prettify?: PrettifyType): IXmlifyedFileMapping {
|
private xmlifyFile(file: File, prettify?: PrettifyType): IXmlifyedFileMapping {
|
||||||
|
@ -3,7 +3,7 @@ import { afterEach, assert, beforeEach, describe, expect, it, vi } from "vitest"
|
|||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
import { HeadingLevel, Paragraph } from "@file/paragraph";
|
import { HeadingLevel, Paragraph } from "@file/paragraph";
|
||||||
|
|
||||||
import { Packer } from "./packer";
|
import { Packer, PrettifyType } from "./packer";
|
||||||
|
|
||||||
describe("Packer", () => {
|
describe("Packer", () => {
|
||||||
let file: File;
|
let file: File;
|
||||||
@ -35,6 +35,36 @@ describe("Packer", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("prettify", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use a default prettify value", async () => {
|
||||||
|
const spy = vi.spyOn((Packer as any).compiler, "compile");
|
||||||
|
|
||||||
|
await Packer.toString(file, true);
|
||||||
|
|
||||||
|
expect(spy).toBeCalledWith(expect.anything(), PrettifyType.WITH_2_BLANKS);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use a prettify value", async () => {
|
||||||
|
const spy = vi.spyOn((Packer as any).compiler, "compile");
|
||||||
|
|
||||||
|
await Packer.toString(file, PrettifyType.WITH_4_BLANKS);
|
||||||
|
|
||||||
|
expect(spy).toBeCalledWith(expect.anything(), PrettifyType.WITH_4_BLANKS);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use an undefined prettify value", async () => {
|
||||||
|
const spy = vi.spyOn((Packer as any).compiler, "compile");
|
||||||
|
|
||||||
|
await Packer.toString(file, false);
|
||||||
|
|
||||||
|
expect(spy).toBeCalledWith(expect.anything(), undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("#toString()", () => {
|
describe("#toString()", () => {
|
||||||
it("should return a non-empty string", async () => {
|
it("should return a non-empty string", async () => {
|
||||||
const result = await Packer.toString(file);
|
const result = await Packer.toString(file);
|
||||||
@ -133,7 +163,10 @@ describe("Packer", () => {
|
|||||||
describe("#toStream()", () => {
|
describe("#toStream()", () => {
|
||||||
it("should create a standard docx file", async () => {
|
it("should create a standard docx file", async () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
vi.spyOn((Packer as any).compiler, "compile").mockReturnValue(Promise.resolve(new Uint8Array(255)));
|
vi.spyOn((Packer as any).compiler, "compile").mockReturnValue({
|
||||||
|
// tslint:disable-next-line: no-empty
|
||||||
|
generateAsync: () => Promise.resolve(vi.fn()),
|
||||||
|
});
|
||||||
const stream = Packer.toStream(file);
|
const stream = Packer.toStream(file);
|
||||||
|
|
||||||
const p = new Promise<void>((resolve, reject) => {
|
const p = new Promise<void>((resolve, reject) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Stream } from "stream";
|
import { Stream } from "stream";
|
||||||
import { File } from "@file/file";
|
import { File } from "@file/file";
|
||||||
import { strFromU8 } from "fflate";
|
|
||||||
|
|
||||||
import { Compiler } from "./next-compiler";
|
import { Compiler } from "./next-compiler";
|
||||||
|
|
||||||
@ -14,46 +13,63 @@ export enum PrettifyType {
|
|||||||
WITH_TAB = "\t",
|
WITH_TAB = "\t",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const convertPrettifyType = (prettify?: boolean | PrettifyType): PrettifyType | undefined =>
|
||||||
|
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify;
|
||||||
|
|
||||||
export class Packer {
|
export class Packer {
|
||||||
public static async toString(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
public static async toString(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
||||||
const zip = await this.compiler.compile(
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
file,
|
const zipData = await zip.generateAsync({
|
||||||
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify,
|
type: "string",
|
||||||
);
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
return strFromU8(zip);
|
compression: "DEFLATE",
|
||||||
|
});
|
||||||
|
|
||||||
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBuffer(file: File, prettify?: boolean | PrettifyType): Promise<Buffer> {
|
public static async toBuffer(file: File, prettify?: boolean | PrettifyType): Promise<Buffer> {
|
||||||
const zip = await this.compiler.compile(
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
file,
|
const zipData = await zip.generateAsync({
|
||||||
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify,
|
type: "nodebuffer",
|
||||||
);
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
return Buffer.from(zip.buffer);
|
compression: "DEFLATE",
|
||||||
|
});
|
||||||
|
|
||||||
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBase64String(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
public static async toBase64String(file: File, prettify?: boolean | PrettifyType): Promise<string> {
|
||||||
const zip = await this.compiler.compile(
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
file,
|
const zipData = await zip.generateAsync({
|
||||||
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify,
|
type: "base64",
|
||||||
);
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
compression: "DEFLATE",
|
||||||
|
});
|
||||||
|
|
||||||
return Promise.resolve(strFromU8(zip));
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async toBlob(file: File, prettify?: boolean | PrettifyType): Promise<Blob> {
|
public static async toBlob(file: File, prettify?: boolean | PrettifyType): Promise<Blob> {
|
||||||
const zip = await this.compiler.compile(
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
file,
|
const zipData = await zip.generateAsync({
|
||||||
prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify,
|
type: "blob",
|
||||||
);
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
compression: "DEFLATE",
|
||||||
|
});
|
||||||
|
|
||||||
return new Blob([zip.buffer]);
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static toStream(file: File, prettify?: boolean | PrettifyType): Stream {
|
public static toStream(file: File, prettify?: boolean | PrettifyType): Stream {
|
||||||
const zip = this.compiler.compile(file, prettify === true ? PrettifyType.WITH_2_BLANKS : prettify === false ? undefined : prettify);
|
|
||||||
const stream = new Stream();
|
const stream = new Stream();
|
||||||
|
const zip = this.compiler.compile(file, convertPrettifyType(prettify));
|
||||||
|
|
||||||
zip.then((z) => {
|
zip.generateAsync({
|
||||||
|
type: "nodebuffer",
|
||||||
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
compression: "DEFLATE",
|
||||||
|
}).then((z) => {
|
||||||
stream.emit("data", z);
|
stream.emit("data", z);
|
||||||
stream.emit("end");
|
stream.emit("end");
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import * as chai from "chai";
|
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
import chaiAsPromised from "chai-as-promised";
|
|
||||||
|
|
||||||
import { ExternalHyperlink, ImageRun, Paragraph, TextRun } from "@file/paragraph";
|
import { ExternalHyperlink, ImageRun, Paragraph, TextRun } from "@file/paragraph";
|
||||||
|
|
||||||
import { patchDocument, PatchType } from "./from-docx";
|
import { patchDocument, PatchType } from "./from-docx";
|
||||||
|
|
||||||
chai.use(chaiAsPromised);
|
|
||||||
|
|
||||||
const MOCK_XML = `
|
const MOCK_XML = `
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
|
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
|
||||||
|
@ -22,6 +22,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
|
minify: false,
|
||||||
lib: {
|
lib: {
|
||||||
entry: [resolve(__dirname, "src/index.ts")],
|
entry: [resolve(__dirname, "src/index.ts")],
|
||||||
name: "docx",
|
name: "docx",
|
||||||
@ -35,5 +36,13 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
environment: "jsdom",
|
environment: "jsdom",
|
||||||
|
coverage: {
|
||||||
|
provider: "c8",
|
||||||
|
reporter: ["text", "json", "html"],
|
||||||
|
statements: 99.93,
|
||||||
|
branches: 98.85,
|
||||||
|
functions: 100,
|
||||||
|
lines: 99.93,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user