Merge branch 'master' into feat/math
# Conflicts: # src/file/paragraph/index.ts # src/file/paragraph/paragraph.ts
This commit is contained in:
@ -1,11 +1,87 @@
|
||||
import { assert, expect } from "chai";
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { ThematicBreak } from "./border";
|
||||
import { Border, ThematicBreak } from "./border";
|
||||
|
||||
describe("Border", () => {
|
||||
// TODO: Need tests here
|
||||
describe("#constructor", () => {
|
||||
it("should create", () => {
|
||||
const border = new Border({
|
||||
top: {
|
||||
color: "red",
|
||||
space: 1,
|
||||
value: "test",
|
||||
size: 2,
|
||||
},
|
||||
bottom: {
|
||||
color: "red",
|
||||
space: 3,
|
||||
value: "test",
|
||||
size: 4,
|
||||
},
|
||||
left: {
|
||||
color: "red",
|
||||
space: 5,
|
||||
value: "test",
|
||||
size: 6,
|
||||
},
|
||||
right: {
|
||||
color: "red",
|
||||
space: 7,
|
||||
value: "test",
|
||||
size: 8,
|
||||
},
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(border);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:pBdr": [
|
||||
{
|
||||
"w:top": {
|
||||
_attr: {
|
||||
"w:color": "red",
|
||||
"w:space": 1,
|
||||
"w:sz": 2,
|
||||
"w:val": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:bottom": {
|
||||
_attr: {
|
||||
"w:color": "red",
|
||||
"w:space": 3,
|
||||
"w:sz": 4,
|
||||
"w:val": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:left": {
|
||||
_attr: {
|
||||
"w:color": "red",
|
||||
"w:space": 5,
|
||||
"w:sz": 6,
|
||||
"w:val": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:right": {
|
||||
_attr: {
|
||||
"w:color": "red",
|
||||
"w:space": 7,
|
||||
"w:sz": 8,
|
||||
"w:val": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("ThematicBreak", () => {
|
||||
@ -16,17 +92,6 @@ describe("ThematicBreak", () => {
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
it("should create valid JSON", () => {
|
||||
const stringifiedJson = JSON.stringify(thematicBreak);
|
||||
|
||||
try {
|
||||
JSON.parse(stringifiedJson);
|
||||
} catch (e) {
|
||||
assert.isTrue(false);
|
||||
}
|
||||
assert.isTrue(true);
|
||||
});
|
||||
|
||||
it("should create a Thematic Break with correct border properties", () => {
|
||||
const tree = new Formatter().format(thematicBreak);
|
||||
expect(tree).to.deep.equal({
|
||||
|
@ -2,13 +2,13 @@ import { assert } from "chai";
|
||||
|
||||
import { Utility } from "tests/utility";
|
||||
|
||||
import { LeaderType, LeftTabStop, MaxRightTabStop, RightTabStop } from "./tab-stop";
|
||||
import { LeaderType, TabStop, TabStopType } from "./tab-stop";
|
||||
|
||||
describe("LeftTabStop", () => {
|
||||
let tabStop: LeftTabStop;
|
||||
let tabStop: TabStop;
|
||||
|
||||
beforeEach(() => {
|
||||
tabStop = new LeftTabStop(100);
|
||||
tabStop = new TabStop(TabStopType.LEFT, 100);
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
@ -29,10 +29,10 @@ describe("LeftTabStop", () => {
|
||||
});
|
||||
|
||||
describe("RightTabStop", () => {
|
||||
let tabStop: RightTabStop;
|
||||
let tabStop: TabStop;
|
||||
|
||||
beforeEach(() => {
|
||||
tabStop = new RightTabStop(100, LeaderType.DOT);
|
||||
tabStop = new TabStop(TabStopType.RIGHT, 100, LeaderType.DOT);
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
@ -52,28 +52,3 @@ describe("RightTabStop", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("MaxRightTabStop", () => {
|
||||
let tabStop: MaxRightTabStop;
|
||||
|
||||
beforeEach(() => {
|
||||
tabStop = new MaxRightTabStop();
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
it("should create a Tab Stop with correct attributes", () => {
|
||||
const newJson = Utility.jsonify(tabStop);
|
||||
|
||||
const attributes = {
|
||||
val: "right",
|
||||
pos: 9026,
|
||||
};
|
||||
assert.equal(JSON.stringify(newJson.root[0].root[0].root), JSON.stringify(attributes));
|
||||
});
|
||||
|
||||
it("should create a Tab Stop with w:tab", () => {
|
||||
const newJson = Utility.jsonify(tabStop);
|
||||
assert.equal(newJson.root[0].rootKey, "w:tab");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -2,13 +2,13 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export class TabStop extends XmlComponent {
|
||||
constructor(tab: TabStopItem) {
|
||||
constructor(type: TabStopType, position: number, leader?: LeaderType) {
|
||||
super("w:tabs");
|
||||
this.root.push(tab);
|
||||
this.root.push(new TabStopItem(type, position, leader));
|
||||
}
|
||||
}
|
||||
|
||||
export enum TabValue {
|
||||
export enum TabStopType {
|
||||
LEFT = "left",
|
||||
RIGHT = "right",
|
||||
CENTER = "center",
|
||||
@ -28,8 +28,12 @@ export enum LeaderType {
|
||||
UNDERSCORE = "underscore",
|
||||
}
|
||||
|
||||
export enum TabStopPosition {
|
||||
MAX = 9026,
|
||||
}
|
||||
|
||||
export class TabAttributes extends XmlAttributeComponent<{
|
||||
readonly val: TabValue;
|
||||
readonly val: TabStopType;
|
||||
readonly pos: string | number;
|
||||
readonly leader?: LeaderType;
|
||||
}> {
|
||||
@ -37,7 +41,7 @@ export class TabAttributes extends XmlAttributeComponent<{
|
||||
}
|
||||
|
||||
export class TabStopItem extends XmlComponent {
|
||||
constructor(value: TabValue, position: string | number, leader?: LeaderType) {
|
||||
constructor(value: TabStopType, position: string | number, leader?: LeaderType) {
|
||||
super("w:tab");
|
||||
this.root.push(
|
||||
new TabAttributes({
|
||||
@ -48,27 +52,3 @@ export class TabStopItem extends XmlComponent {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class MaxRightTabStop extends TabStop {
|
||||
constructor(leader?: LeaderType) {
|
||||
super(new TabStopItem(TabValue.RIGHT, 9026, leader));
|
||||
}
|
||||
}
|
||||
|
||||
export class LeftTabStop extends TabStop {
|
||||
constructor(position: number, leader?: LeaderType) {
|
||||
super(new TabStopItem(TabValue.LEFT, position, leader));
|
||||
}
|
||||
}
|
||||
|
||||
export class RightTabStop extends TabStop {
|
||||
constructor(position: number, leader?: LeaderType) {
|
||||
super(new TabStopItem(TabValue.RIGHT, position, leader));
|
||||
}
|
||||
}
|
||||
|
||||
export class CenterTabStop extends TabStop {
|
||||
constructor(position: number, leader?: LeaderType) {
|
||||
super(new TabStopItem(TabValue.CENTER, position, leader));
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
// tslint:disable:object-literal-key-quotes
|
||||
import { assert } from "chai";
|
||||
|
||||
import { ImageParagraph } from "./image";
|
||||
|
||||
describe("Image", () => {
|
||||
let image: ImageParagraph;
|
||||
|
||||
beforeEach(() => {
|
||||
image = new ImageParagraph({
|
||||
stream: new Buffer(""),
|
||||
path: "",
|
||||
fileName: "test.png",
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,18 +0,0 @@
|
||||
import { IDrawingOptions } from "../drawing";
|
||||
import { IMediaData } from "../media";
|
||||
import { Paragraph } from "./paragraph";
|
||||
import { PictureRun } from "./run";
|
||||
|
||||
export class ImageParagraph extends Paragraph {
|
||||
private readonly pictureRun: PictureRun;
|
||||
|
||||
constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) {
|
||||
super({});
|
||||
this.pictureRun = new PictureRun(imageData, drawingOptions);
|
||||
this.root.push(this.pictureRun);
|
||||
}
|
||||
|
||||
public get Run(): PictureRun {
|
||||
return this.pictureRun;
|
||||
}
|
||||
}
|
@ -3,5 +3,4 @@ export * from "./paragraph";
|
||||
export * from "./properties";
|
||||
export * from "./run";
|
||||
export * from "./links";
|
||||
export * from "./image";
|
||||
export * from "./math";
|
||||
|
@ -4,7 +4,7 @@ import { Formatter } from "export/formatter";
|
||||
import { EMPTY_OBJECT } from "file/xml-components";
|
||||
|
||||
import { Numbering } from "../numbering";
|
||||
import { AlignmentType, HeadingLevel, LeaderType } from "./formatting";
|
||||
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
|
||||
import { Paragraph } from "./paragraph";
|
||||
|
||||
describe("Paragraph", () => {
|
||||
@ -254,11 +254,14 @@ describe("Paragraph", () => {
|
||||
});
|
||||
|
||||
describe("#maxRightTabStop()", () => {
|
||||
it("should add maxRightTabStop to JSON", () => {
|
||||
it("should add right tab stop to JSON", () => {
|
||||
const paragraph = new Paragraph({
|
||||
tabStop: {
|
||||
maxRight: {},
|
||||
},
|
||||
tabStops: [
|
||||
{
|
||||
type: TabStopType.RIGHT,
|
||||
position: TabStopPosition.MAX,
|
||||
},
|
||||
],
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
@ -287,12 +290,13 @@ describe("Paragraph", () => {
|
||||
describe("#leftTabStop()", () => {
|
||||
it("should add leftTabStop to JSON", () => {
|
||||
const paragraph = new Paragraph({
|
||||
tabStop: {
|
||||
left: {
|
||||
tabStops: [
|
||||
{
|
||||
type: TabStopType.LEFT,
|
||||
position: 100,
|
||||
leader: LeaderType.HYPHEN,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
@ -322,12 +326,13 @@ describe("Paragraph", () => {
|
||||
describe("#rightTabStop()", () => {
|
||||
it("should add rightTabStop to JSON", () => {
|
||||
const paragraph = new Paragraph({
|
||||
tabStop: {
|
||||
right: {
|
||||
tabStops: [
|
||||
{
|
||||
type: TabStopType.RIGHT,
|
||||
position: 100,
|
||||
leader: LeaderType.DOT,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
@ -357,12 +362,13 @@ describe("Paragraph", () => {
|
||||
describe("#centerTabStop()", () => {
|
||||
it("should add centerTabStop to JSON", () => {
|
||||
const paragraph = new Paragraph({
|
||||
tabStop: {
|
||||
center: {
|
||||
tabStops: [
|
||||
{
|
||||
type: TabStopType.CENTER,
|
||||
position: 100,
|
||||
leader: LeaderType.MIDDLE_DOT,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
@ -492,8 +498,9 @@ describe("Paragraph", () => {
|
||||
|
||||
describe("#pageBreak()", () => {
|
||||
it("should add page break to JSON", () => {
|
||||
const paragraph = new Paragraph({});
|
||||
paragraph.pageBreak();
|
||||
const paragraph = new Paragraph({
|
||||
children: [new PageBreak()],
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:p": [
|
||||
|
@ -1,6 +1,5 @@
|
||||
// http://officeopenxml.com/WPparagraph.php
|
||||
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
||||
import { Image } from "file/media";
|
||||
import { Num } from "file/numbering/num";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
@ -12,17 +11,12 @@ import { KeepLines, KeepNext } from "./formatting/keep";
|
||||
import { PageBreak, PageBreakBefore } from "./formatting/page-break";
|
||||
import { ContextualSpacing, ISpacingProperties, Spacing } from "./formatting/spacing";
|
||||
import { HeadingLevel, Style } from "./formatting/style";
|
||||
import { CenterTabStop, LeaderType, LeftTabStop, MaxRightTabStop, RightTabStop } from "./formatting/tab-stop";
|
||||
import { LeaderType, TabStop, TabStopPosition, TabStopType } from "./formatting/tab-stop";
|
||||
import { NumberProperties } from "./formatting/unordered-list";
|
||||
import { Bookmark, Hyperlink, OutlineLevel } from "./links";
|
||||
import { Math } from "./math";
|
||||
import { ParagraphProperties } from "./properties";
|
||||
import { PictureRun, Run, SequentialIdentifier, TextRun } from "./run";
|
||||
|
||||
interface ITabStopOptions {
|
||||
readonly position: number;
|
||||
readonly leader?: LeaderType;
|
||||
}
|
||||
import { PictureRun, Run, SequentialIdentifier, SymbolRun, TextRun } from "./run";
|
||||
|
||||
export interface IParagraphOptions {
|
||||
readonly text?: string;
|
||||
@ -38,14 +32,11 @@ export interface IParagraphOptions {
|
||||
readonly indent?: IIndentAttributesProperties;
|
||||
readonly keepLines?: boolean;
|
||||
readonly keepNext?: boolean;
|
||||
readonly tabStop?: {
|
||||
readonly left?: ITabStopOptions;
|
||||
readonly right?: ITabStopOptions;
|
||||
readonly maxRight?: {
|
||||
readonly leader?: LeaderType;
|
||||
};
|
||||
readonly center?: ITabStopOptions;
|
||||
};
|
||||
readonly tabStops?: Array<{
|
||||
readonly position: number | TabStopPosition;
|
||||
readonly type: TabStopType;
|
||||
readonly leader?: LeaderType;
|
||||
}>;
|
||||
readonly style?: string;
|
||||
readonly bullet?: {
|
||||
readonly level: number;
|
||||
@ -55,7 +46,7 @@ export interface IParagraphOptions {
|
||||
readonly level: number;
|
||||
readonly custom?: boolean;
|
||||
};
|
||||
readonly children?: Array<TextRun | PictureRun | Hyperlink | Math>;
|
||||
readonly children?: Array<TextRun | PictureRun | Hyperlink | SymbolRun | Bookmark | PageBreak | SequentialIdentifier | Math>;
|
||||
}
|
||||
|
||||
export class Paragraph extends XmlComponent {
|
||||
@ -132,21 +123,9 @@ export class Paragraph extends XmlComponent {
|
||||
this.properties.push(new KeepNext());
|
||||
}
|
||||
|
||||
if (options.tabStop) {
|
||||
if (options.tabStop.left) {
|
||||
this.properties.push(new LeftTabStop(options.tabStop.left.position, options.tabStop.left.leader));
|
||||
}
|
||||
|
||||
if (options.tabStop.right) {
|
||||
this.properties.push(new RightTabStop(options.tabStop.right.position, options.tabStop.right.leader));
|
||||
}
|
||||
|
||||
if (options.tabStop.maxRight) {
|
||||
this.properties.push(new MaxRightTabStop(options.tabStop.maxRight.leader));
|
||||
}
|
||||
|
||||
if (options.tabStop.center) {
|
||||
this.properties.push(new CenterTabStop(options.tabStop.center.position, options.tabStop.center.leader));
|
||||
if (options.tabStops) {
|
||||
for (const tabStop of options.tabStops) {
|
||||
this.properties.push(new TabStop(tabStop.type, tabStop.position, tabStop.leader));
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,41 +147,18 @@ export class Paragraph extends XmlComponent {
|
||||
|
||||
if (options.children) {
|
||||
for (const child of options.children) {
|
||||
if (child instanceof Bookmark) {
|
||||
this.root.push(child.start);
|
||||
this.root.push(child.text);
|
||||
this.root.push(child.end);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.root.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public addRun(run: Run): Paragraph {
|
||||
this.root.push(run);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addHyperLink(hyperlink: Hyperlink): Paragraph {
|
||||
this.root.push(hyperlink);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addBookmark(bookmark: Bookmark): Paragraph {
|
||||
// Bookmarks by spec have three components, a start, text, and end
|
||||
this.root.push(bookmark.start);
|
||||
this.root.push(bookmark.text);
|
||||
this.root.push(bookmark.end);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addImage(image: Image): PictureRun {
|
||||
const run = image.Run;
|
||||
this.addRun(run);
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
public pageBreak(): Paragraph {
|
||||
this.root.push(new PageBreak());
|
||||
return this;
|
||||
}
|
||||
|
||||
public referenceFootnote(id: number): Paragraph {
|
||||
this.root.push(new FootnoteReferenceRun(id));
|
||||
return this;
|
||||
@ -212,9 +168,4 @@ export class Paragraph extends XmlComponent {
|
||||
this.root.splice(1, 0, run);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addSequentialIdentifier(identifier: string): Paragraph {
|
||||
this.root.push(new SequentialIdentifier(identifier));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
export * from "./run";
|
||||
export * from "./text-run";
|
||||
export * from "./symbol-run";
|
||||
export * from "./picture-run";
|
||||
export * from "./run-fonts";
|
||||
export * from "./sequential-identifier";
|
||||
export * from "./underline";
|
||||
|
@ -2,7 +2,7 @@ import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { NumberOfPages, Page } from "./page-number";
|
||||
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
||||
|
||||
describe("Page", () => {
|
||||
describe("#constructor()", () => {
|
||||
@ -21,3 +21,12 @@ describe("NumberOfPages", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("NumberOfPagesSection", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("uses the font name for both ascii and hAnsi", () => {
|
||||
const tree = new Formatter().format(new NumberOfPagesSection());
|
||||
expect(tree).to.deep.equal({ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTIONPAGES"] });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -20,3 +20,11 @@ export class NumberOfPages extends XmlComponent {
|
||||
this.root.push("NUMPAGES");
|
||||
}
|
||||
}
|
||||
|
||||
export class NumberOfPagesSection extends XmlComponent {
|
||||
constructor() {
|
||||
super("w:instrText");
|
||||
this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
|
||||
this.root.push("SECTIONPAGES");
|
||||
}
|
||||
}
|
||||
|
28
src/file/paragraph/run/run-components/symbol.spec.ts
Normal file
28
src/file/paragraph/run/run-components/symbol.spec.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { Symbol } from "./symbol";
|
||||
|
||||
describe("Symbol", () => {
|
||||
describe("#constructor", () => {
|
||||
// Note: if no character is given, the output is a MS Windows logo
|
||||
it("creates an empty symbol run if no character is given", () => {
|
||||
const s = new Symbol();
|
||||
const f = new Formatter().format(s);
|
||||
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "", "w:font": "Wingdings" } } });
|
||||
});
|
||||
|
||||
it("creates the provided symbol with default font", () => {
|
||||
const s = new Symbol("F071");
|
||||
const f = new Formatter().format(s);
|
||||
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } });
|
||||
});
|
||||
|
||||
it("creates the provided symbol with the provided font", () => {
|
||||
const s = new Symbol("F071", "Arial");
|
||||
const f = new Formatter().format(s);
|
||||
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } } });
|
||||
});
|
||||
});
|
||||
});
|
20
src/file/paragraph/run/run-components/symbol.ts
Normal file
20
src/file/paragraph/run/run-components/symbol.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
interface ISymbolAttributesProperties {
|
||||
readonly char: string;
|
||||
readonly symbolfont?: string;
|
||||
}
|
||||
|
||||
class SymbolAttributes extends XmlAttributeComponent<ISymbolAttributesProperties> {
|
||||
protected readonly xmlKeys = {
|
||||
char: "w:char",
|
||||
symbolfont: "w:font",
|
||||
};
|
||||
}
|
||||
|
||||
export class Symbol extends XmlComponent {
|
||||
constructor(char: string = "", symbolfont: string = "Wingdings") {
|
||||
super("w:sym");
|
||||
this.root.push(new SymbolAttributes({ char: char, symbolfont: symbolfont }));
|
||||
}
|
||||
}
|
@ -284,6 +284,22 @@ describe("Run", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#numberOfTotalPagesSection", () => {
|
||||
it("should set the run to the RTL mode", () => {
|
||||
const run = new Run({});
|
||||
run.numberOfTotalPagesSection();
|
||||
const tree = new Formatter().format(run);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:r": [
|
||||
{ "w:fldChar": { _attr: { "w:fldCharType": "begin" } } },
|
||||
{ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "SECTIONPAGES"] },
|
||||
{ "w:fldChar": { _attr: { "w:fldCharType": "separate" } } },
|
||||
{ "w:fldChar": { _attr: { "w:fldCharType": "end" } } },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#pageNumber", () => {
|
||||
it("should set the run to the RTL mode", () => {
|
||||
const run = new Run({});
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { ShadingType } from "file/table";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
import { FieldInstruction } from "file/table-of-contents/field-instruction";
|
||||
import { Break } from "./break";
|
||||
import { Caps, SmallCaps } from "./caps";
|
||||
import { Begin, End, Separate } from "./field";
|
||||
@ -21,7 +22,7 @@ import {
|
||||
SizeComplexScript,
|
||||
Strike,
|
||||
} from "./formatting";
|
||||
import { NumberOfPages, Page } from "./page-number";
|
||||
import { NumberOfPages, NumberOfPagesSection, Page } from "./page-number";
|
||||
import { RunProperties } from "./properties";
|
||||
import { RunFonts } from "./run-fonts";
|
||||
import { SubScript, SuperScript } from "./script";
|
||||
@ -56,6 +57,7 @@ export interface IRunOptions {
|
||||
readonly fill: string;
|
||||
readonly color: string;
|
||||
};
|
||||
readonly children?: Array<Begin | FieldInstruction | Separate | End>;
|
||||
}
|
||||
|
||||
export class Run extends XmlComponent {
|
||||
@ -134,6 +136,12 @@ export class Run extends XmlComponent {
|
||||
this.properties.push(new Shading(options.shading.type, options.shading.fill, options.shading.color));
|
||||
this.properties.push(new ShadowComplexScript(options.shading.type, options.shading.fill, options.shading.color));
|
||||
}
|
||||
|
||||
if (options.children) {
|
||||
for (const child of options.children) {
|
||||
this.root.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public break(): Run {
|
||||
@ -161,4 +169,12 @@ export class Run extends XmlComponent {
|
||||
this.root.push(new End());
|
||||
return this;
|
||||
}
|
||||
|
||||
public numberOfTotalPagesSection(): Run {
|
||||
this.root.push(new Begin());
|
||||
this.root.push(new NumberOfPagesSection());
|
||||
this.root.push(new Separate());
|
||||
this.root.push(new End());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
76
src/file/paragraph/run/symbol-run.spec.ts
Normal file
76
src/file/paragraph/run/symbol-run.spec.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { UnderlineType } from "./underline";
|
||||
|
||||
import { SymbolRun } from "./symbol-run";
|
||||
|
||||
describe("SymbolRun", () => {
|
||||
let run: SymbolRun;
|
||||
|
||||
describe("#constructor()", () => {
|
||||
it("should create symbol run from text input", () => {
|
||||
run = new SymbolRun("F071");
|
||||
const f = new Formatter().format(run);
|
||||
expect(f).to.deep.equal({
|
||||
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } }],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create symbol run from object input with just 'char' specified", () => {
|
||||
run = new SymbolRun({ char: "F071" });
|
||||
const f = new Formatter().format(run);
|
||||
expect(f).to.deep.equal({
|
||||
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } }],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create symbol run from object input with just 'char' specified", () => {
|
||||
run = new SymbolRun({ char: "F071", symbolfont: "Arial" });
|
||||
const f = new Formatter().format(run);
|
||||
expect(f).to.deep.equal({
|
||||
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } } }],
|
||||
});
|
||||
});
|
||||
|
||||
it("should add other standard run properties", () => {
|
||||
run = new SymbolRun({
|
||||
char: "F071",
|
||||
symbolfont: "Arial",
|
||||
italics: true,
|
||||
bold: true,
|
||||
underline: {
|
||||
color: "red",
|
||||
type: UnderlineType.DOUBLE,
|
||||
},
|
||||
color: "green",
|
||||
size: 40,
|
||||
highlight: "yellow",
|
||||
});
|
||||
|
||||
const f = new Formatter().format(run);
|
||||
expect(f).to.deep.equal({
|
||||
"w:r": [
|
||||
{
|
||||
"w:rPr": [
|
||||
{ "w:b": { _attr: { "w:val": true } } },
|
||||
{ "w:bCs": { _attr: { "w:val": true } } },
|
||||
{ "w:i": { _attr: { "w:val": true } } },
|
||||
{ "w:iCs": { _attr: { "w:val": true } } },
|
||||
{ "w:u": { _attr: { "w:val": "double", "w:color": "red" } } },
|
||||
{ "w:color": { _attr: { "w:val": "green" } } },
|
||||
{ "w:sz": { _attr: { "w:val": 40 } } },
|
||||
{ "w:szCs": { _attr: { "w:val": 40 } } },
|
||||
{ "w:highlight": { _attr: { "w:val": "yellow" } } },
|
||||
{ "w:highlightCs": { _attr: { "w:val": "yellow" } } },
|
||||
],
|
||||
},
|
||||
{
|
||||
"w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
20
src/file/paragraph/run/symbol-run.ts
Normal file
20
src/file/paragraph/run/symbol-run.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { IRunOptions, Run } from "./run";
|
||||
import { Symbol } from "./run-components/symbol";
|
||||
|
||||
export interface ISymbolRunOptions extends IRunOptions {
|
||||
readonly char: string;
|
||||
readonly symbolfont?: string;
|
||||
}
|
||||
|
||||
export class SymbolRun extends Run {
|
||||
constructor(options: ISymbolRunOptions | string) {
|
||||
if (typeof options === "string") {
|
||||
super({});
|
||||
this.root.push(new Symbol(options));
|
||||
return;
|
||||
}
|
||||
|
||||
super(options);
|
||||
this.root.push(new Symbol(options.char, options.symbolfont));
|
||||
}
|
||||
}
|
@ -16,4 +16,23 @@ describe("TextRun", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#referenceFootnote()", () => {
|
||||
it("should add a valid footnote reference", () => {
|
||||
run = new TextRun("test");
|
||||
run.referenceFootnote(1);
|
||||
const tree = new Formatter().format(run);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:r": [
|
||||
{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "test"] },
|
||||
{
|
||||
"w:r": [
|
||||
{ "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "FootnoteReference" } } }] },
|
||||
{ "w:footnoteReference": { _attr: { "w:id": 1 } } },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
|
||||
import { IRunOptions, Run } from "./run";
|
||||
import { Text } from "./run-components/text";
|
||||
|
||||
@ -16,4 +17,9 @@ export class TextRun extends Run {
|
||||
super(options);
|
||||
this.root.push(new Text(options.text));
|
||||
}
|
||||
|
||||
public referenceFootnote(id: number): TextRun {
|
||||
this.root.push(new FootnoteReferenceRun(id));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ describe("Underline", () => {
|
||||
});
|
||||
|
||||
it("should use the given style type and color", () => {
|
||||
const underline = new u.Underline("double", "FF00CC");
|
||||
const underline = new u.Underline(u.UnderlineType.DOUBLE, "FF00CC");
|
||||
const tree = new Formatter().format(underline);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:u": { _attr: { "w:val": "double", "w:color": "FF00CC" } },
|
||||
|
@ -33,7 +33,7 @@ export abstract class BaseUnderline extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Underline extends BaseUnderline {
|
||||
constructor(underlineType: string = "single", color?: string) {
|
||||
constructor(underlineType: UnderlineType = UnderlineType.SINGLE, color?: string) {
|
||||
super(underlineType, color);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user