Use context in prep xml
This commit is contained in:
@ -4,20 +4,24 @@ import * as fs from "fs";
|
|||||||
import { Document, ExternalHyperlink, Footer, FootnoteReferenceRun, Media, Packer, Paragraph, TextRun } from "../build";
|
import { Document, ExternalHyperlink, Footer, FootnoteReferenceRun, Media, Packer, Paragraph, TextRun } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
footnotes: [
|
footnotes: {
|
||||||
new Paragraph({
|
1: {
|
||||||
children: [
|
children: [
|
||||||
new TextRun("Click here for the "),
|
new Paragraph({
|
||||||
new ExternalHyperlink({
|
children: [
|
||||||
child: new TextRun({
|
new TextRun("Click here for the "),
|
||||||
text: "Footnotes external hyperlink",
|
new ExternalHyperlink({
|
||||||
style: "Hyperlink",
|
child: new TextRun({
|
||||||
}),
|
text: "Footnotes external hyperlink",
|
||||||
link: "http://www.example.com",
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
link: "http://www.example.com",
|
||||||
|
}),
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
],
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
|
const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
|
||||||
@ -69,7 +73,7 @@ doc.addSection({
|
|||||||
}),
|
}),
|
||||||
link: "http://www.example.com",
|
link: "http://www.example.com",
|
||||||
}),
|
}),
|
||||||
new FootnoteReferenceRun(1)
|
new FootnoteReferenceRun(1),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
|
@ -27,25 +27,29 @@ import {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
footnotes: [
|
footnotes: {
|
||||||
new Paragraph({
|
1: {
|
||||||
children: [
|
children: [
|
||||||
new TextRun("This is a footnote"),
|
new Paragraph({
|
||||||
new DeletedTextRun({
|
children: [
|
||||||
text: " with some extra text which was deleted",
|
new TextRun("This is a footnote"),
|
||||||
id: 0,
|
new DeletedTextRun({
|
||||||
author: "Firstname Lastname",
|
text: " with some extra text which was deleted",
|
||||||
date: "2020-10-06T09:05:00Z",
|
id: 0,
|
||||||
}),
|
author: "Firstname Lastname",
|
||||||
new InsertedTextRun({
|
date: "2020-10-06T09:05:00Z",
|
||||||
text: " and new content",
|
}),
|
||||||
id: 1,
|
new InsertedTextRun({
|
||||||
author: "Firstname Lastname",
|
text: " and new content",
|
||||||
date: "2020-10-06T09:05:00Z",
|
id: 1,
|
||||||
|
author: "Firstname Lastname",
|
||||||
|
date: "2020-10-06T09:05:00Z",
|
||||||
|
}),
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
],
|
},
|
||||||
features: {
|
features: {
|
||||||
trackRevisions: true,
|
trackRevisions: true,
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { IViewWrapper } from "file/document-wrapper";
|
import { BaseXmlComponent, IContext, IXmlableObject } from "file/xml-components";
|
||||||
import { BaseXmlComponent, IXmlableObject } from "file/xml-components";
|
|
||||||
|
|
||||||
export class Formatter {
|
export class Formatter {
|
||||||
public format(input: BaseXmlComponent, file?: IViewWrapper): IXmlableObject {
|
// tslint:disable-next-line: no-object-literal-type-assertion
|
||||||
const output = input.prepForXml(file);
|
public format(input: BaseXmlComponent, context: IContext = {} as IContext): IXmlableObject {
|
||||||
|
const output = input.prepForXml(context);
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
return output;
|
return output;
|
||||||
|
@ -73,7 +73,13 @@ export class Compiler {
|
|||||||
file.verifyUpdateFields();
|
file.verifyUpdateFields();
|
||||||
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
||||||
|
|
||||||
const documentXmlData = xml(this.formatter.format(file.Document.View, file.Document), prettify);
|
const documentXmlData = xml(
|
||||||
|
this.formatter.format(file.Document.View, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
|
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -87,7 +93,13 @@ export class Compiler {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return xml(this.formatter.format(file.Document.Relationships, file.Document), prettify);
|
return xml(
|
||||||
|
this.formatter.format(file.Document.Relationships, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
})(),
|
})(),
|
||||||
path: "word/_rels/document.xml.rels",
|
path: "word/_rels/document.xml.rels",
|
||||||
},
|
},
|
||||||
@ -101,28 +113,58 @@ export class Compiler {
|
|||||||
path: "word/document.xml",
|
path: "word/document.xml",
|
||||||
},
|
},
|
||||||
Styles: {
|
Styles: {
|
||||||
data: xml(this.formatter.format(file.Styles, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.Styles, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "word/styles.xml",
|
path: "word/styles.xml",
|
||||||
},
|
},
|
||||||
Properties: {
|
Properties: {
|
||||||
data: xml(this.formatter.format(file.CoreProperties, file.Document), {
|
data: xml(
|
||||||
declaration: {
|
this.formatter.format(file.CoreProperties, {
|
||||||
standalone: "yes",
|
viewWrapper: file.Document,
|
||||||
encoding: "UTF-8",
|
file,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
),
|
||||||
path: "docProps/core.xml",
|
path: "docProps/core.xml",
|
||||||
},
|
},
|
||||||
Numbering: {
|
Numbering: {
|
||||||
data: xml(this.formatter.format(file.Numbering, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.Numbering, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "word/numbering.xml",
|
path: "word/numbering.xml",
|
||||||
},
|
},
|
||||||
FileRelationships: {
|
FileRelationships: {
|
||||||
data: xml(this.formatter.format(file.FileRelationships, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.FileRelationships, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "_rels/.rels",
|
path: "_rels/.rels",
|
||||||
},
|
},
|
||||||
HeaderRelationships: file.Headers.map((headerWrapper, index) => {
|
HeaderRelationships: file.Headers.map((headerWrapper, index) => {
|
||||||
const xmlData = xml(this.formatter.format(headerWrapper.View, headerWrapper), prettify);
|
const xmlData = xml(
|
||||||
|
this.formatter.format(headerWrapper.View, {
|
||||||
|
viewWrapper: headerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||||
|
|
||||||
mediaDatas.forEach((mediaData, i) => {
|
mediaDatas.forEach((mediaData, i) => {
|
||||||
@ -134,12 +176,24 @@ export class Compiler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: xml(this.formatter.format(headerWrapper.Relationships, headerWrapper), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(headerWrapper.Relationships, {
|
||||||
|
viewWrapper: headerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: `word/_rels/header${index + 1}.xml.rels`,
|
path: `word/_rels/header${index + 1}.xml.rels`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
FooterRelationships: file.Footers.map((footerWrapper, index) => {
|
FooterRelationships: file.Footers.map((footerWrapper, index) => {
|
||||||
const xmlData = xml(this.formatter.format(footerWrapper.View, footerWrapper), prettify);
|
const xmlData = xml(
|
||||||
|
this.formatter.format(footerWrapper.View, {
|
||||||
|
viewWrapper: footerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||||
|
|
||||||
mediaDatas.forEach((mediaData, i) => {
|
mediaDatas.forEach((mediaData, i) => {
|
||||||
@ -151,12 +205,24 @@ export class Compiler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: xml(this.formatter.format(footerWrapper.Relationships, footerWrapper), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(footerWrapper.Relationships, {
|
||||||
|
viewWrapper: footerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: `word/_rels/footer${index + 1}.xml.rels`,
|
path: `word/_rels/footer${index + 1}.xml.rels`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
Headers: file.Headers.map((headerWrapper, index) => {
|
Headers: file.Headers.map((headerWrapper, index) => {
|
||||||
const tempXmlData = xml(this.formatter.format(headerWrapper.View, headerWrapper), prettify);
|
const tempXmlData = xml(
|
||||||
|
this.formatter.format(headerWrapper.View, {
|
||||||
|
viewWrapper: headerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
||||||
@ -167,7 +233,13 @@ export class Compiler {
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
Footers: file.Footers.map((footerWrapper, index) => {
|
Footers: file.Footers.map((footerWrapper, index) => {
|
||||||
const tempXmlData = xml(this.formatter.format(footerWrapper.View, footerWrapper), prettify);
|
const tempXmlData = xml(
|
||||||
|
this.formatter.format(footerWrapper.View, {
|
||||||
|
viewWrapper: footerWrapper,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
|
||||||
@ -178,27 +250,63 @@ export class Compiler {
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
ContentTypes: {
|
ContentTypes: {
|
||||||
data: xml(this.formatter.format(file.ContentTypes, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.ContentTypes, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "[Content_Types].xml",
|
path: "[Content_Types].xml",
|
||||||
},
|
},
|
||||||
CustomProperties: {
|
CustomProperties: {
|
||||||
data: xml(this.formatter.format(file.CustomProperties, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.CustomProperties, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "docProps/custom.xml",
|
path: "docProps/custom.xml",
|
||||||
},
|
},
|
||||||
AppProperties: {
|
AppProperties: {
|
||||||
data: xml(this.formatter.format(file.AppProperties, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.AppProperties, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "docProps/app.xml",
|
path: "docProps/app.xml",
|
||||||
},
|
},
|
||||||
FootNotes: {
|
FootNotes: {
|
||||||
data: xml(this.formatter.format(file.FootNotes.View, file.FootNotes), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.FootNotes.View, {
|
||||||
|
viewWrapper: file.FootNotes,
|
||||||
|
file: file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "word/footnotes.xml",
|
path: "word/footnotes.xml",
|
||||||
},
|
},
|
||||||
FootNotesRelationships: {
|
FootNotesRelationships: {
|
||||||
data: xml(this.formatter.format(file.FootNotes.Relationships, file.FootNotes), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.FootNotes.Relationships, {
|
||||||
|
viewWrapper: file.FootNotes,
|
||||||
|
file: file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "word/_rels/footnotes.xml.rels",
|
path: "word/_rels/footnotes.xml.rels",
|
||||||
},
|
},
|
||||||
Settings: {
|
Settings: {
|
||||||
data: xml(this.formatter.format(file.Settings, file.Document), prettify),
|
data: xml(
|
||||||
|
this.formatter.format(file.Settings, {
|
||||||
|
viewWrapper: file.Document,
|
||||||
|
file,
|
||||||
|
}),
|
||||||
|
prettify,
|
||||||
|
),
|
||||||
path: "word/settings.xml",
|
path: "word/settings.xml",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
import { CustomPropertiesAttributes } from "./custom-properties-attributes";
|
import { CustomPropertiesAttributes } from "./custom-properties-attributes";
|
||||||
import { CustomProperty, ICustomPropertyOptions } from "./custom-property";
|
import { CustomProperty, ICustomPropertyOptions } from "./custom-property";
|
||||||
|
|
||||||
@ -26,9 +26,9 @@ export class CustomProperties extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
this.properties.forEach((x) => this.root.push(x));
|
this.properties.forEach((x) => this.root.push(x));
|
||||||
return super.prepForXml();
|
return super.prepForXml(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addCustomProperty(property: ICustomPropertyOptions): void {
|
public addCustomProperty(property: ICustomPropertyOptions): void {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { IViewWrapper } from "file/document-wrapper";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
|
import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
|
||||||
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
|
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
|
||||||
@ -26,13 +25,13 @@ export class Body extends XmlComponent {
|
|||||||
this.sections.push(new SectionProperties(options));
|
this.sections.push(new SectionProperties(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(file?: IViewWrapper): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
if (this.sections.length === 1) {
|
if (this.sections.length === 1) {
|
||||||
this.root.splice(0, 1);
|
this.root.splice(0, 1);
|
||||||
this.root.push(this.sections.pop() as SectionProperties);
|
this.root.push(this.sections.pop() as SectionProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.prepForXml(file);
|
return super.prepForXml(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public push(component: XmlComponent): void {
|
public push(component: XmlComponent): void {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// http://officeopenxml.com/WPnumbering.php
|
// http://officeopenxml.com/WPnumbering.php
|
||||||
import { convertInchesToTwip } from "convenience-functions";
|
import { convertInchesToTwip } from "convenience-functions";
|
||||||
import { AlignmentType } from "file/paragraph";
|
import { AlignmentType } from "file/paragraph";
|
||||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { DocumentAttributes } from "../document/document-attributes";
|
import { DocumentAttributes } from "../document/document-attributes";
|
||||||
import { AbstractNumbering } from "./abstract-numbering";
|
import { AbstractNumbering } from "./abstract-numbering";
|
||||||
@ -158,10 +158,10 @@ export class Numbering extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
this.abstractNumbering.forEach((x) => this.root.push(x));
|
this.abstractNumbering.forEach((x) => this.root.push(x));
|
||||||
this.concreteNumbering.forEach((x) => this.root.push(x));
|
this.concreteNumbering.forEach((x) => this.root.push(x));
|
||||||
return super.prepForXml();
|
return super.prepForXml(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createConcreteNumbering(abstractNumbering: AbstractNumbering, reference?: string): ConcreteNumbering {
|
private createConcreteNumbering(abstractNumbering: AbstractNumbering, reference?: string): ConcreteNumbering {
|
||||||
|
@ -6,6 +6,7 @@ import { Formatter } from "export/formatter";
|
|||||||
import { EMPTY_OBJECT } from "file/xml-components";
|
import { EMPTY_OBJECT } from "file/xml-components";
|
||||||
|
|
||||||
import { IViewWrapper } from "../document-wrapper";
|
import { IViewWrapper } from "../document-wrapper";
|
||||||
|
import { File } from "../file";
|
||||||
import { ShadingType } from "../table/shading";
|
import { ShadingType } from "../table/shading";
|
||||||
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
|
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
|
||||||
import { Bookmark, ExternalHyperlink } from "./links";
|
import { Bookmark, ExternalHyperlink } from "./links";
|
||||||
@ -830,12 +831,17 @@ describe("Paragraph", () => {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const fileMock = ({
|
const viewWrapperMock = ({
|
||||||
Relationships: {
|
Relationships: {
|
||||||
createRelationship: () => ({}),
|
createRelationship: () => ({}),
|
||||||
},
|
},
|
||||||
} as unknown) as IViewWrapper;
|
} as unknown) as IViewWrapper;
|
||||||
paragraph.prepForXml(fileMock);
|
|
||||||
|
const file = ({} as unknown) as File;
|
||||||
|
paragraph.prepForXml({
|
||||||
|
viewWrapper: viewWrapperMock,
|
||||||
|
file: file,
|
||||||
|
});
|
||||||
const tree = new Formatter().format(paragraph);
|
const tree = new Formatter().format(paragraph);
|
||||||
expect(tree).to.deep.equal({
|
expect(tree).to.deep.equal({
|
||||||
"w:p": [
|
"w:p": [
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
import * as shortid from "shortid";
|
import * as shortid from "shortid";
|
||||||
|
|
||||||
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
||||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { IViewWrapper } from "../document-wrapper";
|
|
||||||
import { TargetModeType } from "../relationships/relationship/relationship";
|
import { TargetModeType } from "../relationships/relationship/relationship";
|
||||||
import { DeletedTextRun, InsertedTextRun } from "../track-revision";
|
import { DeletedTextRun, InsertedTextRun } from "../track-revision";
|
||||||
import { PageBreak } from "./formatting/page-break";
|
import { PageBreak } from "./formatting/page-break";
|
||||||
@ -76,12 +75,12 @@ export class Paragraph extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(file: IViewWrapper): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
for (const element of this.root) {
|
for (const element of this.root) {
|
||||||
if (element instanceof ExternalHyperlink) {
|
if (element instanceof ExternalHyperlink) {
|
||||||
const index = this.root.indexOf(element);
|
const index = this.root.indexOf(element);
|
||||||
const concreteHyperlink = new ConcreteHyperlink(element.options.child, shortid.generate().toLowerCase());
|
const concreteHyperlink = new ConcreteHyperlink(element.options.child, shortid.generate().toLowerCase());
|
||||||
file.Relationships.createRelationship(
|
context.viewWrapper.Relationships.createRelationship(
|
||||||
concreteHyperlink.linkId,
|
concreteHyperlink.linkId,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
||||||
element.options.link,
|
element.options.link,
|
||||||
@ -91,7 +90,7 @@ export class Paragraph extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.prepForXml();
|
return super.prepForXml(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addRunToFront(run: Run): Paragraph {
|
public addRunToFront(run: Run): Paragraph {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// http://officeopenxml.com/WPtableGrid.php
|
// http://officeopenxml.com/WPtableGrid.php
|
||||||
import { IViewWrapper } from "file/document-wrapper";
|
|
||||||
import { Paragraph } from "file/paragraph";
|
import { Paragraph } from "file/paragraph";
|
||||||
import { BorderStyle } from "file/styles";
|
import { BorderStyle } from "file/styles";
|
||||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { ITableShadingAttributesProperties } from "../shading";
|
import { ITableShadingAttributesProperties } from "../shading";
|
||||||
import { Table } from "../table";
|
import { Table } from "../table";
|
||||||
@ -105,11 +104,11 @@ export class TableCell extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(file?: IViewWrapper): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
// Cells must end with a paragraph
|
// Cells must end with a paragraph
|
||||||
if (!(this.root[this.root.length - 1] instanceof Paragraph)) {
|
if (!(this.root[this.root.length - 1] instanceof Paragraph)) {
|
||||||
this.root.push(new Paragraph({}));
|
this.root.push(new Paragraph({}));
|
||||||
}
|
}
|
||||||
return super.prepForXml(file);
|
return super.prepForXml(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import { IViewWrapper } from "../document-wrapper";
|
import { IViewWrapper } from "../document-wrapper";
|
||||||
|
import { File } from "../file";
|
||||||
import { IXmlableObject } from "./xmlable-object";
|
import { IXmlableObject } from "./xmlable-object";
|
||||||
|
|
||||||
|
export interface IContext {
|
||||||
|
readonly file: File;
|
||||||
|
readonly viewWrapper: IViewWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class BaseXmlComponent {
|
export abstract class BaseXmlComponent {
|
||||||
protected readonly rootKey: string;
|
protected readonly rootKey: string;
|
||||||
// tslint:disable-next-line:readonly-keyword
|
// tslint:disable-next-line:readonly-keyword
|
||||||
@ -10,7 +16,7 @@ export abstract class BaseXmlComponent {
|
|||||||
this.rootKey = rootKey;
|
this.rootKey = rootKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract prepForXml(file?: IViewWrapper): IXmlableObject | undefined;
|
public abstract prepForXml(context: IContext): IXmlableObject | undefined;
|
||||||
|
|
||||||
public get IsDeleted(): boolean {
|
public get IsDeleted(): boolean {
|
||||||
return this.deleted;
|
return this.deleted;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { BaseXmlComponent } from "./base";
|
import { BaseXmlComponent, IContext } from "./base";
|
||||||
import { IXmlableObject } from "./xmlable-object";
|
import { IXmlableObject } from "./xmlable-object";
|
||||||
|
|
||||||
export type AttributeMap<T> = { [P in keyof T]: string };
|
export type AttributeMap<T> = { [P in keyof T]: string };
|
||||||
@ -13,7 +13,7 @@ export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
|
|||||||
this.root = properties;
|
this.root = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject {
|
public prepForXml(_: IContext): IXmlableObject {
|
||||||
const attrs = {};
|
const attrs = {};
|
||||||
Object.keys(this.root).forEach((key) => {
|
Object.keys(this.root).forEach((key) => {
|
||||||
const value = this.root[key];
|
const value = this.root[key];
|
||||||
|
@ -2,6 +2,7 @@ import { expect } from "chai";
|
|||||||
import { Element, xml2js } from "xml-js";
|
import { Element, xml2js } from "xml-js";
|
||||||
|
|
||||||
import { EMPTY_OBJECT, ImportedXmlComponent } from "./";
|
import { EMPTY_OBJECT, ImportedXmlComponent } from "./";
|
||||||
|
import { IContext } from "./base";
|
||||||
import { convertToXmlComponent } from "./imported-xml-component";
|
import { convertToXmlComponent } from "./imported-xml-component";
|
||||||
|
|
||||||
const xmlString = `
|
const xmlString = `
|
||||||
@ -63,7 +64,8 @@ describe("ImportedXmlComponent", () => {
|
|||||||
|
|
||||||
describe("#prepForXml()", () => {
|
describe("#prepForXml()", () => {
|
||||||
it("should transform for xml", () => {
|
it("should transform for xml", () => {
|
||||||
const converted = importedXmlComponent.prepForXml();
|
// tslint:disable-next-line: no-object-literal-type-assertion
|
||||||
|
const converted = importedXmlComponent.prepForXml({} as IContext);
|
||||||
expect(converted).to.deep.equal({
|
expect(converted).to.deep.equal({
|
||||||
"w:test": [
|
"w:test": [
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// tslint:disable:no-any
|
// tslint:disable:no-any
|
||||||
import { Element as XmlElement, xml2js } from "xml-js";
|
import { Element as XmlElement, xml2js } from "xml-js";
|
||||||
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from ".";
|
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from ".";
|
||||||
|
import { IContext } from "./base";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given xml element (in json format) into XmlComponent.
|
* Converts the given xml element (in json format) into XmlComponent.
|
||||||
@ -72,7 +73,7 @@ export class ImportedRootElementAttributes extends XmlComponent {
|
|||||||
super("");
|
super("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject {
|
public prepForXml(_: IContext): IXmlableObject {
|
||||||
return {
|
return {
|
||||||
_attr: this._attr,
|
_attr: this._attr,
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import { expect } from "chai";
|
|||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
import { EMPTY_OBJECT, XmlComponent } from "./";
|
import { EMPTY_OBJECT, XmlComponent } from "./";
|
||||||
|
import { IContext } from "./base";
|
||||||
|
|
||||||
class TestComponent extends XmlComponent {}
|
class TestComponent extends XmlComponent {}
|
||||||
|
|
||||||
@ -27,7 +28,8 @@ describe("XmlComponent", () => {
|
|||||||
child.delete();
|
child.delete();
|
||||||
xmlComponent.addChildElement(child);
|
xmlComponent.addChildElement(child);
|
||||||
|
|
||||||
const xml = xmlComponent.prepForXml();
|
// tslint:disable-next-line: no-object-literal-type-assertion
|
||||||
|
const xml = xmlComponent.prepForXml({} as IContext);
|
||||||
|
|
||||||
if (!xml) {
|
if (!xml) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { IViewWrapper } from "../document-wrapper";
|
import { BaseXmlComponent, IContext } from "./base";
|
||||||
import { BaseXmlComponent } from "./base";
|
|
||||||
import { IXmlableObject } from "./xmlable-object";
|
import { IXmlableObject } from "./xmlable-object";
|
||||||
|
|
||||||
export const EMPTY_OBJECT = Object.seal({});
|
export const EMPTY_OBJECT = Object.seal({});
|
||||||
@ -13,7 +12,7 @@ export abstract class XmlComponent extends BaseXmlComponent {
|
|||||||
this.root = new Array<BaseXmlComponent | string>();
|
this.root = new Array<BaseXmlComponent | string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(file?: IViewWrapper): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
const children = this.root
|
const children = this.root
|
||||||
.filter((c) => {
|
.filter((c) => {
|
||||||
if (c instanceof BaseXmlComponent) {
|
if (c instanceof BaseXmlComponent) {
|
||||||
@ -23,7 +22,7 @@ export abstract class XmlComponent extends BaseXmlComponent {
|
|||||||
})
|
})
|
||||||
.map((comp) => {
|
.map((comp) => {
|
||||||
if (comp instanceof BaseXmlComponent) {
|
if (comp instanceof BaseXmlComponent) {
|
||||||
return comp.prepForXml(file);
|
return comp.prepForXml(context);
|
||||||
}
|
}
|
||||||
return comp;
|
return comp;
|
||||||
})
|
})
|
||||||
@ -52,8 +51,8 @@ export abstract class XmlComponent extends BaseXmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class IgnoreIfEmptyXmlComponent extends XmlComponent {
|
export abstract class IgnoreIfEmptyXmlComponent extends XmlComponent {
|
||||||
public prepForXml(): IXmlableObject | undefined {
|
public prepForXml(context: IContext): IXmlableObject | undefined {
|
||||||
const result = super.prepForXml();
|
const result = super.prepForXml(context);
|
||||||
// Ignore the object if its falsey or is an empty object (would produce
|
// Ignore the object if its falsey or is an empty object (would produce
|
||||||
// an empty XML element if allowed to be included in the output).
|
// an empty XML element if allowed to be included in the output).
|
||||||
if (result && (typeof result[this.rootKey] !== "object" || Object.keys(result[this.rootKey]).length)) {
|
if (result && (typeof result[this.rootKey] !== "object" || Object.keys(result[this.rootKey]).length)) {
|
||||||
|
Reference in New Issue
Block a user