docxml
Version:
TypeScript (component) library for building and parsing a DOCX file
182 lines (181 loc) • 5.05 kB
JavaScript
import * as dntShim from "../../../../_dnt.shims.js";
import _JSZip from "jszip";
import { walk } from "../../std@0.116.0/fs/walk.js";
import { SEP, join } from "../../std@0.116.0/path/mod.js";
/**
* Read zip file asynchronously from a file
*
* @param path of zip file
* @return Returns promise
*/
export async function readZip(path) {
const z = new JSZip();
const content = await dntShim.Deno.readFile(path);
await z.loadAsync(content);
return z;
}
/**
* Read a directory as a JSZip
*
* @param dir directory
* @return Returns promise
*/
export async function zipDir(dir, options) {
const z = new JSZip();
const cwd = dntShim.Deno.cwd();
// FIXME it would be nice to do this without chdir...
dntShim.Deno.chdir(dir);
try {
for await (const f of walk(".", options)) {
if (f.isDirectory) {
// skip directories
continue;
}
const contents = await dntShim.Deno.readFile(f.path);
// In order to support Windows we do this ridiculousness.
let ff = f.path.split(SEP);
let zz = z;
while (ff.length > 1) {
zz = zz.folder(ff.shift());
}
zz.addFile(ff[0], contents);
}
}
finally {
dntShim.Deno.chdir(cwd);
}
return z;
}
export class JSZip {
// we should assert the type (we want it to be a _JSZip) ?
constructor(z) {
Object.defineProperty(this, "_z", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
if (z === undefined) {
// @ts-ignores
this._z = new _JSZip();
}
else {
this._z = z;
}
}
/**
* Returns an new JSZip instance with the given folder as root
*
* @param name Name of the folder
* @return New JSZip object with the given folder as root or null
*/
folder(name) {
// @ts-ignores
const f = this._z.folder(name);
return new JSZip(f);
}
/**
* Get a file from the archive
*
* @param Path relative path to file
* @return File matching path, null if no file found
*/
file(path) {
// @ts-ignores
const f = this._z.file(path);
return f;
}
/**
* Add a file to the archive
*
* @param path Relative path to file
* @param data Content of the file
* @param options Optional information about the file
* @return JSZip object
*/
addFile(path, content, options) {
// @ts-ignores
const f = this._z.file(path, content, options);
return f;
}
files() {
// @ts-ignores
const fs = this._z.files;
return fs;
}
/**
* Generates a new archive asynchronously
*
* @param options Optional options for the generator
* @param onUpdate The optional function called on each internal update with the metadata.
* @return The serialized archive
*/
async generateAsync(options) {
// @ts-ignores
return await this._z.generateAsync(options);
}
/**
* Get all files which match the given filter function
*
* @param predicate Filter function
* @return Array of matched elements
*/
filter(predicate) {
// @ts-ignores
return this._z.filter(predicate);
}
/**
* Removes the file or folder from the archive
*
* @param path Relative path of file or folder
* @return Returns the JSZip instance
*/
remove(path) {
// @ts-ignores
return this._z.remove(path);
}
/**
* Load zip data
*
* @param data Serialized zip file
* @param options Options for deserializing
* @return Returns promise of self
*/
async loadAsync(data, options) {
await this._z.loadAsync(data, options);
return this;
}
/**
* Write zip file asynchronously to a file
*
* @param path of zip file
* @return Returns promise
*/
async writeZip(path) {
const b = await this.generateAsync({ type: "uint8array" });
return await dntShim.Deno.writeFile(path, b);
}
/**
* Unzip a JSZip asynchronously to a directory
*
* @param dir to unzip into
* @return Returns promise
*/
async unzip(dir = ".") {
// FIXME optionally replace the existing folder prefix with dir.
for (const f of this) {
const ff = join(dir, f.name);
if (f.dir) {
// hopefully the directory is prior to any files inside it!
await dntShim.Deno.mkdir(ff, { recursive: true });
continue;
}
const content = await f.async("uint8array");
// TODO pass WriteFileOptions e.g. mode
await dntShim.Deno.writeFile(ff, content);
}
}
*[Symbol.iterator]() {
yield* Object.values(this.files());
}
}