Merge pull request #89 from dolanmiu/feat/base64-image

Image methods
This commit is contained in:
Dolan
2018-08-03 02:22:46 +01:00
committed by GitHub
14 changed files with 435 additions and 93 deletions

15
demo/demo18.js Normal file
View File

@ -0,0 +1,15 @@
// Insert image from a buffer
const docx = require('../build');
var doc = new docx.Document();
const imageBase64Data = `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`
// doc.createImageFromBuffer(Buffer.from(imageBase64Data, 'base64'));
doc.createImageFromBuffer(Buffer.from(imageBase64Data, 'base64'), 100, 100);
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
console.log('Document created successfully at project root!');

28
demo/demo23.js Normal file
View File

@ -0,0 +1,28 @@
// This demo adds an image to the Media cache, and then insert to the document afterwards
const docx = require("../build");
var doc = new docx.Document();
var paragraph = new docx.Paragraph("Hello World");
doc.addParagraph(paragraph);
const image = docx.Media.addImage(doc, "./demo/images/image1.jpeg");
const image2 = docx.Media.addImage(doc, "./demo/images/dog.png");
const image3 = docx.Media.addImage(doc, "./demo/images/cat.jpg");
const image4 = docx.Media.addImage(doc, "./demo/images/parrots.bmp");
const image5 = docx.Media.addImage(doc, "./demo/images/pizza.gif");
const imageBase64Data = `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`
const image6 = docx.Media.addImageFromBuffer(doc, Buffer.from(imageBase64Data, 'base64'), 100, 100);
doc.insertImage(image);
doc.insertImage(image2);
doc.insertImage(image3);
doc.insertImage(image4);
doc.insertImage(image5);
doc.insertImage(image6);
var exporter = new docx.LocalPacker(doc);
exporter.pack("My Document");
console.log("Document created successfully at project root!");

15
demo/demo24.js Normal file
View File

@ -0,0 +1,15 @@
// Add image to table cell
const docx = require('../build');
var doc = new docx.Document();
const table = doc.createTable(4, 4);
table.getCell(2, 2).addContent(new docx.Paragraph('Hello'));
const image = docx.Media.addImage(doc, "./demo/images/image1.jpeg");
table.getCell(1, 1).addContent(image);
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
console.log('Document created successfully at project root!');

View File

@ -1,17 +1,17 @@
const docx = require('../build');
const docx = require("../build");
var doc = new docx.Document();
var paragraph = new docx.Paragraph("Hello World");
doc.addParagraph(paragraph);
const image = doc.createImage("./demo/images/image1.jpeg");
const image2 = doc.createImage("./demo/images/dog.png");
const image3 = doc.createImage("./demo/images/cat.jpg");
const image4 = doc.createImage("./demo/images/parrots.bmp");
const image5 = doc.createImage("./demo/images/pizza.gif");
doc.createImage("./demo/images/image1.jpeg");
doc.createImage("./demo/images/dog.png");
doc.createImage("./demo/images/cat.jpg");
doc.createImage("./demo/images/parrots.bmp");
doc.createImage("./demo/images/pizza.gif");
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
exporter.pack("My Document");
console.log('Document created successfully at project root!');
console.log("Document created successfully at project root!");

View File

