#269 Text Frame (Text Box)
This commit is contained in:
8
.nycrc
8
.nycrc
@ -1,9 +1,9 @@
|
||||
{
|
||||
"check-coverage": true,
|
||||
"lines": 98.66,
|
||||
"functions": 97.06,
|
||||
"branches": 95.51,
|
||||
"statements": 98.67,
|
||||
"lines": 98.67,
|
||||
"functions": 97.08,
|
||||
"branches": 95.6,
|
||||
"statements": 98.68,
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
|
71
demo/60-text-frame.ts
Normal file
71
demo/60-text-frame.ts
Normal file
@ -0,0 +1,71 @@
|
||||
// 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";
|
||||
|
||||
const doc = new Document();
|
||||
|
||||
doc.addSection({
|
||||
properties: {},
|
||||
children: [
|
||||
new Paragraph({
|
||||
frame: {
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 3000,
|
||||
},
|
||||
width: 4000,
|
||||
height: 1000,
|
||||
anchor: {
|
||||
horizontal: FrameAnchorType.MARGIN,
|
||||
vertical: FrameAnchorType.MARGIN,
|
||||
},
|
||||
alignment: {
|
||||
x: HorizontalPositionAlign.CENTER,
|
||||
y: VerticalPositionAlign.TOP,
|
||||
},
|
||||
},
|
||||
border: {
|
||||
top: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
size: 6,
|
||||
},
|
||||
bottom: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
size: 6,
|
||||
},
|
||||
left: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
size: 6,
|
||||
},
|
||||
right: {
|
||||
color: "auto",
|
||||
space: 1,
|
||||
value: "single",
|
||||
size: 6,
|
||||
},
|
||||
},
|
||||
children: [
|
||||
new TextRun("Hello World"),
|
||||
new TextRun({
|
||||
text: "Foo Bar",
|
||||
bold: true,
|
||||
}),
|
||||
new TextRun({
|
||||
text: "\tGithub is the best",
|
||||
bold: true,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
Packer.toBuffer(doc).then((buffer) => {
|
||||
fs.writeFileSync("My Document.docx", buffer);
|
||||
});
|
@ -4,7 +4,7 @@
|
||||
|
||||
- Simple, declarative API
|
||||
- 50+ usage examples
|
||||
- Battle tested, mature, 97%+ coverage
|
||||
- Battle tested, mature, 98%+ coverage
|
||||
|
||||
[GitHub](https://github.com/dolanmiu/docx)
|
||||
[Get Started](#Welcome)
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { VerticalPositionAlign } from "file/shared/alignment";
|
||||
|
||||
import { Align } from "./align";
|
||||
import { VerticalPositionAlign } from "./floating-position";
|
||||
|
||||
describe("Align", () => {
|
||||
describe("#constructor()", () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// http://officeopenxml.com/drwPicFloating-position.php
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "file/shared/alignment";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "./floating-position";
|
||||
|
||||
export class Align extends XmlComponent {
|
||||
constructor(value: HorizontalPositionAlign | VerticalPositionAlign) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
// http://officeopenxml.com/drwPicFloating-position.php
|
||||
// http://officeopenxml.com/drwPicFloating.php
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "file/shared/alignment";
|
||||
|
||||
import { ITextWrapping } from "../text-wrap";
|
||||
|
||||
export enum HorizontalPositionRelativeFrom {
|
||||
@ -24,22 +26,6 @@ export enum VerticalPositionRelativeFrom {
|
||||
TOP_MARGIN = "topMargin",
|
||||
}
|
||||
|
||||
export enum HorizontalPositionAlign {
|
||||
CENTER = "center",
|
||||
INSIDE = "inside",
|
||||
LEFT = "left",
|
||||
OUTSIDE = "outside",
|
||||
RIGHT = "right",
|
||||
}
|
||||
|
||||
export enum VerticalPositionAlign {
|
||||
BOTTOM = "bottom",
|
||||
CENTER = "center",
|
||||
INSIDE = "inside",
|
||||
OUTSIDE = "outside",
|
||||
TOP = "top",
|
||||
}
|
||||
|
||||
export interface IHorizontalPositionOptions {
|
||||
readonly relative?: HorizontalPositionRelativeFrom;
|
||||
readonly align?: HorizontalPositionAlign;
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { HorizontalPositionAlign } from "file/shared/alignment";
|
||||
|
||||
import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from "./floating-position";
|
||||
import { HorizontalPositionRelativeFrom } from "./floating-position";
|
||||
import { HorizontalPosition } from "./horizontal-position";
|
||||
|
||||
describe("HorizontalPosition", () => {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { VerticalPositionAlign } from "file/shared/alignment";
|
||||
|
||||
import { VerticalPositionAlign, VerticalPositionRelativeFrom } from "./floating-position";
|
||||
import { VerticalPositionRelativeFrom } from "./floating-position";
|
||||
import { VerticalPosition } from "./vertical-position";
|
||||
|
||||
describe("VerticalPosition", () => {
|
||||
|
@ -14,3 +14,4 @@ export * from "./footer-wrapper";
|
||||
export * from "./header";
|
||||
export * from "./footnotes";
|
||||
export * from "./track-revision";
|
||||
export * from "./shared";
|
||||
|
86
src/file/paragraph/frame/frame-properties.spec.ts
Normal file
86
src/file/paragraph/frame/frame-properties.spec.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "file/shared";
|
||||
|
||||
import { FrameAnchorType, FrameProperties } from "./frame-properties";
|
||||
|
||||
describe("FrameProperties", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const currentFrameProperties = new FrameProperties({
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 3000,
|
||||
},
|
||||
width: 4000,
|
||||
height: 1000,
|
||||
anchor: {
|
||||
horizontal: FrameAnchorType.MARGIN,
|
||||
vertical: FrameAnchorType.MARGIN,
|
||||
},
|
||||
alignment: {
|
||||
x: HorizontalPositionAlign.CENTER,
|
||||
y: VerticalPositionAlign.TOP,
|
||||
},
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(currentFrameProperties);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:framePr": {
|
||||
_attr: {
|
||||
"w:h": 1000,
|
||||
"w:hAnchor": "margin",
|
||||
"w:vAnchor": "margin",
|
||||
"w:w": 4000,
|
||||
"w:x": 1000,
|
||||
"w:xAlign": "center",
|
||||
"w:y": 3000,
|
||||
"w:yAlign": "top",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create with the space attribute", () => {
|
||||
const currentFrameProperties = new FrameProperties({
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 3000,
|
||||
},
|
||||
width: 4000,
|
||||
height: 1000,
|
||||
anchor: {
|
||||
horizontal: FrameAnchorType.MARGIN,
|
||||
vertical: FrameAnchorType.MARGIN,
|
||||
},
|
||||
alignment: {
|
||||
x: HorizontalPositionAlign.CENTER,
|
||||
y: VerticalPositionAlign.TOP,
|
||||
},
|
||||
space: {
|
||||
horizontal: 100,
|
||||
vertical: 200,
|
||||
},
|
||||
});
|
||||
|
||||
const tree = new Formatter().format(currentFrameProperties);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:framePr": {
|
||||
_attr: {
|
||||
"w:h": 1000,
|
||||
"w:hAnchor": "margin",
|
||||
"w:vAnchor": "margin",
|
||||
"w:w": 4000,
|
||||
"w:x": 1000,
|
||||
"w:xAlign": "center",
|
||||
"w:y": 3000,
|
||||
"w:yAlign": "top",
|
||||
"w:hSpace": 100,
|
||||
"w:vSpace": 200,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
111
src/file/paragraph/frame/frame-properties.ts
Normal file
111
src/file/paragraph/frame/frame-properties.ts
Normal file
@ -0,0 +1,111 @@
|
||||
// http://officeopenxml.com/WPparagraph-textFrames.php
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "file/shared/alignment";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export enum DropCapType {
|
||||
NONE = "none",
|
||||
DROP = "drop",
|
||||
MARGIN = "margin",
|
||||
}
|
||||
|
||||
export enum FrameAnchorType {
|
||||
MARGIN = "margin",
|
||||
PAGE = "page",
|
||||
TEXT = "text",
|
||||
}
|
||||
|
||||
export enum FrameWrap {
|
||||
AROUND = "around",
|
||||
AUTO = "auto",
|
||||
NONE = "none",
|
||||
NOT_BESIDE = "notBeside",
|
||||
THROUGH = "through",
|
||||
TIGHT = "tight",
|
||||
}
|
||||
|
||||
export interface IFrameOptions {
|
||||
readonly anchorLock?: boolean;
|
||||
readonly dropCap?: DropCapType;
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
readonly position: {
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
};
|
||||
readonly wrap?: FrameWrap;
|
||||
readonly lines?: number;
|
||||
readonly anchor: {
|
||||
readonly horizontal: FrameAnchorType;
|
||||
readonly vertical: FrameAnchorType;
|
||||
};
|
||||
readonly space?: {
|
||||
readonly horizontal: number;
|
||||
readonly vertical: number;
|
||||
};
|
||||
readonly rule?: number;
|
||||
readonly alignment: {
|
||||
readonly x: HorizontalPositionAlign;
|
||||
readonly y: VerticalPositionAlign;
|
||||
};
|
||||
}
|
||||
|
||||
export class FramePropertiesAttributes extends XmlAttributeComponent<{
|
||||
readonly anchorLock?: boolean;
|
||||
readonly dropCap?: DropCapType;
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
readonly wrap?: FrameWrap;
|
||||
readonly lines?: number;
|
||||
readonly anchorHorizontal?: FrameAnchorType;
|
||||
readonly anchorVertical?: FrameAnchorType;
|
||||
readonly spaceHorizontal?: number;
|
||||
readonly spaceVertical?: number;
|
||||
readonly rule?: number;
|
||||
readonly alignmentX?: HorizontalPositionAlign;
|
||||
readonly alignmentY?: VerticalPositionAlign;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
anchorLock: "w:anchorLock",
|
||||
dropCap: "w:dropCap",
|
||||
width: "w:w",
|
||||
height: "w:h",
|
||||
x: "w:x",
|
||||
y: "w:y",
|
||||
anchorHorizontal: "w:hAnchor",
|
||||
anchorVertical: "w:vAnchor",
|
||||
spaceHorizontal: "w:hSpace",
|
||||
spaceVertical: "w:vSpace",
|
||||
rule: "w:hRule",
|
||||
alignmentX: "w:xAlign",
|
||||
alignmentY: "w:yAlign",
|
||||
lines: "w:lines",
|
||||
wrap: "w:wrap",
|
||||
};
|
||||
}
|
||||
|
||||
export class FrameProperties extends XmlComponent {
|
||||
constructor(options: IFrameOptions) {
|
||||
super("w:framePr");
|
||||
this.root.push(
|
||||
new FramePropertiesAttributes({
|
||||
anchorLock: options.anchorLock,
|
||||
dropCap: options.dropCap,
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
x: options.position.x,
|
||||
y: options.position.y,
|
||||
anchorHorizontal: options.anchor.horizontal,
|
||||
anchorVertical: options.anchor.vertical,
|
||||
spaceHorizontal: options.space?.horizontal,
|
||||
spaceVertical: options.space?.vertical,
|
||||
rule: options.rule,
|
||||
alignmentX: options.alignment.x,
|
||||
alignmentY: options.alignment.y,
|
||||
lines: options.lines,
|
||||
wrap: options.wrap,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
1
src/file/paragraph/frame/index.ts
Normal file
1
src/file/paragraph/frame/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./frame-properties";
|
@ -4,3 +4,4 @@ export * from "./properties";
|
||||
export * from "./run";
|
||||
export * from "./links";
|
||||
export * from "./math";
|
||||
export * from "./frame";
|
||||
|
@ -7,8 +7,10 @@ import { EMPTY_OBJECT } from "file/xml-components";
|
||||
|
||||
import { IViewWrapper } from "../document-wrapper";
|
||||
import { File } from "../file";
|
||||
import { HorizontalPositionAlign, VerticalPositionAlign } from "../shared";
|
||||
import { ShadingType } from "../table/shading";
|
||||
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
|
||||
import { FrameAnchorType } from "./frame";
|
||||
import { Bookmark, ExternalHyperlink } from "./links";
|
||||
import { Paragraph } from "./paragraph";
|
||||
import { TextRun } from "./run";
|
||||
@ -859,6 +861,52 @@ describe("Paragraph", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#frame", () => {
|
||||
it("should set frame attribute", () => {
|
||||
const paragraph = new Paragraph({
|
||||
frame: {
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 3000,
|
||||
},
|
||||
width: 4000,
|
||||
height: 1000,
|
||||
anchor: {
|
||||
horizontal: FrameAnchorType.MARGIN,
|
||||
vertical: FrameAnchorType.MARGIN,
|
||||
},
|
||||
alignment: {
|
||||
x: HorizontalPositionAlign.CENTER,
|
||||
y: VerticalPositionAlign.TOP,
|
||||
},
|
||||
},
|
||||
});
|
||||
const tree = new Formatter().format(paragraph);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:p": [
|
||||
{
|
||||
"w:pPr": [
|
||||
{
|
||||
"w:framePr": {
|
||||
_attr: {
|
||||
"w:h": 1000,
|
||||
"w:hAnchor": "margin",
|
||||
"w:vAnchor": "margin",
|
||||
"w:w": 4000,
|
||||
"w:x": 1000,
|
||||
"w:xAlign": "center",
|
||||
"w:y": 3000,
|
||||
"w:yAlign": "top",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#prepForXml", () => {
|
||||
it("should set Internal Hyperlink", () => {
|
||||
const paragraph = new Paragraph({
|
||||
|
@ -13,6 +13,7 @@ import { HeadingLevel, Style } from "./formatting/style";
|
||||
import { LeaderType, TabStop, TabStopPosition, TabStopType } from "./formatting/tab-stop";
|
||||
import { NumberProperties } from "./formatting/unordered-list";
|
||||
import { WidowControl } from "./formatting/widow-control";
|
||||
import { FrameProperties, IFrameOptions } from "./frame/frame-properties";
|
||||
import { OutlineLevel } from "./links";
|
||||
import { Shading } from "./run/formatting";
|
||||
|
||||
@ -55,6 +56,7 @@ export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOp
|
||||
readonly color: string;
|
||||
};
|
||||
readonly widowControl?: boolean;
|
||||
readonly frame?: IFrameOptions;
|
||||
}
|
||||
|
||||
export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
|
||||
@ -159,6 +161,10 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
|
||||
if (options.widowControl) {
|
||||
this.push(new WidowControl(options.widowControl));
|
||||
}
|
||||
|
||||
if (options.frame) {
|
||||
this.push(new FrameProperties(options.frame));
|
||||
}
|
||||
}
|
||||
|
||||
public push(item: XmlComponent): void {
|
||||
|
15
src/file/shared/alignment.ts
Normal file
15
src/file/shared/alignment.ts
Normal file
@ -0,0 +1,15 @@
|
||||
export enum HorizontalPositionAlign {
|
||||
CENTER = "center",
|
||||
INSIDE = "inside",
|
||||
LEFT = "left",
|
||||
OUTSIDE = "outside",
|
||||
RIGHT = "right",
|
||||
}
|
||||
|
||||
export enum VerticalPositionAlign {
|
||||
BOTTOM = "bottom",
|
||||
CENTER = "center",
|
||||
INSIDE = "inside",
|
||||
OUTSIDE = "outside",
|
||||
TOP = "top",
|
||||
}
|
1
src/file/shared/index.ts
Normal file
1
src/file/shared/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./alignment";
|
Reference in New Issue
Block a user