import: add support to import any xml tab element to XmlComponent (#8)
- make method to import/convert to XmlComponent - expose method to add childElement to Header/Footer - add tests
This commit is contained in:
@ -3,6 +3,7 @@ import { IMediaData, Media } from "./media";
|
|||||||
import { Paragraph } from "./paragraph";
|
import { Paragraph } from "./paragraph";
|
||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
import { Table } from "./table";
|
import { Table } from "./table";
|
||||||
|
import { XmlComponent } from ".";
|
||||||
|
|
||||||
export class FooterWrapper {
|
export class FooterWrapper {
|
||||||
private readonly footer: Footer;
|
private readonly footer: Footer;
|
||||||
@ -35,6 +36,10 @@ export class FooterWrapper {
|
|||||||
this.footer.addDrawing(imageData);
|
this.footer.addDrawing(imageData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addChildElement(childElement: XmlComponent | string) {
|
||||||
|
this.footer.addChildElement(childElement);
|
||||||
|
}
|
||||||
|
|
||||||
public createImage(image: string): void {
|
public createImage(image: string): void {
|
||||||
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount);
|
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount);
|
||||||
this.relationships.createRelationship(
|
this.relationships.createRelationship(
|
||||||
|
@ -3,6 +3,7 @@ import { IMediaData, Media } from "./media";
|
|||||||
import { Paragraph } from "./paragraph";
|
import { Paragraph } from "./paragraph";
|
||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
import { Table } from "./table";
|
import { Table } from "./table";
|
||||||
|
import { XmlComponent } from ".";
|
||||||
|
|
||||||
export class HeaderWrapper {
|
export class HeaderWrapper {
|
||||||
private readonly header: Header;
|
private readonly header: Header;
|
||||||
@ -35,6 +36,10 @@ export class HeaderWrapper {
|
|||||||
this.header.addDrawing(imageData);
|
this.header.addDrawing(imageData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addChildElement(childElement: XmlComponent | string) {
|
||||||
|
this.header.addChildElement(childElement);
|
||||||
|
}
|
||||||
|
|
||||||
public createImage(image: string): void {
|
public createImage(image: string): void {
|
||||||
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount);
|
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount);
|
||||||
this.relationships.createRelationship(
|
this.relationships.createRelationship(
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import { Styles } from "./";
|
import { Styles } from "./";
|
||||||
import * as fastXmlParser from "fast-xml-parser";
|
import * as fastXmlParser from "fast-xml-parser";
|
||||||
import { ImportedXmlComponent, ImportedRootElementAttributes } from "./../../file/xml-components";
|
import { ImportedXmlComponent, ImportedRootElementAttributes, parseOptions, convertToXmlComponent } from "./../../file/xml-components";
|
||||||
|
|
||||||
const parseOptions = {
|
|
||||||
ignoreAttributes: false,
|
|
||||||
attributeNamePrefix: "",
|
|
||||||
attrNodeName: "_attr",
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ExternalStylesFactory {
|
export class ExternalStylesFactory {
|
||||||
/**
|
/**
|
||||||
@ -44,19 +38,7 @@ export class ExternalStylesFactory {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// convert the styles one by one
|
// convert the styles one by one
|
||||||
xmlStyles["w:style"].map((style) => this.convertElement("w:style", style)).forEach(importedStyle.push.bind(importedStyle));
|
xmlStyles["w:style"].map((style) => convertToXmlComponent("w:style", style)).forEach(importedStyle.push.bind(importedStyle));
|
||||||
|
|
||||||
return importedStyle;
|
return importedStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
convertElement(elementName: string, element: any): ImportedXmlComponent {
|
|
||||||
const xmlElement = new ImportedXmlComponent(elementName, element._attr);
|
|
||||||
if (typeof element === "object") {
|
|
||||||
Object.keys(element)
|
|
||||||
.filter((key) => key !== "_attr")
|
|
||||||
.map((item) => this.convertElement(item, element[item]))
|
|
||||||
.forEach(xmlElement.push.bind(xmlElement));
|
|
||||||
}
|
|
||||||
return xmlElement;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,52 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { ImportedXmlComponent } from "./";
|
import { ImportedXmlComponent, convertToXmlComponent } from "./";
|
||||||
|
|
||||||
|
const xmlString = `
|
||||||
|
<w:p w:one="value 1" w:two="value 2">
|
||||||
|
<w:rPr>
|
||||||
|
<w:noProof>some value</w:noProof>
|
||||||
|
</w:rPr>
|
||||||
|
<w:r active="true">
|
||||||
|
<w:t>Text 1</w:t>
|
||||||
|
</w:r>
|
||||||
|
<w:r active="true">
|
||||||
|
<w:t>Text 2</w:t>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const importedXmlElement = {
|
||||||
|
"w:p": {
|
||||||
|
_attr: { "w:one": "value 1", "w:two": "value 2" },
|
||||||
|
"w:rPr": { "w:noProof": "some value" },
|
||||||
|
"w:r": [{ _attr: { active: "true" }, "w:t": "Text 1" }, { _attr: { active: "true" }, "w:t": "Text 2" }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertedXmlElement = {
|
||||||
|
deleted: false,
|
||||||
|
rootKey: "w:p",
|
||||||
|
root: [
|
||||||
|
{
|
||||||
|
deleted: false,
|
||||||
|
rootKey: "w:rPr",
|
||||||
|
root: [{ deleted: false, rootKey: "w:noProof", root: ["some value"] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deleted: false,
|
||||||
|
rootKey: "w:r",
|
||||||
|
root: [{ deleted: false, rootKey: "w:t", root: ["Text 1"] }],
|
||||||
|
_attr: { active: "true" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deleted: false,
|
||||||
|
rootKey: "w:r",
|
||||||
|
root: [{ deleted: false, rootKey: "w:t", root: ["Text 2"] }],
|
||||||
|
_attr: { active: "true" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
_attr: { "w:one": "value 1", "w:two": "value 2" },
|
||||||
|
};
|
||||||
|
|
||||||
describe("ImportedXmlComponent", () => {
|
describe("ImportedXmlComponent", () => {
|
||||||
let importedXmlComponent: ImportedXmlComponent;
|
let importedXmlComponent: ImportedXmlComponent;
|
||||||
@ -31,4 +78,16 @@ describe("ImportedXmlComponent", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create XmlComponent from xml string", () => {
|
||||||
|
const converted = ImportedXmlComponent.fromXmlString(xmlString);
|
||||||
|
expect(converted).to.eql(convertedXmlElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("convertToXmlComponent", () => {
|
||||||
|
it("should convert to xml component", () => {
|
||||||
|
const converted = convertToXmlComponent("w:p", importedXmlElement["w:p"]);
|
||||||
|
expect(converted).to.eql(convertedXmlElement);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,53 @@
|
|||||||
import { XmlComponent, IXmlableObject } from ".";
|
import { XmlComponent, IXmlableObject } from ".";
|
||||||
|
import * as fastXmlParser from "fast-xml-parser";
|
||||||
|
import { flatMap } from "lodash";
|
||||||
|
|
||||||
|
export const parseOptions = {
|
||||||
|
ignoreAttributes: false,
|
||||||
|
attributeNamePrefix: "",
|
||||||
|
attrNodeName: "_attr",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given xml element (in json format) into XmlComponent.
|
||||||
|
* Note: If element is array, them it will return ImportedXmlComponent[]. Example for given:
|
||||||
|
* element = [
|
||||||
|
* { w:t: "val 1"},
|
||||||
|
* { w:t: "val 2"}
|
||||||
|
* ]
|
||||||
|
* will return
|
||||||
|
* [
|
||||||
|
* ImportedXmlComponent { rootKey: "w:t", root: [ "val 1" ]},
|
||||||
|
* ImportedXmlComponent { rootKey: "w:t", root: [ "val 2" ]}
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* @param elementName name (rootKey) of the XmlComponent
|
||||||
|
* @param element the xml element in json presentation
|
||||||
|
*/
|
||||||
|
export function convertToXmlComponent(elementName: string, element: any): ImportedXmlComponent | ImportedXmlComponent[] {
|
||||||
|
const xmlElement = new ImportedXmlComponent(elementName, element._attr);
|
||||||
|
if (Array.isArray(element)) {
|
||||||
|
const out: any[] = [];
|
||||||
|
element.forEach((itemInArray) => {
|
||||||
|
out.push(convertToXmlComponent(elementName, itemInArray));
|
||||||
|
});
|
||||||
|
return flatMap(out);
|
||||||
|
} else if (typeof element === "object") {
|
||||||
|
Object.keys(element)
|
||||||
|
.filter((key) => key !== "_attr")
|
||||||
|
.map((item) => convertToXmlComponent(item, element[item]))
|
||||||
|
.forEach((converted) => {
|
||||||
|
if (Array.isArray(converted)) {
|
||||||
|
converted.forEach(xmlElement.push.bind(xmlElement));
|
||||||
|
} else {
|
||||||
|
xmlElement.push(converted);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (element !== "") {
|
||||||
|
xmlElement.push(element);
|
||||||
|
}
|
||||||
|
return xmlElement;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents imported xml component from xml file.
|
* Represents imported xml component from xml file.
|
||||||
@ -53,6 +102,23 @@ export class ImportedXmlComponent extends XmlComponent {
|
|||||||
push(xmlComponent: XmlComponent) {
|
push(xmlComponent: XmlComponent) {
|
||||||
this.root.push(xmlComponent);
|
this.root.push(xmlComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the xml string to a XmlComponent tree.
|
||||||
|
*
|
||||||
|
* @param importedContent xml content of the imported component
|
||||||
|
*/
|
||||||
|
static fromXmlString(importedContent: string): ImportedXmlComponent {
|
||||||
|
const imported = fastXmlParser.parse(importedContent, parseOptions);
|
||||||
|
const elementName = Object.keys(imported)[0];
|
||||||
|
|
||||||
|
const converted = convertToXmlComponent(elementName, imported[elementName]);
|
||||||
|
|
||||||
|
if (Array.isArray(converted) && converted.length > 1) {
|
||||||
|
throw new Error("Invalid conversion, input must be one element.");
|
||||||
|
}
|
||||||
|
return Array.isArray(converted) ? converted[0] : converted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user