@ -1,7 +1,6 @@
// http://officeopenxml.com/WPdocument.php
import { IMediaData } from "file/media";
import { XmlComponent } from "file/xml-components";
import { Paragraph, PictureRun } from "../paragraph";
import { Paragraph } from "../paragraph";
import { Table } from "../table";
import { Body } from "./body";
import { SectionPropertiesOptions } from "./body/section-properties/section-properties";
@ -37,8 +36,9 @@ export class Document extends XmlComponent {
this.root.push(this.body);
}
public addParagraph(paragraph: Paragraph): void {
public addParagraph(paragraph: Paragraph): Document {
this.body.push(paragraph);
return this;
}
public createParagraph(text?: string): Paragraph {
@ -57,20 +57,6 @@ export class Document extends XmlComponent {
return table;
}
public addDrawing(pictureParagraph: Paragraph): void {
this.body.push(pictureParagraph);
}
public createDrawing(imageData: IMediaData): PictureRun {
const paragraph = new Paragraph();
const run = new PictureRun(imageData);
paragraph.addRun(run);
this.addDrawing(paragraph);
return run;
}
get Body(): Body {
return this.body;
}

View File

@ -1,4 +1,3 @@
import { IMediaData } from "file/media";
import { AppProperties } from "./app-properties/app-properties";
import { ContentTypes } from "./content-types/content-types";
import { CoreProperties, IPropertiesOptions } from "./core-properties";
@ -10,7 +9,7 @@ import { FootNotes } from "./footnotes";
import { HeaderWrapper } from "./header-wrapper";
import { Media } from "./media";
import { Numbering } from "./numbering";
import { Bookmark, Hyperlink, Paragraph, PictureRun } from "./paragraph";
import { Bookmark, Hyperlink, Image, Paragraph } from "./paragraph";
import { Relationships } from "./relationships";
import { Styles } from "./styles";
import { ExternalStylesFactory } from "./styles/external-styles-factory";
@ -32,7 +31,7 @@ export class File {
private readonly contentTypes: ContentTypes;
private readonly appProperties: AppProperties;
private nextId: number = 1;
private currentRelationshipId: number = 1;
constructor(options?: IPropertiesOptions, sectionPropertiesOptions?: SectionPropertiesOptions) {
if (!options) {
@ -55,19 +54,19 @@ export class File {
this.numbering = new Numbering();
this.docRelationships = new Relationships();
this.docRelationships.createRelationship(
this.nextId++,
this.currentRelationshipId++,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
"styles.xml",
);
this.docRelationships.createRelationship(
this.nextId++,
this.currentRelationshipId++,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
"numbering.xml",
);
this.contentTypes = new ContentTypes();
this.docRelationships.createRelationship(
this.nextId++,
this.currentRelationshipId++,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
"footnotes.xml",
);
@ -125,24 +124,23 @@ export class File {
return this.document.createTable(rows, cols);
}
public createImage(image: string): PictureRun {
const mediaData = this.media.addMedia(image, this.nextId++);
this.docRelationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
return this.document.createDrawing(mediaData);
public createImage(filePath: string): Image {
const image = Media.addImage(this, filePath);
this.document.addParagraph(image);
return image;
}
public createImageData(imageName: string, data: Buffer, width?: number, height?: number): IMediaData {
const mediaData = this.media.addMediaWithData(imageName, data, this.nextId++, width, height);
this.docRelationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
return mediaData;
public insertImage(image: Image): File {
this.document.addParagraph(image);
return this;
}
public createImageFromBuffer(buffer: Buffer, width?: number, height?: number): Image {
const image = Media.addImageFromBuffer(this, buffer, width, height);
this.document.addParagraph(image);
return image;
}
public createHyperlink(link: string, text?: string): Hyperlink {
@ -179,11 +177,8 @@ export class File {
this.footNotes.createFootNote(paragraph);
}
/**
* Creates new header.
*/
public createHeader(): HeaderWrapper {
const header = new HeaderWrapper(this.media, this.nextId++);
const header = new HeaderWrapper(this.media, this.currentRelationshipId++);
this.headerWrapper.push(header);
this.docRelationships.createRelationship(
header.Header.referenceId,
@ -194,11 +189,8 @@ export class File {
return header;
}
/**
* Creates new footer.
*/
public createFooter(): FooterWrapper {
const footer = new FooterWrapper(this.media, this.nextId++);
const footer = new FooterWrapper(this.media, this.currentRelationshipId++);
this.footerWrapper.push(footer);
this.docRelationships.createRelationship(
footer.Footer.referenceId,

View File

@ -1,7 +1,7 @@
import { XmlComponent } from "file/xml-components";
import { Footer } from "./footer/footer";
import { IMediaData, Media } from "./media";
import { Paragraph } from "./paragraph";
import { Media } from "./media";
import { Image, Paragraph } from "./paragraph";
import { Relationships } from "./relationships";
import { Table } from "./table";
@ -32,10 +32,6 @@ export class FooterWrapper {
return this.footer.createTable(rows, cols);
}
public addDrawing(imageData: IMediaData): void {
this.footer.addDrawing(imageData);
}
public addChildElement(childElement: XmlComponent | string): void {
this.footer.addChildElement(childElement);
}
@ -47,7 +43,12 @@ export class FooterWrapper {
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
this.addDrawing(mediaData);
this.insertImage(new Image(mediaData));
}
public insertImage(image: Image): FooterWrapper {
this.footer.addParagraph(image);
return this;
}
public get Footer(): Footer {

View File

@ -1,7 +1,6 @@
// http://officeopenxml.com/WPfooters.php
import { IMediaData } from "file/media";
import { XmlComponent } from "file/xml-components";
import { Paragraph, PictureRun } from "../paragraph";
import { Paragraph } from "../paragraph";
import { Table } from "../table";
import { FooterAttributes } from "./footer-attributes";
@ -36,8 +35,10 @@ export class Footer extends XmlComponent {
return this.refId;
}
public addParagraph(paragraph: Paragraph): void {
public addParagraph(paragraph: Paragraph): Footer {
this.root.push(paragraph);
return this;
}
public createParagraph(text?: string): Paragraph {
@ -55,12 +56,4 @@ export class Footer extends XmlComponent {
this.addTable(table);
return table;
}
public addDrawing(imageData: IMediaData): void {
const paragraph = new Paragraph();
const run = new PictureRun(imageData);
paragraph.addRun(run);
this.root.push(paragraph);
}
}

View File

@ -1,7 +1,7 @@
import { XmlComponent } from "file/xml-components";
import { Header } from "./header/header";
import { IMediaData, Media } from "./media";
import { Paragraph } from "./paragraph";
import { Media } from "./media";
import { Image, Paragraph } from "./paragraph";
import { Relationships } from "./relationships";
import { Table } from "./table";
@ -32,10 +32,6 @@ export class HeaderWrapper {
return this.header.createTable(rows, cols);
}
public addDrawing(imageData: IMediaData): void {
this.header.addDrawing(imageData);
}
public addChildElement(childElement: XmlComponent | string): void {
this.header.addChildElement(childElement);
}
@ -47,7 +43,12 @@ export class HeaderWrapper {
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
this.addDrawing(mediaData);
this.insertImage(new Image(mediaData));
}
public insertImage(image: Image): HeaderWrapper {
this.header.addParagraph(image);
return this;
}
public get Header(): Header {

View File

@ -1,7 +1,6 @@
// http://officeopenxml.com/WPheaders.php
import { IMediaData } from "file/media";
import { XmlComponent } from "file/xml-components";
import { Paragraph, PictureRun } from "../paragraph";
import { Paragraph } from "../paragraph";
import { Table } from "../table";
import { HeaderAttributes } from "./header-attributes";
@ -55,12 +54,4 @@ export class Header extends XmlComponent {
this.addTable(table);
return table;
}
public addDrawing(imageData: IMediaData): void {
const paragraph = new Paragraph();
const run = new PictureRun(imageData);
paragraph.addRun(run);
this.root.push(paragraph);
}
}

View File

@ -2,9 +2,58 @@ import * as fs from "fs";
import * as sizeOf from "image-size";
import * as path from "path";
import { File } from "../file";
import { Image } from "../paragraph";
import { IMediaData } from "./data";
interface IHackedFile {
currentRelationshipId: number;
}
export class Media {
public static addImage(file: File, filePath: string): Image {
// Workaround to expose id without exposing to API
const exposedFile = (file as {}) as IHackedFile;
const mediaData = file.Media.addMedia(filePath, exposedFile.currentRelationshipId++);
file.DocumentRelationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
return new Image(mediaData);
}
public static addImageFromBuffer(file: File, buffer: Buffer, width?: number, height?: number): Image {
// Workaround to expose id without exposing to API
const exposedFile = (file as {}) as IHackedFile;
const mediaData = file.Media.addMediaFromBuffer(
`${Media.generateId()}.png`,
buffer,
exposedFile.currentRelationshipId++,
width,
height,
);
file.DocumentRelationships.createRelationship(
mediaData.referenceId,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
`media/${mediaData.fileName}`,
);
return new Image(mediaData);
}
private static generateId(): string {
// https://gist.github.com/6174/6062387
return (
Math.random()
.toString(36)
.substring(2, 15) +
Math.random()
.toString(36)
.substring(2, 15)
);
}
private readonly map: Map<string, IMediaData>;
constructor() {
@ -27,7 +76,7 @@ export class Media {
return this.createMedia(key, referenceId, dimensions, fs.createReadStream(filePath), filePath);
}
public addMediaWithData(fileName: string, data: Buffer, referenceId: number, width?: number, height?: number): IMediaData {
public addMediaFromBuffer(fileName: string, buffer: Buffer, referenceId: number, width?: number, height?: number): IMediaData {
const key = fileName;
let dimensions;
if (width && height) {
@ -36,10 +85,10 @@ export class Media {
height: height,
};
} else {
dimensions = sizeOf(data);
dimensions = sizeOf(buffer);
}
return this.createMedia(key, referenceId, dimensions, data);
return this.createMedia(key, referenceId, dimensions, buffer);
}
private createMedia(
@ -65,6 +114,7 @@ export class Media {
},
},
};
this.map.set(key, imageData);
return imageData;

View File

@ -0,0 +1,251 @@
// tslint:disable:object-literal-key-quotes
import { assert, expect } from "chai";
import { Formatter } from "../../export/formatter";
import { Image } from "./image";
describe("Image", () => {
let image: Image;
beforeEach(() => {
image = new Image({
referenceId: 0,
stream: new Buffer(""),
path: "",
fileName: "",
dimensions: {
pixels: {
x: 10,
y: 10,
},
emus: {
x: 10,
y: 10,
},
},
});
});
describe("#constructor()", () => {
it("should create valid JSON", () => {
const stringifiedJson = JSON.stringify(image);
try {
JSON.parse(stringifiedJson);
} catch (e) {
assert.isTrue(false);
}
assert.isTrue(true);
});
});
describe("#scale()", () => {
it("should set the scale of the object properly", () => {
image.scale(2);
const tree = new Formatter().format(image);
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:drawing": [
{
"wp:inline": [
{
_attr: {
distB: 0,
distL: 0,
distR: 0,
distT: 0,
},
},
{
"wp:extent": [
{
_attr: {
cx: 20,
cy: 20,
},
},
],
},
{
"wp:effectExtent": [
{
_attr: {
b: 0,
l: 0,
r: 0,
t: 0,
},
},
],
},
{
"wp:docPr": [
{
_attr: {
descr: "",
id: 0,
name: "",
},
},
],
},
{
"wp:cNvGraphicFramePr": [
{
"a:graphicFrameLocks": [
{
_attr: {
noChangeAspect: 1,
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
],
},
],
},
{
"a:graphic": [
{
_attr: {
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
{
"a:graphicData": [
{
_attr: {
uri: "http://schemas.openxmlformats.org/drawingml/2006/picture",
},
},
{
"pic:pic": [
{
_attr: {
"xmlns:pic":
"http://schemas.openxmlformats.org/drawingml/2006/picture",
},
},
{
"pic:nvPicPr": [
{
"pic:cNvPr": [
{
_attr: {
desc: "",
id: 0,
name: "",
},
},
],
},
{
"pic:cNvPicPr": [
{
"a:picLocks": [
{
_attr: {
noChangeArrowheads: 1,
noChangeAspect: 1,
},
},
],
},
],
},
],
},
{
"pic:blipFill": [
{
"a:blip": [
{
_attr: {
cstate: "none",
"r:embed": "rId0",
},
},
],
},
{
"a:srcRect": [],
},
{
"a:stretch": [
{
"a:fillRect": [],
},
],
},
],
},
{
"pic:spPr": [
{
_attr: {
bwMode: "auto",
},
},
{
"a:xfrm": [
{
"a:ext": [
{
_attr: {
cx: 10,
cy: 10,
},
},
],
},
{
"a:off": [
{
_attr: {
x: 0,
y: 0,
},
},
],
},
],
},
{
"a:prstGeom": [
{
_attr: {
prst: "rect",
},
},
{
"a:avLst": [],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
});
});
});
});

View File

@ -0,0 +1,18 @@
import { IDrawingOptions } from "../drawing";
import { IMediaData } from "../media";
import { Paragraph } from "./paragraph";
import { PictureRun } from "./run";
export class Image extends Paragraph {
private readonly pictureRun: PictureRun;
constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) {
super();
this.pictureRun = new PictureRun(imageData, drawingOptions);
this.root.push(this.pictureRun);
}
public scale(factorX: number, factorY?: number): void {
this.pictureRun.scale(factorX, factorY);
}
}

View File

@ -3,3 +3,4 @@ export * from "./paragraph";
export * from "./properties";
export * from "./run";
export * from "./links";
export * from "./image";