Merge pull request #956 from devoidfury/experiment
v7 prep - includes redesigning parts of core, and unifying different types
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
// Multiple sections and headers
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { Document, Footer, Header, Packer, PageNumber, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
|
||||
import { Document, Footer, Header, Packer, PageNumber, NumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
@ -13,7 +13,7 @@ const doc = new Document({
|
||||
page: {
|
||||
pageNumbers: {
|
||||
start: 1,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -38,7 +38,7 @@ const doc = new Document({
|
||||
},
|
||||
pageNumbers: {
|
||||
start: 1,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -85,7 +85,7 @@ const doc = new Document({
|
||||
orientation: PageOrientation.PORTRAIT,
|
||||
},
|
||||
pageNumbers: {
|
||||
formatType: PageNumberFormat.UPPER_ROMAN,
|
||||
formatType: NumberFormat.UPPER_ROMAN,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -116,7 +116,7 @@ const doc = new Document({
|
||||
},
|
||||
pageNumbers: {
|
||||
start: 25,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -24,7 +24,7 @@ const doc = new Document({
|
||||
size: 28,
|
||||
bold: true,
|
||||
italics: true,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
paragraph: {
|
||||
spacing: {
|
||||
|
@ -36,17 +36,17 @@ const doc = new Document({
|
||||
top: {
|
||||
style: BorderStyle.DASH_DOT_STROKED,
|
||||
size: 3,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
bottom: {
|
||||
style: BorderStyle.DOUBLE,
|
||||
size: 3,
|
||||
color: "blue",
|
||||
color: "0000FF",
|
||||
},
|
||||
left: {
|
||||
style: BorderStyle.DASH_DOT_STROKED,
|
||||
size: 3,
|
||||
color: "green",
|
||||
color: "00FF00",
|
||||
},
|
||||
right: {
|
||||
style: BorderStyle.DASH_DOT_STROKED,
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Creates two paragraphs, one with a border and one without
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { Document, Packer, Paragraph } from "../build";
|
||||
import { BorderStyle, Document, Packer, Paragraph } from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
@ -14,13 +14,13 @@ const doc = new Document({
|
||||
top: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
bottom: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
},
|
||||
|
@ -9,6 +9,9 @@ import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } fr
|
||||
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
|
||||
// making the entries be hyperlinks for the paragraph
|
||||
const doc = new File({
|
||||
features: {
|
||||
updateFields: true,
|
||||
},
|
||||
styles: {
|
||||
paragraphStyles: [
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ const table3 = new Table({
|
||||
children: [new Paragraph("Bar1")],
|
||||
shading: {
|
||||
fill: "b79c2f",
|
||||
val: ShadingType.REVERSE_DIAGONAL_STRIPE,
|
||||
type: ShadingType.REVERSE_DIAGONAL_STRIPE,
|
||||
color: "auto",
|
||||
},
|
||||
}),
|
||||
@ -106,7 +106,7 @@ const table3 = new Table({
|
||||
children: [new Paragraph("Bar2")],
|
||||
shading: {
|
||||
fill: "42c5f4",
|
||||
val: ShadingType.PERCENT_95,
|
||||
type: ShadingType.PERCENT_95,
|
||||
color: "auto",
|
||||
},
|
||||
}),
|
||||
@ -114,7 +114,7 @@ const table3 = new Table({
|
||||
children: [new Paragraph("Bar3")],
|
||||
shading: {
|
||||
fill: "880aa8",
|
||||
val: ShadingType.PERCENT_10,
|
||||
type: ShadingType.PERCENT_10,
|
||||
color: "e2df0b",
|
||||
},
|
||||
}),
|
||||
@ -122,7 +122,7 @@ const table3 = new Table({
|
||||
children: [new Paragraph("Bar4")],
|
||||
shading: {
|
||||
fill: "FF0000",
|
||||
val: ShadingType.CLEAR,
|
||||
type: ShadingType.CLEAR,
|
||||
color: "auto",
|
||||
},
|
||||
}),
|
||||
@ -224,22 +224,22 @@ const borders = {
|
||||
top: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
bottom: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
left: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
right: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Example how to display page numbers
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
|
||||
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
@ -10,7 +10,7 @@ const doc = new Document({
|
||||
page: {
|
||||
pageNumbers: {
|
||||
start: 1,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -14,7 +14,7 @@ const doc = new Document({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: "Hello World",
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
bold: true,
|
||||
size: 24,
|
||||
font: {
|
||||
|
@ -14,7 +14,7 @@ const doc = new Document({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: "Hello World",
|
||||
color: "red",
|
||||
color: "FF0000",
|
||||
bold: true,
|
||||
size: 24,
|
||||
font: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Multiple sections with total number of pages in each section
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
|
||||
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
|
||||
|
||||
const header = new Header({
|
||||
children: [
|
||||
@ -31,7 +31,7 @@ const doc = new Document({
|
||||
page: {
|
||||
pageNumbers: {
|
||||
start: 1,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -52,7 +52,7 @@ const doc = new Document({
|
||||
page: {
|
||||
pageNumbers: {
|
||||
start: 1,
|
||||
formatType: PageNumberFormat.DECIMAL,
|
||||
formatType: NumberFormat.DECIMAL,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Example of making content of section vertically aligned
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { Document, Packer, Paragraph, SectionVerticalAlignValue, TextRun } from "../build";
|
||||
import { Document, Packer, Paragraph, VerticalAlign, TextRun } from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
{
|
||||
properties: {
|
||||
verticalAlign: SectionVerticalAlignValue.CENTER,
|
||||
verticalAlign: VerticalAlign.CENTER,
|
||||
},
|
||||
children: [
|
||||
new Paragraph({
|
||||
|
@ -24,22 +24,22 @@ const table = new Table({
|
||||
top: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
},
|
||||
bottom: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
},
|
||||
left: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
},
|
||||
right: {
|
||||
style: BorderStyle.DASH_SMALL_GAP,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
},
|
||||
},
|
||||
children: [new Paragraph("Hello")],
|
||||
|
@ -20,10 +20,12 @@ import {
|
||||
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.insertedrun
|
||||
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.deletedrun
|
||||
|
||||
The method `addTrackRevisions()` adds an element `<w:trackRevisions />` to the `settings.xml` file. This specifies that the application shall track *new* revisions made to the existing document.
|
||||
The setting `features: { trackRevisions: true }` adds an element `<w:trackRevisions />` to the `settings.xml` file.
|
||||
This specifies that the application shall track *new* revisions made to the existing document.
|
||||
See also https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.trackrevisions
|
||||
|
||||
Note that this setting enables to track *new changes* after teh file is generated, so this example will still show inserted and deleted text runs when you remove it.
|
||||
Note that this setting enables to track *new changes* after teh file is generated, so this example will still
|
||||
show inserted and deleted text runs when you remove it.
|
||||
*/
|
||||
|
||||
const paragraph = new Paragraph({
|
||||
@ -85,7 +87,7 @@ const doc = new Document({
|
||||
new DeletedTextRun({
|
||||
break: 1,
|
||||
text: "in order",
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
bold: true,
|
||||
size: 24,
|
||||
font: {
|
||||
|
@ -1,7 +1,16 @@
|
||||
// Text Frame (Text Box) example
|
||||
// Import from 'docx' rather than '../build' if you install from npm
|
||||
import * as fs from "fs";
|
||||
import { Document, FrameAnchorType, HorizontalPositionAlign, Packer, Paragraph, TextRun, VerticalPositionAlign } from "../build";
|
||||
import {
|
||||
BorderStyle,
|
||||
Document,
|
||||
FrameAnchorType,
|
||||
HorizontalPositionAlign,
|
||||
Packer,
|
||||
Paragraph,
|
||||
TextRun,
|
||||
VerticalPositionAlign,
|
||||
} from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
@ -29,25 +38,25 @@ const doc = new Document({
|
||||
top: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
bottom: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
left: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
right: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 6,
|
||||
},
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ const paragraph = new Paragraph({
|
||||
new TextRun("This is a simple demo"),
|
||||
new DeletedTextRun({
|
||||
text: "with a deletion.",
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
bold: true,
|
||||
size: 24,
|
||||
id: 0,
|
||||
|
@ -12,14 +12,29 @@ The complete documentation can be found [here](https://www.ecma-international.or
|
||||
|
||||
All you need to do is create a `TableOfContents` object and assign it to the document.
|
||||
|
||||
**Note**: updateFields feature must be enabled for TableOfContents to update correctly.
|
||||
|
||||
```ts
|
||||
const toc = new TableOfContents("Summary", {
|
||||
const doc = new Document({
|
||||
features: {
|
||||
updateFields: true,
|
||||
},
|
||||
sections: [
|
||||
{
|
||||
children: [
|
||||
new TableOfContents("Summary", {
|
||||
hyperlink: true,
|
||||
headingStyleRange: "1-5",
|
||||
stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)],
|
||||
}),
|
||||
new Paragraph({
|
||||
text: "Header #1",
|
||||
heading: HeadingLevel.HEADING_1,
|
||||
pageBreakBefore: true,
|
||||
}),
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
doc.addTableOfContents(toc);
|
||||
```
|
||||
|
||||
## Table of Contents Options
|
||||
|
@ -53,6 +53,18 @@ const table = new Table({
|
||||
});
|
||||
```
|
||||
|
||||
### Set Indent
|
||||
|
||||
```ts
|
||||
const table = new Table({
|
||||
...,
|
||||
indent: {
|
||||
size: 600,
|
||||
type: WidthType.DXA,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Table Row
|
||||
|
||||
A table consists of multiple `table rows`. Table rows have a list of `children` which accepts a list of `table cells` explained below. You can create a simple `table row` like so:
|
||||
@ -145,7 +157,7 @@ const tableRow = new TableRow({
|
||||
| Property | Type | Notes |
|
||||
| ------------- | ----------------------------------- | ----------------------------------------------------------- |
|
||||
| children | `Array<Paragraph or Table>` | Required. You can nest tables by adding a table into a cell |
|
||||
| shading | `ITableShadingAttributesProperties` | Optional |
|
||||
| shading | `IShadingAttributesProperties` | Optional |
|
||||
| margins | `ITableCellMarginOptions` | Optional |
|
||||
| verticalAlign | `VerticalAlign` | Optional |
|
||||
| columnSpan | `number` | Optional |
|
||||
@ -171,7 +183,7 @@ const cell = new TableCell({
|
||||
top: {
|
||||
style: BorderStyle.DASH_DOT_STROKED,
|
||||
size: 1,
|
||||
color: "red",
|
||||
color: "ff0000",
|
||||
},
|
||||
bottom: {
|
||||
style: BorderStyle.THICK_THIN_MEDIUM_GAP,
|
||||
@ -190,12 +202,12 @@ Google DOCS does not support start and end borders, instead they use left and ri
|
||||
const cell = new TableCell({
|
||||
...,
|
||||
borders: {
|
||||
top: {
|
||||
left: {
|
||||
style: BorderStyle.DOT_DOT_DASH,
|
||||
size: 3,
|
||||
color: "green",
|
||||
color: "00FF00",
|
||||
},
|
||||
bottom: {
|
||||
right: {
|
||||
style: BorderStyle.DOT_DOT_DASH,
|
||||
size: 3,
|
||||
color: "ff8000",
|
||||
|
@ -18,14 +18,14 @@ describe("Utility", () => {
|
||||
});
|
||||
|
||||
describe("#uniqueNumericId", () => {
|
||||
it("should generate a unique ID", () => {
|
||||
it("should generate a unique incrementing ID", () => {
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
expect(uniqueNumericId()).to.not.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#uniqueId", () => {
|
||||
it("should call the underlying header's addChildElement", () => {
|
||||
it("should generate a unique pseudorandom ID", () => {
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
expect(uniqueId()).to.not.be.empty;
|
||||
});
|
||||
|
@ -12,7 +12,7 @@ export const convertInchesToTwip = (inches: number): number => {
|
||||
};
|
||||
|
||||
export const uniqueNumericId = (): number => {
|
||||
return currentCount++;
|
||||
return ++currentCount;
|
||||
};
|
||||
|
||||
export const uniqueId = (): string => {
|
||||
|
@ -45,18 +45,10 @@ describe("Formatter", () => {
|
||||
{
|
||||
"w:rPr": [
|
||||
{
|
||||
"w:b": {
|
||||
_attr: {
|
||||
"w:val": true,
|
||||
},
|
||||
},
|
||||
"w:b": {},
|
||||
},
|
||||
{
|
||||
"w:bCs": {
|
||||
_attr: {
|
||||
"w:val": true,
|
||||
},
|
||||
},
|
||||
"w:bCs": {},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -70,7 +70,6 @@ export class Compiler {
|
||||
}
|
||||
|
||||
private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping {
|
||||
file.verifyUpdateFields();
|
||||
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
||||
|
||||
const documentXmlData = xml(
|
||||
@ -78,7 +77,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
|
||||
|
||||
@ -98,7 +103,12 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
})(),
|
||||
path: "word/_rels/document.xml.rels",
|
||||
@ -118,7 +128,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "word/styles.xml",
|
||||
},
|
||||
@ -129,6 +145,7 @@ export class Compiler {
|
||||
file,
|
||||
}),
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
@ -143,7 +160,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "word/numbering.xml",
|
||||
},
|
||||
@ -153,7 +176,12 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "_rels/.rels",
|
||||
},
|
||||
@ -163,7 +191,12 @@ export class Compiler {
|
||||
viewWrapper: headerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||
|
||||
@ -181,7 +214,12 @@ export class Compiler {
|
||||
viewWrapper: headerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: `word/_rels/header${index + 1}.xml.rels`,
|
||||
};
|
||||
@ -192,7 +230,12 @@ export class Compiler {
|
||||
viewWrapper: footerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||
|
||||
@ -210,7 +253,12 @@ export class Compiler {
|
||||
viewWrapper: footerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: `word/_rels/footer${index + 1}.xml.rels`,
|
||||
};
|
||||
@ -221,7 +269,12 @@ export class Compiler {
|
||||
viewWrapper: headerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||
@ -238,7 +291,12 @@ export class Compiler {
|
||||
viewWrapper: footerWrapper,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
);
|
||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||
@ -255,7 +313,12 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "[Content_Types].xml",
|
||||
},
|
||||
@ -265,7 +328,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "docProps/custom.xml",
|
||||
},
|
||||
@ -275,7 +344,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "docProps/app.xml",
|
||||
},
|
||||
@ -285,7 +360,12 @@ export class Compiler {
|
||||
viewWrapper: file.FootNotes,
|
||||
file: file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "word/footnotes.xml",
|
||||
},
|
||||
@ -295,7 +375,12 @@ export class Compiler {
|
||||
viewWrapper: file.FootNotes,
|
||||
file: file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "word/_rels/footnotes.xml.rels",
|
||||
},
|
||||
@ -305,7 +390,13 @@ export class Compiler {
|
||||
viewWrapper: file.Document,
|
||||
file,
|
||||
}),
|
||||
prettify,
|
||||
{
|
||||
indent: prettify,
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
},
|
||||
),
|
||||
path: "word/settings.xml",
|
||||
},
|
||||
|
54
src/file/border/border.spec.ts
Normal file
54
src/file/border/border.spec.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { BorderStyle } from "file/border";
|
||||
|
||||
import { BorderElement } from "./border";
|
||||
|
||||
describe("BorderElement", () => {
|
||||
describe("#constructor", () => {
|
||||
it("should create a simple border element", () => {
|
||||
const border = new BorderElement("w:top", {
|
||||
style: BorderStyle.SINGLE,
|
||||
});
|
||||
const tree = new Formatter().format(border);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:top": {
|
||||
_attr: {
|
||||
"w:val": "single",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
it("should create a simple border element with a size", () => {
|
||||
const border = new BorderElement("w:top", {
|
||||
style: BorderStyle.SINGLE,
|
||||
size: 22,
|
||||
});
|
||||
const tree = new Formatter().format(border);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:top": {
|
||||
_attr: {
|
||||
"w:val": "single",
|
||||
"w:sz": 22,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
it("should create a simple border element with space", () => {
|
||||
const border = new BorderElement("w:top", {
|
||||
style: BorderStyle.SINGLE,
|
||||
space: 22,
|
||||
});
|
||||
const tree = new Formatter().format(border);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:top": {
|
||||
_attr: {
|
||||
"w:val": "single",
|
||||
"w:space": 22,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
86
src/file/border/border.ts
Normal file
86
src/file/border/border.ts
Normal file
@ -0,0 +1,86 @@
|
||||
// Note that the border type is identical in all places,
|
||||
// regardless of where it's used like paragraph/table/etc.
|
||||
// PageBorders are a superset, but we're not using any of those extras.
|
||||
//
|
||||
// http://officeopenxml.com/WPborders.php
|
||||
// http://officeopenxml.com/WPtableBorders.php
|
||||
// http://officeopenxml.com/WPtableCellProperties-Borders.php
|
||||
// http://officeopenxml.com/WPsectionBorders.php
|
||||
//
|
||||
// This describes the CT_Border type.
|
||||
// <xsd:complexType name="CT_Border">
|
||||
// <xsd:attribute name="val" type="ST_Border" use="required"/>
|
||||
// <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/>
|
||||
// <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/>
|
||||
// <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/>
|
||||
// <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/>
|
||||
// <xsd:attribute name="sz" type="ST_EighthPointMeasure" use="optional"/>
|
||||
// <xsd:attribute name="space" type="ST_PointMeasure" use="optional" default="0"/>
|
||||
// <xsd:attribute name="shadow" type="s:ST_OnOff" use="optional"/>
|
||||
// <xsd:attribute name="frame" type="s:ST_OnOff" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "../values";
|
||||
|
||||
export interface IBorderOptions {
|
||||
readonly style: BorderStyle;
|
||||
/** Border color, in hex (eg 'FF00AA') */
|
||||
readonly color?: string;
|
||||
/** Size of the border in 1/8 pt */
|
||||
readonly size?: number;
|
||||
/** Spacing offset. Values are specified in pt */
|
||||
readonly space?: number;
|
||||
}
|
||||
|
||||
export class BorderElement extends XmlComponent {
|
||||
constructor(elementName: string, { color, size, space, style }: IBorderOptions) {
|
||||
super(elementName);
|
||||
this.root.push(
|
||||
new BordersAttributes({
|
||||
style,
|
||||
color: color === undefined ? undefined : hexColorValue(color),
|
||||
size: size === undefined ? undefined : eighthPointMeasureValue(size),
|
||||
space: space === undefined ? undefined : pointMeasureValue(space),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BordersAttributes extends XmlAttributeComponent<IBorderOptions> {
|
||||
protected readonly xmlKeys = {
|
||||
style: "w:val",
|
||||
color: "w:color",
|
||||
size: "w:sz",
|
||||
space: "w:space",
|
||||
};
|
||||
}
|
||||
|
||||
export enum BorderStyle {
|
||||
SINGLE = "single",
|
||||
DASH_DOT_STROKED = "dashDotStroked",
|
||||
DASHED = "dashed",
|
||||
DASH_SMALL_GAP = "dashSmallGap",
|
||||
DOT_DASH = "dotDash",
|
||||
DOT_DOT_DASH = "dotDotDash",
|
||||
DOTTED = "dotted",
|
||||
DOUBLE = "double",
|
||||
DOUBLE_WAVE = "doubleWave",
|
||||
INSET = "inset",
|
||||
NIL = "nil",
|
||||
NONE = "none",
|
||||
OUTSET = "outset",
|
||||
THICK = "thick",
|
||||
THICK_THIN_LARGE_GAP = "thickThinLargeGap",
|
||||
THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
|
||||
THICK_THIN_SMALL_GAP = "thickThinSmallGap",
|
||||
THIN_THICK_LARGE_GAP = "thinThickLargeGap",
|
||||
THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
|
||||
THIN_THICK_SMALL_GAP = "thinThickSmallGap",
|
||||
THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
|
||||
THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
|
||||
THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
|
||||
THREE_D_EMBOSS = "threeDEmboss",
|
||||
THREE_D_ENGRAVE = "threeDEngrave",
|
||||
TRIPLE = "triple",
|
||||
WAVE = "wave",
|
||||
}
|
1
src/file/border/index.ts
Normal file
1
src/file/border/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./border";
|
@ -1,89 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocumentAttributes } from "../document/document-attributes";
|
||||
|
||||
export class Title extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("dc:title");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Subject extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("dc:subject");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Creator extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("dc:creator");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Keywords extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("cp:keywords");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Description extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("dc:description");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class LastModifiedBy extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("cp:lastModifiedBy");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Revision extends XmlComponent {
|
||||
constructor(value: string) {
|
||||
super("cp:revision");
|
||||
this.root.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class DateComponent extends XmlComponent {
|
||||
protected getCurrentDate(): string {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = ("0" + (date.getMonth() + 1)).slice(-2);
|
||||
const day = ("0" + date.getDate()).slice(-2);
|
||||
const hours = ("0" + date.getHours()).slice(-2);
|
||||
const minutes = ("0" + date.getMinutes()).slice(-2);
|
||||
const seconds = ("0" + date.getSeconds()).slice(-2);
|
||||
|
||||
return year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z";
|
||||
}
|
||||
}
|
||||
|
||||
export class Created extends DateComponent {
|
||||
constructor() {
|
||||
super("dcterms:created");
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}),
|
||||
);
|
||||
this.root.push(this.getCurrentDate());
|
||||
}
|
||||
}
|
||||
|
||||
export class Modified extends DateComponent {
|
||||
constructor() {
|
||||
super("dcterms:modified");
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}),
|
||||
);
|
||||
this.root.push(this.getCurrentDate());
|
||||
}
|
||||
}
|
@ -27,8 +27,7 @@ describe("Properties", () => {
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||
expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
|
||||
expect(tree["cp:coreProperties"][1]).to.deep.equal({ "dc:title": ["test document"] });
|
||||
expect(tree["cp:coreProperties"]).to.deep.include({ "dc:title": ["test document"] });
|
||||
});
|
||||
|
||||
it("should create properties with all the attributes given", () => {
|
||||
@ -44,9 +43,9 @@ describe("Properties", () => {
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||
|
||||
const key = (obj) => Object.keys(obj)[0];
|
||||
const props = tree["cp:coreProperties"].map(key).sort();
|
||||
expect(props).to.deep.equal([
|
||||
expect(tree["cp:coreProperties"].map(key)).to.include.members([
|
||||
"_attr",
|
||||
"cp:keywords",
|
||||
"cp:lastModifiedBy",
|
||||
@ -58,7 +57,7 @@ describe("Properties", () => {
|
||||
"dcterms:created",
|
||||
"dcterms:modified",
|
||||
]);
|
||||
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => (key(a) < key(b) ? -1 : 1))).to.deep.equal([
|
||||
expect(tree["cp:coreProperties"]).to.deep.include.members([
|
||||
{ "cp:keywords": ["test docx"] },
|
||||
{ "cp:lastModifiedBy": ["the author"] },
|
||||
{ "cp:revision": ["123"] },
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { StringContainer, XmlComponent } from "file/xml-components";
|
||||
import { ICustomPropertyOptions } from "../custom-properties";
|
||||
import { IDocumentBackgroundOptions } from "../document";
|
||||
|
||||
@ -7,7 +7,7 @@ import { ISectionOptions } from "../file";
|
||||
import { INumberingOptions } from "../numbering";
|
||||
import { Paragraph } from "../paragraph";
|
||||
import { IStylesOptions } from "../styles";
|
||||
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
||||
import { dateTimeValue } from "../values";
|
||||
|
||||
export interface IPropertiesOptions {
|
||||
readonly sections: ISectionOptions[];
|
||||
@ -29,12 +29,35 @@ export interface IPropertiesOptions {
|
||||
readonly background?: IDocumentBackgroundOptions;
|
||||
readonly features?: {
|
||||
readonly trackRevisions?: boolean;
|
||||
readonly updateFields?: boolean;
|
||||
};
|
||||
readonly compatabilityModeVersion?: number;
|
||||
readonly customProperties?: ICustomPropertyOptions[];
|
||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||
}
|
||||
|
||||
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||
|
||||
// <xs:complexType name="CT_CoreProperties">
|
||||
// <xs:all>
|
||||
// <xs:element name="category" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||
// <xs:element name="contentStatus" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||
// <xs:element ref="dcterms:created" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element ref="dc:creator" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element ref="dc:description" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element ref="dc:identifier" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element name="keywords" minOccurs="0" maxOccurs="1" type="CT_Keywords"/>
|
||||
// <xs:element ref="dc:language" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element name="lastModifiedBy" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||
// <xs:element name="lastPrinted" minOccurs="0" maxOccurs="1" type="xs:dateTime"/>
|
||||
// <xs:element ref="dcterms:modified" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element name="revision" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||
// <xs:element ref="dc:subject" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element ref="dc:title" minOccurs="0" maxOccurs="1"/>
|
||||
// <xs:element name="version" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||
// </xs:all>
|
||||
// </xs:complexType>
|
||||
|
||||
export class CoreProperties extends XmlComponent {
|
||||
constructor(options: Omit<IPropertiesOptions, "sections">) {
|
||||
super("cp:coreProperties");
|
||||
@ -48,27 +71,39 @@ export class CoreProperties extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
if (options.title) {
|
||||
this.root.push(new Title(options.title));
|
||||
this.root.push(new StringContainer("dc:title", options.title));
|
||||
}
|
||||
if (options.subject) {
|
||||
this.root.push(new Subject(options.subject));
|
||||
this.root.push(new StringContainer("dc:subject", options.subject));
|
||||
}
|
||||
if (options.creator) {
|
||||
this.root.push(new Creator(options.creator));
|
||||
this.root.push(new StringContainer("dc:creator", options.creator));
|
||||
}
|
||||
if (options.keywords) {
|
||||
this.root.push(new Keywords(options.keywords));
|
||||
this.root.push(new StringContainer("cp:keywords", options.keywords));
|
||||
}
|
||||
if (options.description) {
|
||||
this.root.push(new Description(options.description));
|
||||
this.root.push(new StringContainer("dc:description", options.description));
|
||||
}
|
||||
if (options.lastModifiedBy) {
|
||||
this.root.push(new LastModifiedBy(options.lastModifiedBy));
|
||||
this.root.push(new StringContainer("cp:lastModifiedBy", options.lastModifiedBy));
|
||||
}
|
||||
if (options.revision) {
|
||||
this.root.push(new Revision(options.revision));
|
||||
this.root.push(new StringContainer("cp:revision", options.revision));
|
||||
}
|
||||
this.root.push(new Created());
|
||||
this.root.push(new Modified());
|
||||
this.root.push(new TimestampElement("dcterms:created"));
|
||||
this.root.push(new TimestampElement("dcterms:modified"));
|
||||
}
|
||||
}
|
||||
|
||||
class TimestampElement extends XmlComponent {
|
||||
constructor(name: string) {
|
||||
super(name);
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}),
|
||||
);
|
||||
this.root.push(dateTimeValue(new Date()));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { expect } from "chai";
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { Body } from "./body";
|
||||
import { sectionMarginDefaults } from "./section-properties";
|
||||
|
||||
describe("Body", () => {
|
||||
let body: Body;
|
||||
@ -32,13 +33,13 @@ describe("Body", () => {
|
||||
{
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:bottom": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:footer": 708,
|
||||
"w:gutter": 0,
|
||||
"w:top": sectionMarginDefaults.TOP,
|
||||
"w:right": sectionMarginDefaults.RIGHT,
|
||||
"w:bottom": sectionMarginDefaults.BOTTOM,
|
||||
"w:left": sectionMarginDefaults.LEFT,
|
||||
"w:header": sectionMarginDefaults.HEADER,
|
||||
"w:footer": sectionMarginDefaults.FOOTER,
|
||||
"w:gutter": sectionMarginDefaults.GUTTER,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -47,7 +48,7 @@ describe("Body", () => {
|
||||
_attr: {},
|
||||
},
|
||||
},
|
||||
{ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
|
||||
// { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
|
||||
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
|
||||
],
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||
|
||||
import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
|
||||
import { Paragraph, ParagraphProperties } from "../..";
|
||||
import { ISectionPropertiesOptions, SectionProperties } from "./section-properties/section-properties";
|
||||
|
||||
export class Body extends XmlComponent {
|
||||
@ -38,10 +38,6 @@ export class Body extends XmlComponent {
|
||||
this.root.push(component);
|
||||
}
|
||||
|
||||
public getTablesOfContents(): TableOfContents[] {
|
||||
return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[];
|
||||
}
|
||||
|
||||
private createSectionParagraph(section: SectionProperties): Paragraph {
|
||||
const paragraph = new Paragraph({});
|
||||
const properties = new ParagraphProperties({});
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export class ColumnsAttributes extends XmlAttributeComponent<{
|
||||
readonly space?: number;
|
||||
readonly num?: number;
|
||||
readonly separate?: boolean;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
space: "w:space",
|
||||
num: "w:num",
|
||||
separate: "w:sep",
|
||||
};
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { ColumnsAttributes } from "./columns-attributes";
|
||||
|
||||
export class Columns extends XmlComponent {
|
||||
constructor(space: number, num: number, separate: boolean) {
|
||||
super("w:cols");
|
||||
this.root.push(
|
||||
new ColumnsAttributes({
|
||||
space: space,
|
||||
num: num,
|
||||
separate: separate,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IDocGridAttributesProperties {
|
||||
readonly linePitch?: number;
|
||||
}
|
||||
|
||||
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||
protected readonly xmlKeys = {
|
||||
linePitch: "w:linePitch",
|
||||
};
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocGridAttributes } from "./doc-grid-attributes";
|
||||
|
||||
export class DocumentGrid extends XmlComponent {
|
||||
constructor(linePitch: number) {
|
||||
super("w:docGrid");
|
||||
this.root.push(
|
||||
new DocGridAttributes({
|
||||
linePitch: linePitch,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export enum FooterReferenceType {
|
||||
DEFAULT = "default",
|
||||
FIRST = "first",
|
||||
EVEN = "even",
|
||||
}
|
||||
|
||||
export class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||
readonly type: string;
|
||||
readonly id: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
type: "w:type",
|
||||
id: "r:id",
|
||||
};
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { FooterReference } from "./footer-reference";
|
||||
import { FooterReferenceType } from "./footer-reference-attributes";
|
||||
|
||||
describe("footerReference", () => {
|
||||
it("should create", () => {
|
||||
const footer = new FooterReference({
|
||||
footerType: FooterReferenceType.DEFAULT,
|
||||
footerId: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:footerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create without a footer type", () => {
|
||||
const footer = new FooterReference({
|
||||
footerId: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:footerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
@ -1,20 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
|
||||
|
||||
export interface IFooterOptions {
|
||||
readonly footerType?: FooterReferenceType;
|
||||
readonly footerId?: number;
|
||||
}
|
||||
|
||||
export class FooterReference extends XmlComponent {
|
||||
constructor(options: IFooterOptions) {
|
||||
super("w:footerReference");
|
||||
|
||||
this.root.push(
|
||||
new FooterReferenceAttributes({
|
||||
type: options.footerType || FooterReferenceType.DEFAULT,
|
||||
id: `rId${options.footerId}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from "./footer-reference";
|
||||
export * from "./footer-reference-attributes";
|
@ -1,17 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export enum HeaderReferenceType {
|
||||
DEFAULT = "default",
|
||||
FIRST = "first",
|
||||
EVEN = "even",
|
||||
}
|
||||
|
||||
export class HeaderReferenceAttributes extends XmlAttributeComponent<{
|
||||
readonly type: string;
|
||||
readonly id: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
type: "w:type",
|
||||
id: "r:id",
|
||||
};
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { HeaderReference } from "./header-reference";
|
||||
import { HeaderReferenceType } from "./header-reference-attributes";
|
||||
|
||||
describe("HeaderReference", () => {
|
||||
it("should create", () => {
|
||||
const footer = new HeaderReference({
|
||||
headerType: HeaderReferenceType.DEFAULT,
|
||||
headerId: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:headerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create without a header type", () => {
|
||||
const footer = new HeaderReference({
|
||||
headerId: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:headerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
@ -1,19 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
|
||||
|
||||
export interface IHeaderReferenceOptions {
|
||||
readonly headerType?: HeaderReferenceType;
|
||||
readonly headerId?: number;
|
||||
}
|
||||
|
||||
export class HeaderReference extends XmlComponent {
|
||||
constructor(options: IHeaderReferenceOptions) {
|
||||
super("w:headerReference");
|
||||
this.root.push(
|
||||
new HeaderReferenceAttributes({
|
||||
type: options.headerType || HeaderReferenceType.DEFAULT,
|
||||
id: `rId${options.headerId}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from "./header-reference";
|
||||
export * from "./header-reference-attributes";
|
@ -1,9 +1,2 @@
|
||||
export * from "./section-properties";
|
||||
export * from "./footer-reference";
|
||||
export * from "./header-reference";
|
||||
export * from "./page-size";
|
||||
export * from "./page-number";
|
||||
export * from "./page-border";
|
||||
export * from "./line-number";
|
||||
export * from "./vertical-align";
|
||||
export * from "./type";
|
||||
export * from "./properties";
|
||||
|
@ -1 +0,0 @@
|
||||
export * from "./line-number";
|
@ -1,38 +0,0 @@
|
||||
// http://officeopenxml.com/WPsectionLineNumbering.php
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export enum LineNumberRestartFormat {
|
||||
CONTINUOUS = "continuous",
|
||||
NEW_SECTION = "newSection",
|
||||
NEW_PAGE = "newPage",
|
||||
}
|
||||
|
||||
export interface ILineNumberAttributes {
|
||||
readonly countBy?: number;
|
||||
readonly start?: number;
|
||||
readonly restart?: LineNumberRestartFormat;
|
||||
readonly distance?: number;
|
||||
}
|
||||
|
||||
export class LineNumberAttributes extends XmlAttributeComponent<ILineNumberAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
countBy: "w:countBy",
|
||||
start: "w:start",
|
||||
restart: "w:restart",
|
||||
distance: "w:distance",
|
||||
};
|
||||
}
|
||||
|
||||
export class LineNumberType extends XmlComponent {
|
||||
constructor(countBy?: number, start?: number, restart?: LineNumberRestartFormat, dist?: number) {
|
||||
super("w:lnNumType");
|
||||
this.root.push(
|
||||
new LineNumberAttributes({
|
||||
countBy: countBy,
|
||||
start: start,
|
||||
restart: restart,
|
||||
distance: dist,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from "./page-borders";
|
@ -1,100 +0,0 @@
|
||||
// http://officeopenxml.com/WPsectionBorders.php
|
||||
import { BorderStyle } from "file/styles";
|
||||
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export enum PageBorderDisplay {
|
||||
ALL_PAGES = "allPages",
|
||||
FIRST_PAGE = "firstPage",
|
||||
NOT_FIRST_PAGE = "notFirstPage",
|
||||
}
|
||||
|
||||
export enum PageBorderOffsetFrom {
|
||||
PAGE = "page",
|
||||
TEXT = "text",
|
||||
}
|
||||
|
||||
export enum PageBorderZOrder {
|
||||
BACK = "back",
|
||||
FRONT = "front",
|
||||
}
|
||||
|
||||
export interface IPageBorderAttributes {
|
||||
readonly display?: PageBorderDisplay;
|
||||
readonly offsetFrom?: PageBorderOffsetFrom;
|
||||
readonly zOrder?: PageBorderZOrder;
|
||||
}
|
||||
|
||||
export interface IPageBorderConfiguration {
|
||||
readonly style?: BorderStyle;
|
||||
readonly size?: number;
|
||||
readonly color?: string;
|
||||
readonly space?: number;
|
||||
}
|
||||
|
||||
export interface IPageBordersOptions {
|
||||
readonly pageBorders?: IPageBorderAttributes;
|
||||
readonly pageBorderTop?: IPageBorderConfiguration;
|
||||
readonly pageBorderRight?: IPageBorderConfiguration;
|
||||
readonly pageBorderBottom?: IPageBorderConfiguration;
|
||||
readonly pageBorderLeft?: IPageBorderConfiguration;
|
||||
}
|
||||
|
||||
class PageBordeAttributes extends XmlAttributeComponent<IPageBorderConfiguration> {
|
||||
protected readonly xmlKeys = {
|
||||
style: "w:val",
|
||||
size: "w:size",
|
||||
color: "w:color",
|
||||
space: "w:space",
|
||||
};
|
||||
}
|
||||
|
||||
class PageBorder extends XmlComponent {
|
||||
constructor(key: string, options: IPageBorderConfiguration) {
|
||||
super(key);
|
||||
|
||||
this.root.push(new PageBordeAttributes(options));
|
||||
}
|
||||
}
|
||||
|
||||
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
display: "w:display",
|
||||
offsetFrom: "w:offsetFrom",
|
||||
zOrder: "w:zOrder",
|
||||
};
|
||||
}
|
||||
|
||||
export class PageBorders extends IgnoreIfEmptyXmlComponent {
|
||||
constructor(options?: IPageBordersOptions) {
|
||||
super("w:pgBorders");
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.pageBorders) {
|
||||
this.root.push(
|
||||
new PageBordersAttributes({
|
||||
display: options.pageBorders.display,
|
||||
offsetFrom: options.pageBorders.offsetFrom,
|
||||
zOrder: options.pageBorders.zOrder,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
this.root.push(new PageBordersAttributes({}));
|
||||
}
|
||||
|
||||
if (options.pageBorderTop) {
|
||||
this.root.push(new PageBorder("w:top", options.pageBorderTop));
|
||||
}
|
||||
if (options.pageBorderRight) {
|
||||
this.root.push(new PageBorder("w:right", options.pageBorderRight));
|
||||
}
|
||||
if (options.pageBorderBottom) {
|
||||
this.root.push(new PageBorder("w:bottom", options.pageBorderBottom));
|
||||
}
|
||||
if (options.pageBorderLeft) {
|
||||
this.root.push(new PageBorder("w:left", options.pageBorderLeft));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IPageMarginAttributes {
|
||||
readonly top?: number;
|
||||
readonly right?: number;
|
||||
readonly bottom?: number;
|
||||
readonly left?: number;
|
||||
readonly header?: number;
|
||||
readonly footer?: number;
|
||||
readonly gutter?: number;
|
||||
}
|
||||
|
||||
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
top: "w:top",
|
||||
right: "w:right",
|
||||
bottom: "w:bottom",
|
||||
left: "w:left",
|
||||
header: "w:header",
|
||||
footer: "w:footer",
|
||||
gutter: "w:gutter",
|
||||
};
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PageMarginAttributes } from "./page-margin-attributes";
|
||||
|
||||
export class PageMargin extends XmlComponent {
|
||||
constructor(top: number, right: number, bottom: number, left: number, header: number, footer: number, gutter: number) {
|
||||
super("w:pgMar");
|
||||
this.root.push(
|
||||
new PageMarginAttributes({
|
||||
top: top,
|
||||
right: right,
|
||||
bottom: bottom,
|
||||
left: left,
|
||||
header: header,
|
||||
footer: footer,
|
||||
gutter: gutter,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from "./page-number";
|
@ -1,53 +0,0 @@
|
||||
// http://officeopenxml.com/WPSectionPgNumType.php
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export enum PageNumberFormat {
|
||||
CARDINAL_TEXT = "cardinalText",
|
||||
DECIMAL = "decimal",
|
||||
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
|
||||
DECIMAL_ENCLOSED_FULL_STOP = "decimalEnclosedFullstop",
|
||||
DECIMAL_ENCLOSED_PAREN = "decimalEnclosedParen",
|
||||
DECIMAL_ZERO = "decimalZero",
|
||||
LOWER_LETTER = "lowerLetter",
|
||||
LOWER_ROMAN = "lowerRoman",
|
||||
NONE = "none",
|
||||
ORDINAL_TEXT = "ordinalText",
|
||||
UPPER_LETTER = "upperLetter",
|
||||
UPPER_ROMAN = "upperRoman",
|
||||
DECIMAL_FULL_WIDTH = "decimalFullWidth",
|
||||
}
|
||||
|
||||
export enum PageNumberSeparator {
|
||||
COLON = "colon",
|
||||
EM_DASH = "emDash",
|
||||
EN_DASH = "endash",
|
||||
HYPHEN = "hyphen",
|
||||
PERIOD = "period",
|
||||
}
|
||||
|
||||
export interface IPageNumberTypeAttributes {
|
||||
readonly start?: number;
|
||||
readonly formatType?: PageNumberFormat;
|
||||
readonly separator?: PageNumberSeparator;
|
||||
}
|
||||
|
||||
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
start: "w:start",
|
||||
formatType: "w:fmt",
|
||||
separator: "w:chapSep",
|
||||
};
|
||||
}
|
||||
|
||||
export class PageNumberType extends XmlComponent {
|
||||
constructor(start?: number, numberFormat?: PageNumberFormat, separator?: PageNumberSeparator) {
|
||||
super("w:pgNumType");
|
||||
this.root.push(
|
||||
new PageNumberTypeAttributes({
|
||||
start: start,
|
||||
formatType: numberFormat,
|
||||
separator: separator,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from "./page-size";
|
||||
export * from "./page-size-attributes";
|
@ -1,20 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export enum PageOrientation {
|
||||
PORTRAIT = "portrait",
|
||||
LANDSCAPE = "landscape",
|
||||
}
|
||||
|
||||
export interface IPageSizeAttributes {
|
||||
readonly width?: number;
|
||||
readonly height?: number;
|
||||
readonly orientation?: PageOrientation;
|
||||
}
|
||||
|
||||
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
width: "w:w",
|
||||
height: "w:h",
|
||||
orientation: "w:orient",
|
||||
};
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PageOrientation, PageSizeAttributes } from "./page-size-attributes";
|
||||
|
||||
export class PageSize extends XmlComponent {
|
||||
constructor(width: number, height: number, orientation: PageOrientation) {
|
||||
super("w:pgSz");
|
||||
|
||||
const flip = orientation === PageOrientation.LANDSCAPE;
|
||||
|
||||
this.root.push(
|
||||
new PageSizeAttributes({
|
||||
width: flip ? height : width,
|
||||
height: flip ? width : height,
|
||||
orientation: orientation,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import { decimalNumber, twipsMeasureValue } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:complexType name="CT_Columns">
|
||||
// <xsd:sequence minOccurs="0">
|
||||
// <xsd:element name="col" type="CT_Column" maxOccurs="45"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="equalWidth" type="s:ST_OnOff" use="optional"/>
|
||||
// <xsd:attribute name="space" type="s:ST_TwipsMeasure" use="optional" default="720"/>
|
||||
// <xsd:attribute name="num" type="ST_DecimalNumber" use="optional" default="1"/>
|
||||
// <xsd:attribute name="sep" type="s:ST_OnOff" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
export interface IColumnsAttributes {
|
||||
readonly space?: number | string;
|
||||
readonly count?: number;
|
||||
readonly separate?: boolean;
|
||||
readonly equalWidth?: boolean;
|
||||
}
|
||||
|
||||
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
space: "w:space",
|
||||
count: "w:num",
|
||||
separate: "w:sep",
|
||||
equalWidth: "w:equalWidth",
|
||||
};
|
||||
}
|
||||
|
||||
export class Columns extends XmlComponent {
|
||||
constructor({ space, count, separate, equalWidth }: IColumnsAttributes) {
|
||||
super("w:cols");
|
||||
this.root.push(
|
||||
new ColumnsAttributes({
|
||||
space: space === undefined ? undefined : twipsMeasureValue(space),
|
||||
count: count === undefined ? undefined : decimalNumber(count),
|
||||
separate,
|
||||
equalWidth,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
import { decimalNumber } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// not implemented
|
||||
// <xsd:simpleType name="ST_DocGrid">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="default"/>
|
||||
// <xsd:enumeration value="lines"/>
|
||||
// <xsd:enumeration value="linesAndChars"/>
|
||||
// <xsd:enumeration value="snapToChars"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
|
||||
// <xsd:complexType name="CT_DocGrid">
|
||||
// <xsd:attribute name="type" type="ST_DocGrid"/>
|
||||
// <xsd:attribute name="linePitch" type="ST_DecimalNumber"/>
|
||||
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
|
||||
// </xsd:complexType>
|
||||
export interface IDocGridAttributesProperties {
|
||||
readonly linePitch?: number;
|
||||
}
|
||||
|
||||
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||
protected readonly xmlKeys = {
|
||||
linePitch: "w:linePitch",
|
||||
};
|
||||
}
|
||||
|
||||
export class DocumentGrid extends XmlComponent {
|
||||
constructor(linePitch: number) {
|
||||
super("w:docGrid");
|
||||
this.root.push(
|
||||
new DocGridAttributes({
|
||||
linePitch: decimalNumber(linePitch),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./header-footer-reference";
|
||||
|
||||
describe("HeaderFooterReference", () => {
|
||||
it("#constructor (footer)", () => {
|
||||
const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
|
||||
type: HeaderFooterReferenceType.DEFAULT,
|
||||
id: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:footerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("#constructor (header)", () => {
|
||||
const header = new HeaderFooterReference(HeaderFooterType.HEADER, {
|
||||
type: HeaderFooterReferenceType.DEFAULT,
|
||||
id: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(header);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:headerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create without a type", () => {
|
||||
const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
|
||||
id: 1,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(footer);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:footerReference": {
|
||||
_attr: {
|
||||
"r:id": "rId1",
|
||||
"w:type": "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,65 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_HdrFtr">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="even"/>
|
||||
// <xsd:enumeration value="default"/>
|
||||
// <xsd:enumeration value="first"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum HeaderFooterReferenceType {
|
||||
DEFAULT = "default",
|
||||
FIRST = "first",
|
||||
EVEN = "even",
|
||||
}
|
||||
|
||||
// </xsd:complexType>
|
||||
// <xsd:group name="EG_HdrFtrReferences">
|
||||
// <xsd:choice>
|
||||
// <xsd:element name="headerReference" type="CT_HdrFtrRef" minOccurs="0"/>
|
||||
// <xsd:element name="footerReference" type="CT_HdrFtrRef" minOccurs="0"/>
|
||||
// </xsd:choice>
|
||||
// </xsd:group>
|
||||
|
||||
// <xsd:complexType name="CT_HdrFtrRef">
|
||||
// <xsd:complexContent>
|
||||
// <xsd:extension base="CT_Rel">
|
||||
// <xsd:attribute name="type" type="ST_HdrFtr" use="required"/>
|
||||
// </xsd:extension>
|
||||
// </xsd:complexContent>
|
||||
|
||||
// <xsd:complexType name="CT_Rel">
|
||||
// <xsd:attribute ref="r:id" use="required"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
export interface IHeaderFooterOptions {
|
||||
readonly type?: HeaderFooterReferenceType;
|
||||
readonly id?: number;
|
||||
}
|
||||
|
||||
class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
readonly id: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
type: "w:type",
|
||||
id: "r:id",
|
||||
};
|
||||
}
|
||||
|
||||
export enum HeaderFooterType {
|
||||
HEADER = "w:headerReference",
|
||||
FOOTER = "w:footerReference",
|
||||
}
|
||||
export class HeaderFooterReference extends XmlComponent {
|
||||
constructor(type: HeaderFooterType, options: IHeaderFooterOptions) {
|
||||
super(type);
|
||||
|
||||
this.root.push(
|
||||
new FooterReferenceAttributes({
|
||||
type: options.type || HeaderFooterReferenceType.DEFAULT,
|
||||
id: `rId${options.id}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
export * from "./columns";
|
||||
export * from "./doc-grid";
|
||||
// export * from "./header-reference";
|
||||
export * from "./page-size";
|
||||
export * from "./page-number";
|
||||
export * from "./page-borders";
|
||||
export * from "./page-margin";
|
||||
export * from "./page-borders";
|
||||
export * from "./line-number";
|
||||
export * from "./section-type";
|
||||
export * from "./header-footer-reference";
|
@ -0,0 +1,53 @@
|
||||
// http://officeopenxml.com/WPsectionLineNumbering.php
|
||||
import { decimalNumber, twipsMeasureValue } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_LineNumberRestart">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="newPage"/>
|
||||
// <xsd:enumeration value="newSection"/>
|
||||
// <xsd:enumeration value="continuous"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum LineNumberRestartFormat {
|
||||
NEW_PAGE = "newPage",
|
||||
NEW_SECTION = "newSection",
|
||||
CONTINUOUS = "continuous",
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_LineNumber">
|
||||
// <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
|
||||
// <xsd:attribute name="start" type="ST_DecimalNumber" use="optional" default="1"/>
|
||||
// <xsd:attribute name="distance" type="s:ST_TwipsMeasure" use="optional"/>
|
||||
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
export interface ILineNumberAttributes {
|
||||
readonly countBy?: number;
|
||||
readonly start?: number;
|
||||
readonly restart?: LineNumberRestartFormat;
|
||||
readonly distance?: number | string;
|
||||
}
|
||||
|
||||
export class LineNumberAttributes extends XmlAttributeComponent<ILineNumberAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
countBy: "w:countBy",
|
||||
start: "w:start",
|
||||
restart: "w:restart",
|
||||
distance: "w:distance",
|
||||
};
|
||||
}
|
||||
|
||||
export class LineNumberType extends XmlComponent {
|
||||
constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
|
||||
super("w:lnNumType");
|
||||
this.root.push(
|
||||
new LineNumberAttributes({
|
||||
countBy: countBy === undefined ? undefined : decimalNumber(countBy),
|
||||
start: start === undefined ? undefined : decimalNumber(start),
|
||||
restart,
|
||||
distance: distance === undefined ? undefined : twipsMeasureValue(distance),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { BorderStyle } from "file/styles";
|
||||
import { BorderStyle } from "file/border";
|
||||
|
||||
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
|
||||
|
||||
@ -70,22 +70,22 @@ describe("PageBorders", () => {
|
||||
expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage", "w:zOrder": "back" } });
|
||||
expect(tree["w:pgBorders"][1]).to.deep.equal({
|
||||
"w:top": {
|
||||
_attr: { "w:color": "001122", "w:size": 10, "w:val": "doubleWave" },
|
||||
_attr: { "w:color": "001122", "w:sz": 10, "w:val": "doubleWave" },
|
||||
},
|
||||
});
|
||||
expect(tree["w:pgBorders"][2]).to.deep.equal({
|
||||
"w:right": {
|
||||
_attr: { "w:color": "223344", "w:size": 20, "w:val": "double" },
|
||||
"w:left": {
|
||||
_attr: { "w:color": "889900", "w:sz": 40, "w:val": "dotted" },
|
||||
},
|
||||
});
|
||||
expect(tree["w:pgBorders"][3]).to.deep.equal({
|
||||
"w:bottom": {
|
||||
_attr: { "w:color": "556677", "w:size": 30, "w:val": "single" },
|
||||
_attr: { "w:color": "556677", "w:sz": 30, "w:val": "single" },
|
||||
},
|
||||
});
|
||||
expect(tree["w:pgBorders"][4]).to.deep.equal({
|
||||
"w:left": {
|
||||
_attr: { "w:color": "889900", "w:size": 40, "w:val": "dotted" },
|
||||
"w:right": {
|
||||
_attr: { "w:color": "223344", "w:sz": 20, "w:val": "double" },
|
||||
},
|
||||
});
|
||||
});
|
@ -0,0 +1,106 @@
|
||||
// http://officeopenxml.com/WPsectionBorders.php
|
||||
import { BorderElement, IBorderOptions } from "file/border";
|
||||
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_PageBorderDisplay">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="allPages"/>
|
||||
// <xsd:enumeration value="firstPage"/>
|
||||
// <xsd:enumeration value="notFirstPage"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderDisplay {
|
||||
ALL_PAGES = "allPages",
|
||||
FIRST_PAGE = "firstPage",
|
||||
NOT_FIRST_PAGE = "notFirstPage",
|
||||
}
|
||||
|
||||
// <xsd:simpleType name="ST_PageBorderOffset">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="page"/>
|
||||
// <xsd:enumeration value="text"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderOffsetFrom {
|
||||
PAGE = "page",
|
||||
TEXT = "text",
|
||||
}
|
||||
|
||||
// <xsd:simpleType name="ST_PageBorderZOrder">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="front"/>
|
||||
// <xsd:enumeration value="back"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageBorderZOrder {
|
||||
BACK = "back",
|
||||
FRONT = "front",
|
||||
}
|
||||
|
||||
export interface IPageBorderAttributes {
|
||||
readonly display?: PageBorderDisplay;
|
||||
readonly offsetFrom?: PageBorderOffsetFrom;
|
||||
readonly zOrder?: PageBorderZOrder;
|
||||
}
|
||||
|
||||
export interface IPageBordersOptions {
|
||||
readonly pageBorders?: IPageBorderAttributes;
|
||||
readonly pageBorderTop?: IBorderOptions;
|
||||
readonly pageBorderRight?: IBorderOptions;
|
||||
readonly pageBorderBottom?: IBorderOptions;
|
||||
readonly pageBorderLeft?: IBorderOptions;
|
||||
}
|
||||
|
||||
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
display: "w:display",
|
||||
offsetFrom: "w:offsetFrom",
|
||||
zOrder: "w:zOrder",
|
||||
};
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_PageBorders">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="top" type="CT_TopPageBorder" minOccurs="0"/>
|
||||
// <xsd:element name="left" type="CT_PageBorder" minOccurs="0"/>
|
||||
// <xsd:element name="bottom" type="CT_BottomPageBorder" minOccurs="0"/>
|
||||
// <xsd:element name="right" type="CT_PageBorder" minOccurs="0"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="zOrder" type="ST_PageBorderZOrder" use="optional" default="front"/>
|
||||
// <xsd:attribute name="display" type="ST_PageBorderDisplay" use="optional"/>
|
||||
// <xsd:attribute name="offsetFrom" type="ST_PageBorderOffset" use="optional" default="text"/>
|
||||
// </xsd:complexType>
|
||||
export class PageBorders extends IgnoreIfEmptyXmlComponent {
|
||||
constructor(options?: IPageBordersOptions) {
|
||||
super("w:pgBorders");
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.pageBorders) {
|
||||
this.root.push(
|
||||
new PageBordersAttributes({
|
||||
display: options.pageBorders.display,
|
||||
offsetFrom: options.pageBorders.offsetFrom,
|
||||
zOrder: options.pageBorders.zOrder,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
this.root.push(new PageBordersAttributes({}));
|
||||
}
|
||||
|
||||
if (options.pageBorderTop) {
|
||||
this.root.push(new BorderElement("w:top", options.pageBorderTop));
|
||||
}
|
||||
if (options.pageBorderLeft) {
|
||||
this.root.push(new BorderElement("w:left", options.pageBorderLeft));
|
||||
}
|
||||
if (options.pageBorderBottom) {
|
||||
this.root.push(new BorderElement("w:bottom", options.pageBorderBottom));
|
||||
}
|
||||
if (options.pageBorderRight) {
|
||||
this.root.push(new BorderElement("w:right", options.pageBorderRight));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import { signedTwipsMeasureValue, twipsMeasureValue } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:complexType name="CT_PageMar">
|
||||
// <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="right" type="s:ST_TwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="bottom" type="ST_SignedTwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="left" type="s:ST_TwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="header" type="s:ST_TwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/>
|
||||
// <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/>
|
||||
// </xsd:complexType>
|
||||
export interface IPageMarginAttributes {
|
||||
readonly top?: number | string;
|
||||
readonly right?: number | string;
|
||||
readonly bottom?: number | string;
|
||||
readonly left?: number | string;
|
||||
readonly header?: number | string;
|
||||
readonly footer?: number | string;
|
||||
readonly gutter?: number | string;
|
||||
}
|
||||
|
||||
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
top: "w:top",
|
||||
right: "w:right",
|
||||
bottom: "w:bottom",
|
||||
left: "w:left",
|
||||
header: "w:header",
|
||||
footer: "w:footer",
|
||||
gutter: "w:gutter",
|
||||
};
|
||||
}
|
||||
|
||||
export class PageMargin extends XmlComponent {
|
||||
constructor(
|
||||
top: number | string,
|
||||
right: number | string,
|
||||
bottom: number | string,
|
||||
left: number | string,
|
||||
header: number | string,
|
||||
footer: number | string,
|
||||
gutter: number | string,
|
||||
) {
|
||||
super("w:pgMar");
|
||||
this.root.push(
|
||||
new PageMarginAttributes({
|
||||
top: signedTwipsMeasureValue(top),
|
||||
right: twipsMeasureValue(right),
|
||||
bottom: signedTwipsMeasureValue(bottom),
|
||||
left: twipsMeasureValue(left),
|
||||
header: twipsMeasureValue(header),
|
||||
footer: twipsMeasureValue(footer),
|
||||
gutter: twipsMeasureValue(gutter),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
// http://officeopenxml.com/WPSectionPgNumType.php
|
||||
import { NumberFormat } from "file/shared/number-format";
|
||||
import { decimalNumber } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_ChapterSep">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="hyphen"/>
|
||||
// <xsd:enumeration value="period"/>
|
||||
// <xsd:enumeration value="colon"/>
|
||||
// <xsd:enumeration value="emDash"/>
|
||||
// <xsd:enumeration value="enDash"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageNumberSeparator {
|
||||
HYPHEN = "hyphen",
|
||||
PERIOD = "period",
|
||||
COLON = "colon",
|
||||
EM_DASH = "emDash",
|
||||
EN_DASH = "endash",
|
||||
}
|
||||
|
||||
export interface IPageNumberTypeAttributes {
|
||||
readonly start?: number;
|
||||
readonly formatType?: NumberFormat;
|
||||
readonly separator?: PageNumberSeparator;
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_PageNumber">
|
||||
// <xsd:attribute name="fmt" type="ST_NumberFormat" use="optional" default="decimal"/>
|
||||
// <xsd:attribute name="start" type="ST_DecimalNumber" use="optional"/>
|
||||
// <xsd:attribute name="chapStyle" type="ST_DecimalNumber" use="optional"/>
|
||||
// <xsd:attribute name="chapSep" type="ST_ChapterSep" use="optional" default="hyphen"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
start: "w:start",
|
||||
formatType: "w:fmt",
|
||||
separator: "w:chapSep",
|
||||
};
|
||||
}
|
||||
export class PageNumberType extends XmlComponent {
|
||||
constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
|
||||
super("w:pgNumType");
|
||||
this.root.push(
|
||||
new PageNumberTypeAttributes({
|
||||
start: start === undefined ? undefined : decimalNumber(start),
|
||||
formatType,
|
||||
separator,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -2,8 +2,7 @@ import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { PageSize } from "./page-size";
|
||||
import { PageOrientation } from "./page-size-attributes";
|
||||
import { PageOrientation, PageSize } from "./page-size";
|
||||
|
||||
describe("PageSize", () => {
|
||||
describe("#constructor()", () => {
|
@ -0,0 +1,52 @@
|
||||
import { twipsMeasureValue } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_PageOrientation">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="portrait"/>
|
||||
// <xsd:enumeration value="landscape"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum PageOrientation {
|
||||
PORTRAIT = "portrait",
|
||||
LANDSCAPE = "landscape",
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_PageSz">
|
||||
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
|
||||
// <xsd:attribute name="h" type="s:ST_TwipsMeasure"/>
|
||||
// <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/>
|
||||
// <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
export interface IPageSizeAttributes {
|
||||
readonly width?: number | string;
|
||||
readonly height?: number | string;
|
||||
readonly orientation?: PageOrientation;
|
||||
}
|
||||
|
||||
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||
protected readonly xmlKeys = {
|
||||
width: "w:w",
|
||||
height: "w:h",
|
||||
orientation: "w:orient",
|
||||
};
|
||||
}
|
||||
|
||||
export class PageSize extends XmlComponent {
|
||||
constructor(width: number | string, height: number | string, orientation: PageOrientation) {
|
||||
super("w:pgSz");
|
||||
|
||||
const flip = orientation === PageOrientation.LANDSCAPE;
|
||||
|
||||
const widthTwips = twipsMeasureValue(width);
|
||||
const heightTwips = twipsMeasureValue(height);
|
||||
|
||||
this.root.push(
|
||||
new PageSizeAttributes({
|
||||
width: flip ? heightTwips : widthTwips,
|
||||
height: flip ? widthTwips : heightTwips,
|
||||
orientation: orientation,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { Type } from "./section-type";
|
||||
import { SectionType } from "./section-type-attributes";
|
||||
import { SectionType, Type } from "./section-type";
|
||||
|
||||
describe("Type", () => {
|
||||
it("should create with even page section type", () => {
|
@ -0,0 +1,37 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_SectionMark">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="nextPage"/>
|
||||
// <xsd:enumeration value="nextColumn"/>
|
||||
// <xsd:enumeration value="continuous"/>
|
||||
// <xsd:enumeration value="evenPage"/>
|
||||
// <xsd:enumeration value="oddPage"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
export enum SectionType {
|
||||
NEXT_PAGE = "nextPage",
|
||||
NEXT_COLUMN = "nextColumn",
|
||||
CONTINUOUS = "continuous",
|
||||
EVEN_PAGE = "evenPage",
|
||||
ODD_PAGE = "oddPage",
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_SectType">
|
||||
// <xsd:attribute name="val" type="ST_SectionMark"/>
|
||||
// </xsd:complexType>
|
||||
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||
readonly val: SectionType;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
val: "w:val",
|
||||
};
|
||||
}
|
||||
|
||||
export class Type extends XmlComponent {
|
||||
constructor(value: SectionType) {
|
||||
super("w:type");
|
||||
this.root.push(new SectionTypeAttributes({ val: value }));
|
||||
}
|
||||
}
|
@ -5,13 +5,30 @@ import { Formatter } from "export/formatter";
|
||||
import { FooterWrapper } from "file/footer-wrapper";
|
||||
import { HeaderWrapper } from "file/header-wrapper";
|
||||
import { Media } from "file/media";
|
||||
import { LineNumberRestartFormat } from "./line-number";
|
||||
import { NumberFormat } from "file/shared/number-format";
|
||||
import { VerticalAlign } from "file/vertical-align";
|
||||
|
||||
import { PageBorderOffsetFrom } from "./page-border";
|
||||
import { PageNumberFormat } from "./page-number";
|
||||
import { SectionProperties } from "./section-properties";
|
||||
import { SectionType } from "./type/section-type-attributes";
|
||||
import { SectionVerticalAlignValue } from "./vertical-align";
|
||||
import { PageOrientation } from "./properties";
|
||||
import { LineNumberRestartFormat } from "./properties/line-number";
|
||||
import { PageBorderOffsetFrom } from "./properties/page-borders";
|
||||
import { SectionType } from "./properties/section-type";
|
||||
import { sectionMarginDefaults, sectionPageSizeDefaults, SectionProperties } from "./section-properties";
|
||||
|
||||
const DEFAULT_MARGINS = {
|
||||
"w:bottom": sectionMarginDefaults.BOTTOM,
|
||||
"w:footer": sectionMarginDefaults.FOOTER,
|
||||
"w:top": sectionMarginDefaults.TOP,
|
||||
"w:right": sectionMarginDefaults.RIGHT,
|
||||
"w:left": sectionMarginDefaults.LEFT,
|
||||
"w:header": sectionMarginDefaults.HEADER,
|
||||
"w:gutter": sectionMarginDefaults.GUTTER,
|
||||
};
|
||||
|
||||
const PAGE_SIZE_DEFAULTS = {
|
||||
"w:h": sectionPageSizeDefaults.HEIGHT,
|
||||
"w:orient": sectionPageSizeDefaults.ORIENTATION,
|
||||
"w:w": sectionPageSizeDefaults.WIDTH,
|
||||
};
|
||||
|
||||
describe("SectionProperties", () => {
|
||||
describe("#constructor()", () => {
|
||||
@ -21,26 +38,27 @@ describe("SectionProperties", () => {
|
||||
const properties = new SectionProperties({
|
||||
page: {
|
||||
size: {
|
||||
width: 11906,
|
||||
height: 16838,
|
||||
width: 1190,
|
||||
height: 1680,
|
||||
orientation: PageOrientation.PORTRAIT,
|
||||
},
|
||||
margin: {
|
||||
top: convertInchesToTwip(1),
|
||||
right: convertInchesToTwip(1),
|
||||
bottom: convertInchesToTwip(1),
|
||||
left: convertInchesToTwip(1),
|
||||
header: 708,
|
||||
footer: 708,
|
||||
gutter: 0,
|
||||
top: "2in",
|
||||
right: "2in",
|
||||
bottom: "2in",
|
||||
left: "2in",
|
||||
header: 808,
|
||||
footer: 808,
|
||||
gutter: 10,
|
||||
},
|
||||
pageNumbers: {
|
||||
start: 10,
|
||||
formatType: PageNumberFormat.CARDINAL_TEXT,
|
||||
formatType: NumberFormat.CARDINAL_TEXT,
|
||||
},
|
||||
},
|
||||
column: {
|
||||
space: 708,
|
||||
count: 1,
|
||||
space: 208,
|
||||
count: 2,
|
||||
separate: true,
|
||||
},
|
||||
grid: {
|
||||
@ -53,7 +71,7 @@ describe("SectionProperties", () => {
|
||||
even: new FooterWrapper(media, 200),
|
||||
},
|
||||
titlePage: true,
|
||||
verticalAlign: SectionVerticalAlignValue.TOP,
|
||||
verticalAlign: VerticalAlign.TOP,
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(properties);
|
||||
@ -62,25 +80,25 @@ describe("SectionProperties", () => {
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:headerReference": { _attr: { "r:id": "rId100", "w:type": "default" } } });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({ "w:footerReference": { _attr: { "r:id": "rId200", "w:type": "even" } } });
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 1680, "w:w": 1190, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][3]).to.deep.equal({
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
"w:bottom": "2in",
|
||||
"w:footer": 808,
|
||||
"w:top": "2in",
|
||||
"w:right": "2in",
|
||||
"w:left": "2in",
|
||||
"w:header": 808,
|
||||
"w:gutter": 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:pgNumType": { _attr: { "w:fmt": "cardinalText", "w:start": 10 } } });
|
||||
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": true, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:cols": { _attr: { "w:space": 208, "w:sep": true, "w:num": 2 } } });
|
||||
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:vAlign": { _attr: { "w:val": "top" } } });
|
||||
expect(tree["w:sectPr"][7]).to.deep.equal({ "w:titlePg": { _attr: { "w:val": "1" } } });
|
||||
expect(tree["w:sectPr"][7]).to.deep.equal({ "w:titlePg": {} });
|
||||
expect(tree["w:sectPr"][8]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
|
||||
});
|
||||
|
||||
@ -89,22 +107,12 @@ describe("SectionProperties", () => {
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: PAGE_SIZE_DEFAULTS } });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
"w:pgMar": { _attr: DEFAULT_MARGINS },
|
||||
});
|
||||
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
|
||||
// expect(tree["w:sectPr"][3]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
|
||||
});
|
||||
|
||||
it("should create section properties with changed options", () => {
|
||||
@ -118,17 +126,12 @@ describe("SectionProperties", () => {
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: PAGE_SIZE_DEFAULTS } });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
...DEFAULT_MARGINS,
|
||||
"w:top": 0,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -145,17 +148,12 @@ describe("SectionProperties", () => {
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: PAGE_SIZE_DEFAULTS } });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
...DEFAULT_MARGINS,
|
||||
"w:bottom": 0,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -167,24 +165,25 @@ describe("SectionProperties", () => {
|
||||
size: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
orientation: PageOrientation.LANDSCAPE,
|
||||
},
|
||||
},
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 0, "w:w": 0, "w:orient": "portrait" } } });
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({
|
||||
"w:pgSz": {
|
||||
_attr: {
|
||||
"w:h": 0,
|
||||
"w:orient": PageOrientation.LANDSCAPE,
|
||||
"w:w": 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
_attr: DEFAULT_MARGINS,
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -211,7 +210,7 @@ describe("SectionProperties", () => {
|
||||
const properties = new SectionProperties({
|
||||
page: {
|
||||
pageNumbers: {
|
||||
formatType: PageNumberFormat.UPPER_ROMAN,
|
||||
formatType: NumberFormat.UPPER_ROMAN,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -1,29 +1,21 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
// tslint:disable: no-unnecessary-initializer
|
||||
|
||||
import { convertInchesToTwip } from "convenience-functions";
|
||||
import { FooterWrapper } from "file/footer-wrapper";
|
||||
import { HeaderWrapper } from "file/header-wrapper";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { VerticalAlign, VerticalAlignElement } from "file/vertical-align";
|
||||
import { OnOffElement, XmlComponent } from "file/xml-components";
|
||||
|
||||
import { Columns } from "./columns/columns";
|
||||
import { DocumentGrid } from "./doc-grid/doc-grid";
|
||||
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
|
||||
import { FooterReferenceType } from "./footer-reference";
|
||||
import { FooterReference } from "./footer-reference/footer-reference";
|
||||
import { HeaderReferenceType } from "./header-reference";
|
||||
import { HeaderReference } from "./header-reference/header-reference";
|
||||
import { ILineNumberAttributes, LineNumberType } from "./line-number";
|
||||
import { IPageBordersOptions, PageBorders } from "./page-border";
|
||||
import { PageMargin } from "./page-margin/page-margin";
|
||||
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
|
||||
import { IPageNumberTypeAttributes, PageNumberType } from "./page-number";
|
||||
import { PageSize } from "./page-size/page-size";
|
||||
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
|
||||
import { TitlePage } from "./title-page/title-page";
|
||||
import { Type } from "./type/section-type";
|
||||
import { SectionType } from "./type/section-type-attributes";
|
||||
import { SectionVerticalAlign, SectionVerticalAlignValue } from "./vertical-align";
|
||||
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
|
||||
|
||||
import { Columns, IColumnsAttributes } from "./properties/columns";
|
||||
import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
|
||||
import { ILineNumberAttributes, LineNumberType } from "./properties/line-number";
|
||||
import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
|
||||
import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
|
||||
import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
|
||||
import { IPageSizeAttributes, PageOrientation, PageSize } from "./properties/page-size";
|
||||
import { SectionType, Type } from "./properties/section-type";
|
||||
|
||||
export interface IHeaderFooterGroup<T> {
|
||||
readonly default?: T;
|
||||
@ -43,53 +35,93 @@ export interface ISectionPropertiesOptions {
|
||||
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
|
||||
readonly lineNumbers?: ILineNumberAttributes;
|
||||
readonly titlePage?: boolean;
|
||||
readonly verticalAlign?: SectionVerticalAlignValue;
|
||||
readonly column?: {
|
||||
readonly space?: number;
|
||||
readonly count?: number;
|
||||
readonly separate?: boolean;
|
||||
};
|
||||
readonly verticalAlign?: VerticalAlign;
|
||||
readonly column?: IColumnsAttributes;
|
||||
readonly type?: SectionType;
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_SectPr">
|
||||
// <xsd:sequence>
|
||||
// <xsd:group ref="EG_HdrFtrReferences" minOccurs="0" maxOccurs="6"/>
|
||||
// <xsd:group ref="EG_SectPrContents" minOccurs="0"/>
|
||||
// <xsd:element name="sectPrChange" type="CT_SectPrChange" minOccurs="0"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attributeGroup ref="AG_SectPrAttributes"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
// <xsd:group name="EG_SectPrContents">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="footnotePr" type="CT_FtnProps" minOccurs="0"/>
|
||||
// <xsd:element name="endnotePr" type="CT_EdnProps" minOccurs="0"/>
|
||||
// <xsd:element name="type" type="CT_SectType" minOccurs="0"/>
|
||||
// <xsd:element name="pgSz" type="CT_PageSz" minOccurs="0"/>
|
||||
// <xsd:element name="pgMar" type="CT_PageMar" minOccurs="0"/>
|
||||
// <xsd:element name="paperSrc" type="CT_PaperSource" minOccurs="0"/>
|
||||
// <xsd:element name="pgBorders" type="CT_PageBorders" minOccurs="0"/>
|
||||
// <xsd:element name="lnNumType" type="CT_LineNumber" minOccurs="0"/>
|
||||
// <xsd:element name="pgNumType" type="CT_PageNumber" minOccurs="0"/>
|
||||
// <xsd:element name="cols" type="CT_Columns" minOccurs="0"/>
|
||||
// <xsd:element name="formProt" type="CT_OnOff" minOccurs="0"/>
|
||||
// <xsd:element name="vAlign" type="CT_VerticalJc" minOccurs="0"/>
|
||||
// <xsd:element name="noEndnote" type="CT_OnOff" minOccurs="0"/>
|
||||
// <xsd:element name="titlePg" type="CT_OnOff" minOccurs="0"/>
|
||||
// <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0"/>
|
||||
// <xsd:element name="bidi" type="CT_OnOff" minOccurs="0"/>
|
||||
// <xsd:element name="rtlGutter" type="CT_OnOff" minOccurs="0"/>
|
||||
// <xsd:element name="docGrid" type="CT_DocGrid" minOccurs="0"/>
|
||||
// <xsd:element name="printerSettings" type="CT_Rel" minOccurs="0"/>
|
||||
// </xsd:sequence>
|
||||
// </xsd:group>
|
||||
|
||||
export const sectionMarginDefaults = {
|
||||
TOP: "1in",
|
||||
RIGHT: "1in",
|
||||
BOTTOM: "1in",
|
||||
LEFT: "1in",
|
||||
HEADER: 708,
|
||||
FOOTER: 708,
|
||||
GUTTER: 0,
|
||||
};
|
||||
|
||||
export const sectionPageSizeDefaults = {
|
||||
WIDTH: 11906,
|
||||
HEIGHT: 16838,
|
||||
ORIENTATION: PageOrientation.PORTRAIT,
|
||||
};
|
||||
|
||||
export class SectionProperties extends XmlComponent {
|
||||
constructor({
|
||||
page: {
|
||||
size: { width = 11906, height = 16838, orientation = PageOrientation.PORTRAIT } = {},
|
||||
size: {
|
||||
width = sectionPageSizeDefaults.WIDTH,
|
||||
height = sectionPageSizeDefaults.HEIGHT,
|
||||
orientation = sectionPageSizeDefaults.ORIENTATION,
|
||||
} = {},
|
||||
margin: {
|
||||
top = convertInchesToTwip(1),
|
||||
right = convertInchesToTwip(1),
|
||||
bottom = convertInchesToTwip(1),
|
||||
left = convertInchesToTwip(1),
|
||||
header = 708,
|
||||
footer = 708,
|
||||
gutter = 0,
|
||||
} = {},
|
||||
pageNumbers: {
|
||||
start: pageNumberStart = undefined,
|
||||
formatType: pageNumberFormatType = undefined,
|
||||
separator: pageNumberSeparator = undefined,
|
||||
} = {},
|
||||
borders: {
|
||||
pageBorders = undefined,
|
||||
pageBorderTop = undefined,
|
||||
pageBorderRight = undefined,
|
||||
pageBorderBottom = undefined,
|
||||
pageBorderLeft = undefined,
|
||||
top = sectionMarginDefaults.TOP,
|
||||
right = sectionMarginDefaults.RIGHT,
|
||||
bottom = sectionMarginDefaults.BOTTOM,
|
||||
left = sectionMarginDefaults.LEFT,
|
||||
header = sectionMarginDefaults.HEADER,
|
||||
footer = sectionMarginDefaults.FOOTER,
|
||||
gutter = sectionMarginDefaults.GUTTER,
|
||||
} = {},
|
||||
pageNumbers = {},
|
||||
borders,
|
||||
} = {},
|
||||
grid: { linePitch = 360 } = {},
|
||||
headerWrapperGroup = {},
|
||||
footerWrapperGroup = {},
|
||||
lineNumbers: { countBy: lineNumberCountBy, start: lineNumberStart, restart: lineNumberRestart, distance: lineNumberDistance } = {},
|
||||
titlePage = false,
|
||||
lineNumbers,
|
||||
titlePage,
|
||||
verticalAlign,
|
||||
column: { space = 708, count = 1, separate = false } = {},
|
||||
column,
|
||||
type,
|
||||
}: ISectionPropertiesOptions = {}) {
|
||||
super("w:sectPr");
|
||||
|
||||
this.addHeaders(headerWrapperGroup);
|
||||
this.addFooters(footerWrapperGroup);
|
||||
this.addHeaderFooterGroup(HeaderFooterType.HEADER, headerWrapperGroup);
|
||||
this.addHeaderFooterGroup(HeaderFooterType.FOOTER, footerWrapperGroup);
|
||||
|
||||
if (type) {
|
||||
this.root.push(new Type(type));
|
||||
@ -98,90 +130,58 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(new PageSize(width, height, orientation));
|
||||
this.root.push(new PageMargin(top, right, bottom, left, header, footer, gutter));
|
||||
|
||||
if (pageBorders || pageBorderTop || pageBorderRight || pageBorderBottom || pageBorderLeft) {
|
||||
this.root.push(
|
||||
new PageBorders({
|
||||
pageBorders: pageBorders,
|
||||
pageBorderTop: pageBorderTop,
|
||||
pageBorderRight: pageBorderRight,
|
||||
pageBorderBottom: pageBorderBottom,
|
||||
pageBorderLeft: pageBorderLeft,
|
||||
}),
|
||||
);
|
||||
if (borders) {
|
||||
this.root.push(new PageBorders(borders));
|
||||
}
|
||||
|
||||
if (lineNumberCountBy || lineNumberStart || lineNumberRestart || lineNumberDistance) {
|
||||
this.root.push(new LineNumberType(lineNumberCountBy, lineNumberStart, lineNumberRestart, lineNumberDistance));
|
||||
if (lineNumbers) {
|
||||
this.root.push(new LineNumberType(lineNumbers));
|
||||
}
|
||||
|
||||
this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType, pageNumberSeparator));
|
||||
this.root.push(new PageNumberType(pageNumbers));
|
||||
|
||||
this.root.push(new Columns(space, count, separate));
|
||||
if (column) {
|
||||
this.root.push(new Columns(column));
|
||||
}
|
||||
|
||||
if (verticalAlign) {
|
||||
this.root.push(new SectionVerticalAlign(verticalAlign));
|
||||
this.root.push(new VerticalAlignElement(verticalAlign));
|
||||
}
|
||||
|
||||
if (titlePage) {
|
||||
this.root.push(new TitlePage());
|
||||
if (titlePage !== undefined) {
|
||||
this.root.push(new OnOffElement("w:titlePg", titlePage));
|
||||
}
|
||||
|
||||
this.root.push(new DocumentGrid(linePitch));
|
||||
}
|
||||
|
||||
private addHeaders(headers: IHeaderFooterGroup<HeaderWrapper>): void {
|
||||
if (headers.default) {
|
||||
private addHeaderFooterGroup(
|
||||
type: HeaderFooterType,
|
||||
group: IHeaderFooterGroup<HeaderWrapper> | IHeaderFooterGroup<FooterWrapper>,
|
||||
): void {
|
||||
if (group.default) {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.DEFAULT,
|
||||
headerId: headers.default.View.ReferenceId,
|
||||
new HeaderFooterReference(type, {
|
||||
type: HeaderFooterReferenceType.DEFAULT,
|
||||
id: group.default.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (headers.first) {
|
||||
if (group.first) {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.FIRST,
|
||||
headerId: headers.first.View.ReferenceId,
|
||||
new HeaderFooterReference(type, {
|
||||
type: HeaderFooterReferenceType.FIRST,
|
||||
id: group.first.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (headers.even) {
|
||||
if (group.even) {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.EVEN,
|
||||
headerId: headers.even.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private addFooters(footers: IHeaderFooterGroup<FooterWrapper>): void {
|
||||
if (footers.default) {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.DEFAULT,
|
||||
footerId: footers.default.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (footers.first) {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.FIRST,
|
||||
footerId: footers.first.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (footers.even) {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.EVEN,
|
||||
footerId: footers.even.View.ReferenceId,
|
||||
new HeaderFooterReference(type, {
|
||||
type: HeaderFooterReferenceType.EVEN,
|
||||
id: group.even.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export class TitlePageAttributes extends XmlAttributeComponent<{
|
||||
readonly value: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
value: "w:val",
|
||||
};
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { TitlePage } from "./title-page";
|
||||
|
||||
describe("PageSize", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create title page property for different first page header", () => {
|
||||
const properties = new TitlePage();
|
||||
const tree = new Formatter().format(properties);
|
||||
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:titlePg"]);
|
||||
expect(tree["w:titlePg"]).to.deep.equal({ _attr: { "w:val": "1" } });
|
||||
});
|
||||
});
|
||||
});
|
@ -1,13 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { TitlePageAttributes } from "./title-page-attributes";
|
||||
|
||||
export class TitlePage extends XmlComponent {
|
||||
constructor() {
|
||||
super("w:titlePg");
|
||||
this.root.push(
|
||||
new TitlePageAttributes({
|
||||
value: "1",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from "./section-type";
|
||||
export * from "./section-type-attributes";
|
@ -1,17 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export enum SectionType {
|
||||
CONTINUOUS = "continuous",
|
||||
EVEN_PAGE = "evenPage",
|
||||
NEXT_COLUMN = "nextColumn",
|
||||
NEXT_PAGE = "nextPage",
|
||||
ODD_PAGE = "oddPage",
|
||||
}
|
||||
|
||||
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||
readonly val: SectionType;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
val: "w:val",
|
||||
};
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { SectionType, SectionTypeAttributes } from "./section-type-attributes";
|
||||
|
||||
export class Type extends XmlComponent {
|
||||
constructor(value: SectionType) {
|
||||
super("w:type");
|
||||
this.root.push(new SectionTypeAttributes({ val: value }));
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from "./vertical-align";
|
||||
export * from "./vertical-align-attributes";
|
@ -1,10 +0,0 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
import { SectionVerticalAlignValue } from "./vertical-align";
|
||||
|
||||
export class SectionVerticalAlignAttributes extends XmlAttributeComponent<{
|
||||
readonly verticalAlign?: SectionVerticalAlignValue;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
verticalAlign: "w:val",
|
||||
};
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { SectionVerticalAlignAttributes } from "./vertical-align-attributes";
|
||||
|
||||
export enum SectionVerticalAlignValue {
|
||||
BOTH = "both",
|
||||
BOTTOM = "bottom",
|
||||
CENTER = "center",
|
||||
TOP = "top",
|
||||
}
|
||||
|
||||
export class SectionVerticalAlign extends XmlComponent {
|
||||
constructor(value: SectionVerticalAlignValue) {
|
||||
super("w:vAlign");
|
||||
this.root.push(new SectionVerticalAlignAttributes({ verticalAlign: value }));
|
||||
}
|
||||
}
|
@ -34,8 +34,8 @@ describe("DocumentBackground", () => {
|
||||
const documentBackground = new DocumentBackground({
|
||||
color: "ffff00",
|
||||
themeColor: "test",
|
||||
themeShade: "test",
|
||||
themeTint: "test",
|
||||
themeShade: "0A",
|
||||
themeTint: "0B",
|
||||
});
|
||||
const tree = new Formatter().format(documentBackground);
|
||||
expect(tree).to.deep.equal({
|
||||
@ -43,8 +43,8 @@ describe("DocumentBackground", () => {
|
||||
_attr: {
|
||||
"w:color": "ffff00",
|
||||
"w:themeColor": "test",
|
||||
"w:themeShade": "test",
|
||||
"w:themeTint": "test",
|
||||
"w:themeShade": "0A",
|
||||
"w:themeTint": "0B",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -1,7 +1,30 @@
|
||||
// http://officeopenxml.com/WPdocument.php
|
||||
// http://www.datypic.com/sc/ooxml/e-w_background-1.html
|
||||
import { hexColorValue, uCharHexNumber } from "file/values";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_ThemeColor">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="dark1"/>
|
||||
// <xsd:enumeration value="light1"/>
|
||||
// <xsd:enumeration value="dark2"/>
|
||||
// <xsd:enumeration value="light2"/>
|
||||
// <xsd:enumeration value="accent1"/>
|
||||
// <xsd:enumeration value="accent2"/>
|
||||
// <xsd:enumeration value="accent3"/>
|
||||
// <xsd:enumeration value="accent4"/>
|
||||
// <xsd:enumeration value="accent5"/>
|
||||
// <xsd:enumeration value="accent6"/>
|
||||
// <xsd:enumeration value="hyperlink"/>
|
||||
// <xsd:enumeration value="followedHyperlink"/>
|
||||
// <xsd:enumeration value="none"/>
|
||||
// <xsd:enumeration value="background1"/>
|
||||
// <xsd:enumeration value="text1"/>
|
||||
// <xsd:enumeration value="background2"/>
|
||||
// <xsd:enumeration value="text2"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
|
||||
export class DocumentBackgroundAttributes extends XmlAttributeComponent<{
|
||||
readonly color: string;
|
||||
readonly themeColor?: string;
|
||||
@ -23,16 +46,32 @@ export interface IDocumentBackgroundOptions {
|
||||
readonly themeTint?: string;
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_Background">
|
||||
// <xsd:sequence>
|
||||
// <xsd:sequence maxOccurs="unbounded">
|
||||
// <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:vml" minOccurs="0"
|
||||
// maxOccurs="unbounded"/>
|
||||
// <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:office:office"
|
||||
// minOccurs="0" maxOccurs="unbounded"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:element name="drawing" type="CT_Drawing" minOccurs="0"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/>
|
||||
// <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/>
|
||||
// <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/>
|
||||
// <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
|
||||
export class DocumentBackground extends XmlComponent {
|
||||
constructor(options: IDocumentBackgroundOptions) {
|
||||
super("w:background");
|
||||
|
||||
this.root.push(
|
||||
new DocumentBackgroundAttributes({
|
||||
color: options.color ? options.color : "FFFFFF",
|
||||
color: hexColorValue(options.color ? options.color : "FFFFFF"),
|
||||
themeColor: options.themeColor,
|
||||
themeShade: options.themeShade,
|
||||
themeTint: options.themeTint,
|
||||
themeShade: options.themeShade === undefined ? undefined : uCharHexNumber(options.themeShade),
|
||||
themeTint: options.themeTint === undefined ? undefined : uCharHexNumber(options.themeTint),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -11,6 +11,25 @@ export interface IDocumentOptions {
|
||||
readonly background: IDocumentBackgroundOptions;
|
||||
}
|
||||
|
||||
// <xsd:element name="document" type="CT_Document"/>
|
||||
//
|
||||
// <xsd:complexType name="CT_Document">
|
||||
// <xsd:complexContent>
|
||||
// <xsd:extension base="CT_DocumentBase">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="body" type="CT_Body" minOccurs="0" maxOccurs="1"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="conformance" type="s:ST_ConformanceClass"/>
|
||||
// <xsd:attribute ref="mc:Ignorable" use="optional" />
|
||||
// </xsd:extension>
|
||||
// </xsd:complexContent>
|
||||
// </xsd:complexType>
|
||||
//
|
||||
// <xsd:complexType name="CT_DocumentBase">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="background" type="CT_Background" minOccurs="0"/>
|
||||
// </xsd:sequence>
|
||||
// </xsd:complexType>
|
||||
export class Document extends XmlComponent {
|
||||
private readonly body: Body;
|
||||
|
||||
@ -50,8 +69,4 @@ export class Document extends XmlComponent {
|
||||
public get Body(): Body {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public getTablesOfContents(): TableOfContents[] {
|
||||
return this.body.getTablesOfContents();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,31 @@ import { Extent } from "./../extent/extent";
|
||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||
import { AnchorAttributes } from "./anchor-attributes";
|
||||
|
||||
// <xsd:complexType name="CT_Anchor">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="simplePos" type="a:CT_Point2D"/>
|
||||
// <xsd:element name="positionH" type="CT_PosH"/>
|
||||
// <xsd:element name="positionV" type="CT_PosV"/>
|
||||
// <xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
||||
// <xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
// <xsd:group ref="EG_WrapType"/>
|
||||
// <xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
// <xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
// minOccurs="0" maxOccurs="1"/>
|
||||
// <xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="simplePos" type="xsd:boolean"/>
|
||||
// <xsd:attribute name="relativeHeight" type="xsd:unsignedInt" use="required"/>
|
||||
// <xsd:attribute name="behindDoc" type="xsd:boolean" use="required"/>
|
||||
// <xsd:attribute name="locked" type="xsd:boolean" use="required"/>
|
||||
// <xsd:attribute name="layoutInCell" type="xsd:boolean" use="required"/>
|
||||
// <xsd:attribute name="hidden" type="xsd:boolean" use="optional"/>
|
||||
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||
// </xsd:complexType>
|
||||
export class Anchor extends XmlComponent {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
|
||||
super("wp:anchor");
|
||||
|
@ -15,6 +15,13 @@ export interface IDrawingOptions {
|
||||
readonly floating?: IFloating;
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_Drawing">
|
||||
// <xsd:choice minOccurs="1" maxOccurs="unbounded">
|
||||
// <xsd:element ref="wp:anchor" minOccurs="0"/>
|
||||
// <xsd:element ref="wp:inline" minOccurs="0"/>
|
||||
// </xsd:choice>
|
||||
// </xsd:complexType>
|
||||
|
||||
export class Drawing extends XmlComponent {
|
||||
private readonly inline: Inline;
|
||||
|
||||
@ -28,8 +35,4 @@ export class Drawing extends XmlComponent {
|
||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
||||
}
|
||||
}
|
||||
|
||||
public scale(factorX: number, factorY: number): void {
|
||||
this.inline.scale(factorX, factorY);
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,4 @@ export class Extent extends XmlComponent {
|
||||
|
||||
this.root.push(this.attributes);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.attributes.set({
|
||||
cx: x,
|
||||
cy: y,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -49,5 +49,9 @@ describe("HorizontalPosition", () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should require one of align or offset", () => {
|
||||
expect(() => new HorizontalPosition({})).to.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -49,5 +49,9 @@ describe("VerticalPosition", () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should require one of align or offset", () => {
|
||||
expect(() => new VerticalPosition({})).to.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -20,8 +20,4 @@ export class GraphicData extends XmlComponent {
|
||||
|
||||
this.root.push(this.pic);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.pic.setXY(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ import { PicAttributes } from "./pic-attributes";
|
||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||
|
||||
export class Pic extends XmlComponent {
|
||||
private readonly shapeProperties: ShapeProperties;
|
||||
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
||||
super("pic:pic");
|
||||
|
||||
@ -19,14 +17,8 @@ export class Pic extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.shapeProperties = new ShapeProperties(transform);
|
||||
|
||||
this.root.push(new NonVisualPicProperties());
|
||||
this.root.push(new BlipFill(mediaData));
|
||||
this.root.push(new ShapeProperties(transform));
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.shapeProperties.setXY(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,4 @@ export class Extents extends XmlComponent {
|
||||
|
||||
this.root.push(this.attributes);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.attributes.set({
|
||||
cx: x,
|
||||
cy: y,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,4 @@ export class Form extends XmlComponent {
|
||||
this.root.push(new Offset());
|
||||
this.root.push(this.extents);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.extents.setXY(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,4 @@ export class ShapeProperties extends XmlComponent {
|
||||
// this.root.push(new NoFill());
|
||||
// this.root.push(new Outline());
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.form.setXY(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,4 @@ export class Graphic extends XmlComponent {
|
||||
|
||||
this.root.push(this.data);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.data.setXY(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,25 @@ import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-propert
|
||||
import { Graphic } from "./../inline/graphic";
|
||||
import { InlineAttributes } from "./inline-attributes";
|
||||
|
||||
// <xsd:complexType name="CT_Inline">
|
||||
// <xsd:sequence>
|
||||
// <xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
||||
// <xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
// <xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
// <xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
// minOccurs="0" maxOccurs="1"/>
|
||||
// <xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
// </xsd:sequence>
|
||||
// <xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
// <xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
export class Inline extends XmlComponent {
|
||||
private readonly extent: Extent;
|
||||
private readonly graphic: Graphic;
|
||||
|
||||
constructor(mediaData: IMediaData, private readonly transform: IMediaDataTransformation) {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
||||
super("wp:inline");
|
||||
|
||||
this.root.push(
|
||||
@ -33,12 +47,4 @@ export class Inline extends XmlComponent {
|
||||
this.root.push(new GraphicFrameProperties());
|
||||
this.root.push(this.graphic);
|
||||
}
|
||||
|
||||
public scale(factorX: number, factorY: number): void {
|
||||
const newX = Math.round(this.transform.emus.x * factorX);
|
||||
const newY = Math.round(this.transform.emus.y * factorY);
|
||||
|
||||
this.extent.setXY(newX, newY);
|
||||
this.graphic.setXY(newX, newY);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { sectionMarginDefaults, sectionPageSizeDefaults } from "./document";
|
||||
|
||||
import { File } from "./file";
|
||||
import { Footer, Header } from "./header";
|
||||
import { Paragraph } from "./paragraph";
|
||||
|
||||
const PAGE_SIZE_DEFAULTS = {
|
||||
"w:h": sectionPageSizeDefaults.HEIGHT,
|
||||
"w:orient": sectionPageSizeDefaults.ORIENTATION,
|
||||
"w:w": sectionPageSizeDefaults.WIDTH,
|
||||
};
|
||||
|
||||
describe("File", () => {
|
||||
describe("#constructor", () => {
|
||||
it("should create with correct headers and footers", () => {
|
||||
@ -114,23 +121,19 @@ describe("File", () => {
|
||||
"w:sectPr": [
|
||||
{
|
||||
"w:pgSz": {
|
||||
_attr: {
|
||||
"w:h": 16838,
|
||||
"w:orient": "portrait",
|
||||
"w:w": 11906,
|
||||
},
|
||||
_attr: PAGE_SIZE_DEFAULTS,
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:pgMar": {
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:gutter": 0,
|
||||
"w:header": 708,
|
||||
"w:left": 1440,
|
||||
"w:right": 1440,
|
||||
"w:top": 1440,
|
||||
"w:bottom": sectionMarginDefaults.BOTTOM,
|
||||
"w:footer": sectionMarginDefaults.FOOTER,
|
||||
"w:gutter": sectionMarginDefaults.GUTTER,
|
||||
"w:header": sectionMarginDefaults.HEADER,
|
||||
"w:left": sectionMarginDefaults.LEFT,
|
||||
"w:right": sectionMarginDefaults.RIGHT,
|
||||
"w:top": sectionMarginDefaults.TOP,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -139,15 +142,15 @@ describe("File", () => {
|
||||
_attr: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:cols": {
|
||||
_attr: {
|
||||
"w:num": 1,
|
||||
"w:sep": false,
|
||||
"w:space": 708,
|
||||
},
|
||||
},
|
||||
},
|
||||
// {
|
||||
// "w:cols": {
|
||||
// _attr: {
|
||||
// "w:num": 1,
|
||||
// "w:sep": false,
|
||||
// "w:space": 708,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
{
|
||||
"w:docGrid": {
|
||||
_attr: {
|
||||
@ -162,20 +165,6 @@ describe("File", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#addTrackRevisionsFeature", () => {
|
||||
it("should call the underlying document's add", () => {
|
||||
const file = new File({
|
||||
features: {
|
||||
trackRevisions: true,
|
||||
},
|
||||
sections: [],
|
||||
});
|
||||
|
||||
// tslint:disable-next-line: no-unused-expression no-string-literal
|
||||
expect(file.Settings["trackRevisions"]).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#createFootnote", () => {
|
||||
it("should create footnote", () => {
|
||||
const wrapper = new File({
|
||||
|
@ -3,7 +3,7 @@ import { ContentTypes } from "./content-types/content-types";
|
||||
import { CoreProperties, IPropertiesOptions } from "./core-properties";
|
||||
import { CustomProperties } from "./custom-properties";
|
||||
import { DocumentWrapper } from "./document-wrapper";
|
||||
import { FooterReferenceType, HeaderReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties";
|
||||
import { HeaderFooterReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties";
|
||||
import { IFileProperties } from "./file-properties";
|
||||
import { FooterWrapper, IDocumentFooter } from "./footer-wrapper";
|
||||
import { FootnotesWrapper } from "./footnotes-wrapper";
|
||||
@ -78,6 +78,8 @@ export class File {
|
||||
this.settings = new Settings({
|
||||
compatabilityModeVersion: options.compatabilityModeVersion,
|
||||
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
|
||||
trackRevisions: options.features?.trackRevisions,
|
||||
updateFields: options.features?.updateFields,
|
||||
});
|
||||
|
||||
this.media = fileProperties.template && fileProperties.template.media ? fileProperties.template.media : new Media();
|
||||
@ -132,18 +134,6 @@ export class File {
|
||||
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.features) {
|
||||
if (options.features.trackRevisions) {
|
||||
this.settings.addTrackRevisions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public verifyUpdateFields(): void {
|
||||
if (this.documentWrapper.View.getTablesOfContents().length) {
|
||||
this.settings.addUpdateFields();
|
||||
}
|
||||
}
|
||||
|
||||
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
|
||||
@ -188,7 +178,7 @@ export class File {
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void {
|
||||
private addHeaderToDocument(header: HeaderWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
|
||||
this.headers.push({ header, type });
|
||||
this.documentWrapper.Relationships.createRelationship(
|
||||
header.View.ReferenceId,
|
||||
@ -198,7 +188,7 @@ export class File {
|
||||
this.contentTypes.addHeader(this.headers.length);
|
||||
}
|
||||
|
||||
private addFooterToDocument(footer: FooterWrapper, type: FooterReferenceType = FooterReferenceType.DEFAULT): void {
|
||||
private addFooterToDocument(footer: FooterWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
|
||||
this.footers.push({ footer, type });
|
||||
this.documentWrapper.Relationships.createRelationship(
|
||||
footer.View.ReferenceId,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
import { FooterReferenceType } from "./document";
|
||||
import { HeaderFooterReferenceType } from "./document";
|
||||
import { IViewWrapper } from "./document-wrapper";
|
||||
import { Footer } from "./footer/footer";
|
||||
import { Media } from "./media";
|
||||
@ -10,7 +10,7 @@ import { Table } from "./table";
|
||||
|
||||
export interface IDocumentFooter {
|
||||
readonly footer: FooterWrapper;
|
||||
readonly type: FooterReferenceType;
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
}
|
||||
|
||||
export class FooterWrapper implements IViewWrapper {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Run } from "file/paragraph/run";
|
||||
import { Style } from "file/paragraph/run/style";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export class FootNoteReferenceRunAttributes extends XmlAttributeComponent<{
|
||||
@ -24,9 +23,7 @@ export class FootnoteReference extends XmlComponent {
|
||||
|
||||
export class FootnoteReferenceRun extends Run {
|
||||
constructor(id: number) {
|
||||
super({});
|
||||
|
||||
this.properties.push(new Style("FootnoteReference"));
|
||||
super({ style: "FootnoteReference" });
|
||||
|
||||
this.root.push(new FootnoteReference(id));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
import { HeaderReferenceType } from "./document";
|
||||
import { HeaderFooterReferenceType } from "./document";
|
||||
import { IViewWrapper } from "./document-wrapper";
|
||||
import { Header } from "./header/header";
|
||||
import { Media } from "./media";
|
||||
@ -10,7 +10,7 @@ import { Table } from "./table";
|
||||
|
||||
export interface IDocumentHeader {
|
||||
readonly header: HeaderWrapper;
|
||||
readonly type: HeaderReferenceType;
|
||||
readonly type: HeaderFooterReferenceType;
|
||||
}
|
||||
|
||||
export class HeaderWrapper implements IViewWrapper {
|
||||
|
@ -6,6 +6,7 @@ export * from "./numbering";
|
||||
export * from "./media";
|
||||
export * from "./drawing";
|
||||
export * from "./document";
|
||||
export * from "./shading";
|
||||
export * from "./styles";
|
||||
export * from "./table-of-contents";
|
||||
export * from "./xml-components";
|
||||
@ -15,3 +16,6 @@ export * from "./header";
|
||||
export * from "./footnotes";
|
||||
export * from "./track-revision";
|
||||
export * from "./shared";
|
||||
export * from "./border";
|
||||
export * from "./values";
|
||||
export * from "./vertical-align";
|
||||
|
@ -5,7 +5,7 @@ import { EMPTY_OBJECT } from "file/xml-components";
|
||||
|
||||
import { AlignmentType, EmphasisMarkType, TabStopPosition } from "../paragraph";
|
||||
import { UnderlineType } from "../paragraph/run/underline";
|
||||
import { ShadingType } from "../table";
|
||||
import { ShadingType } from "../shading";
|
||||
import { AbstractNumbering } from "./abstract-numbering";
|
||||
import { LevelFormat, LevelSuffix } from "./level";
|
||||
|
||||
@ -351,7 +351,7 @@ describe("AbstractNumbering", () => {
|
||||
]);
|
||||
const tree = new Formatter().format(abstractNumbering);
|
||||
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
|
||||
"w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
|
||||
"w:rPr": [{ "w:smallCaps": {} }],
|
||||
});
|
||||
});
|
||||
|
||||
@ -370,7 +370,7 @@ describe("AbstractNumbering", () => {
|
||||
]);
|
||||
const tree = new Formatter().format(abstractNumbering);
|
||||
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
|
||||
"w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
|
||||
"w:rPr": [{ "w:caps": {} }],
|
||||
});
|
||||
});
|
||||
|
||||
@ -390,7 +390,7 @@ describe("AbstractNumbering", () => {
|
||||
|
||||
const tree = new Formatter().format(abstractNumbering);
|
||||
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
|
||||
"w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
|
||||
"w:rPr": [{ "w:strike": {} }],
|
||||
});
|
||||
});
|
||||
|
||||
@ -409,7 +409,7 @@ describe("AbstractNumbering", () => {
|
||||
]);
|
||||
const tree = new Formatter().format(abstractNumbering);
|
||||
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
|
||||
"w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
|
||||
"w:rPr": [{ "w:dstrike": {} }],
|
||||
});
|
||||
});
|
||||
|
||||
@ -515,17 +515,17 @@ describe("AbstractNumbering", () => {
|
||||
const boldTests = [
|
||||
{
|
||||
bold: true,
|
||||
expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:b": {} }, { "w:bCs": {} }],
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
boldComplexScript: true,
|
||||
expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:b": {} }, { "w:bCs": {} }],
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
boldComplexScript: false,
|
||||
expected: [{ "w:b": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:b": {} }],
|
||||
},
|
||||
];
|
||||
boldTests.forEach(({ bold, boldComplexScript, expected }) => {
|
||||
@ -548,17 +548,17 @@ describe("AbstractNumbering", () => {
|
||||
const italicsTests = [
|
||||
{
|
||||
italics: true,
|
||||
expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:i": {} }, { "w:iCs": {} }],
|
||||
},
|
||||
{
|
||||
italics: true,
|
||||
italicsComplexScript: true,
|
||||
expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:i": {} }, { "w:iCs": {} }],
|
||||
},
|
||||
{
|
||||
italics: true,
|
||||
italicsComplexScript: false,
|
||||
expected: [{ "w:i": { _attr: { "w:val": true } } }],
|
||||
expected: [{ "w:i": {} }],
|
||||
},
|
||||
];
|
||||
italicsTests.forEach(({ italics, italicsComplexScript, expected }) => {
|
||||
@ -617,37 +617,13 @@ describe("AbstractNumbering", () => {
|
||||
});
|
||||
|
||||
const shadingTests = [
|
||||
{
|
||||
shadow: {
|
||||
type: ShadingType.PERCENT_10,
|
||||
fill: "00FFFF",
|
||||
color: "FF0000",
|
||||
},
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
|
||||
},
|
||||
{
|
||||
shading: {
|
||||
type: ShadingType.PERCENT_10,
|
||||
fill: "00FFFF",
|
||||
color: "FF0000",
|
||||
type: ShadingType.DIAGONAL_STRIPE,
|
||||
fill: "006622",
|
||||
color: "0000FF",
|
||||
},
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
|
||||
},
|
||||
{
|
||||
shading: {
|
||||
type: ShadingType.PERCENT_10,
|
||||
fill: "00FFFF",
|
||||
color: "FF0000",
|
||||
},
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
|
||||
},
|
||||
{
|
||||
shading: {
|
||||
type: ShadingType.PERCENT_10,
|
||||
fill: "00FFFF",
|
||||
color: "FF0000",
|
||||
},
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "diagStripe", "w:fill": "006622", "w:color": "0000FF" } } }],
|
||||
},
|
||||
{
|
||||
shading: {
|
||||
@ -658,15 +634,15 @@ describe("AbstractNumbering", () => {
|
||||
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
|
||||
},
|
||||
];
|
||||
shadingTests.forEach(({ shadow, shading, expected }) => {
|
||||
it("#shadow correctly", () => {
|
||||
shadingTests.forEach(({ shading, expected }) => {
|
||||
it("#shade correctly", () => {
|
||||
const abstractNumbering = new AbstractNumbering(1, [
|
||||
{
|
||||
level: 0,
|
||||
format: LevelFormat.LOWER_ROMAN,
|
||||
text: "%0.",
|
||||
style: {
|
||||
run: { shadow, shading },
|
||||
run: { shading },
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user