diff --git a/demo/61-text-frame.ts b/demo/61-text-frame.ts
index a9460bae878..cd8196e84e9 100644
--- a/demo/61-text-frame.ts
+++ b/demo/61-text-frame.ts
@@ -2,6 +2,7 @@
import * as fs from "fs";
import {
+ AlignmentType,
BorderStyle,
Document,
FrameAnchorType,
@@ -20,6 +21,7 @@ const doc = new Document({
children: [
new Paragraph({
frame: {
+ type: "absolute",
position: {
x: 1000,
y: 3000,
@@ -30,6 +32,54 @@ const doc = new Document({
horizontal: FrameAnchorType.MARGIN,
vertical: FrameAnchorType.MARGIN,
},
+ },
+ border: {
+ top: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ bottom: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ left: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ right: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ },
+ children: [
+ new TextRun("Hello World"),
+ new TextRun({
+ text: "Foo Bar",
+ bold: true,
+ }),
+ new TextRun({
+ children: [new Tab(), "Github is the best"],
+ bold: true,
+ }),
+ ],
+ }),
+ new Paragraph({
+ frame: {
+ type: "alignment",
+ width: 4000,
+ height: 1000,
+ anchor: {
+ horizontal: FrameAnchorType.MARGIN,
+ vertical: FrameAnchorType.MARGIN,
+ },
alignment: {
x: HorizontalPositionAlign.CENTER,
y: VerticalPositionAlign.TOP,
@@ -73,6 +123,59 @@ const doc = new Document({
}),
],
}),
+ new Paragraph({
+ frame: {
+ type: "alignment",
+ width: 4000,
+ height: 1000,
+ anchor: {
+ horizontal: FrameAnchorType.MARGIN,
+ vertical: FrameAnchorType.MARGIN,
+ },
+ alignment: {
+ x: HorizontalPositionAlign.CENTER,
+ y: VerticalPositionAlign.BOTTOM,
+ },
+ },
+ border: {
+ top: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ bottom: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ left: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ right: {
+ color: "auto",
+ space: 1,
+ style: BorderStyle.SINGLE,
+ size: 6,
+ },
+ },
+ alignment: AlignmentType.RIGHT,
+ children: [
+ new TextRun("Hello World"),
+ new TextRun({
+ text: "Foo Bar",
+ bold: true,
+ }),
+ new TextRun({
+ children: [new Tab(), "Github is the best"],
+ bold: true,
+ }),
+ ],
+ }),
],
},
],
diff --git a/src/file/paragraph/frame/frame-properties.spec.ts b/src/file/paragraph/frame/frame-properties.spec.ts
index 5ff7afaef3a..fb6d90b9c6e 100644
--- a/src/file/paragraph/frame/frame-properties.spec.ts
+++ b/src/file/paragraph/frame/frame-properties.spec.ts
@@ -3,154 +3,144 @@ import { describe, expect, it } from "vitest";
import { Formatter } from "@export/formatter";
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared";
-import { FrameAnchorType, FrameProperties } from "./frame-properties";
+import { FrameAnchorType, createFrameProperties } 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,
- },
- });
+describe("createFrameProperties", () => {
+ it("should create", () => {
+ const currentFrameProperties = createFrameProperties({
+ type: "absolute",
+ position: {
+ x: 1000,
+ y: 3000,
+ },
+ width: 4000,
+ height: 1000,
+ anchor: {
+ horizontal: FrameAnchorType.MARGIN,
+ vertical: FrameAnchorType.MARGIN,
+ },
+ });
- 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",
- },
- },
- });
+ 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:y": 3000,
+ },
+ },
});
+ });
- 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,
- },
- });
+ it("should create with the space attribute", () => {
+ const currentFrameProperties = createFrameProperties({
+ type: "absolute",
+ position: {
+ x: 1000,
+ y: 3000,
+ },
+ width: 4000,
+ height: 1000,
+ anchor: {
+ horizontal: FrameAnchorType.MARGIN,
+ vertical: FrameAnchorType.MARGIN,
+ },
+ 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,
- },
- },
- });
+ 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:y": 3000,
+ "w:hSpace": 100,
+ "w:vSpace": 200,
+ },
+ },
});
+ });
- it("should create without x and y", () => {
- const currentFrameProperties = new FrameProperties({
- width: 4000,
- height: 1000,
- anchor: {
- horizontal: FrameAnchorType.MARGIN,
- vertical: FrameAnchorType.MARGIN,
- },
- alignment: {
- x: HorizontalPositionAlign.CENTER,
- y: VerticalPositionAlign.TOP,
- },
- space: {
- horizontal: 100,
- vertical: 200,
- },
- });
+ it("should create without x and y", () => {
+ const currentFrameProperties = createFrameProperties({
+ type: "alignment",
+ 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:xAlign": "center",
- "w:yAlign": "top",
- "w:hSpace": 100,
- "w:vSpace": 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:xAlign": "center",
+ "w:yAlign": "top",
+ "w:hSpace": 100,
+ "w:vSpace": 200,
+ },
+ },
});
+ });
- it("should create without alignments", () => {
- const currentFrameProperties = new FrameProperties({
- position: {
- x: 1000,
- y: 3000,
- },
- width: 4000,
- height: 1000,
- anchor: {
- horizontal: FrameAnchorType.MARGIN,
- vertical: FrameAnchorType.MARGIN,
- },
- space: {
- horizontal: 100,
- vertical: 200,
- },
- });
+ it("should create without alignments", () => {
+ const currentFrameProperties = createFrameProperties({
+ type: "absolute",
+ position: {
+ x: 1000,
+ y: 3000,
+ },
+ width: 4000,
+ height: 1000,
+ anchor: {
+ horizontal: FrameAnchorType.MARGIN,
+ vertical: FrameAnchorType.MARGIN,
+ },
+ 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:y": 3000,
- "w:hSpace": 100,
- "w:vSpace": 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:y": 3000,
+ "w:hSpace": 100,
+ "w:vSpace": 200,
+ },
+ },
});
});
});
diff --git a/src/file/paragraph/frame/frame-properties.ts b/src/file/paragraph/frame/frame-properties.ts
index 28ce7c28611..b72ced9f5fd 100644
--- a/src/file/paragraph/frame/frame-properties.ts
+++ b/src/file/paragraph/frame/frame-properties.ts
@@ -1,7 +1,7 @@
// http://officeopenxml.com/WPparagraph-textFrames.php
import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/alignment";
import { HeightRule } from "@file/table";
-import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
+import { BuilderElement, XmlComponent } from "@file/xml-components";
export const DropCapType = {
NONE: "none",
@@ -44,6 +44,7 @@ interface IBaseFrameOptions {
}
export interface IXYFrameOptions extends IBaseFrameOptions {
+ readonly type: "absolute";
readonly position: {
readonly x: number;
readonly y: number;
@@ -51,6 +52,7 @@ export interface IXYFrameOptions extends IBaseFrameOptions {
}
export interface IAlignmentFrameOptions extends IBaseFrameOptions {
+ readonly type: "alignment";
readonly alignment: {
readonly x: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
readonly y: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
@@ -61,7 +63,24 @@ export interface IAlignmentFrameOptions extends IBaseFrameOptions {
// https://stackoverflow.com/q/46370222/3481582
export type IFrameOptions = IXYFrameOptions | IAlignmentFrameOptions;
-export class FramePropertiesAttributes extends XmlAttributeComponent<{
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+type FramePropertiesAttributes = {
readonly anchorLock?: boolean;
readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType];
readonly width: number;
@@ -77,47 +96,71 @@ export class FramePropertiesAttributes extends XmlAttributeComponent<{
readonly rule?: (typeof HeightRule)[keyof typeof HeightRule];
readonly alignmentX?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
readonly alignmentY?: (typeof VerticalPositionAlign)[keyof typeof 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 {
- public 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 as IXYFrameOptions).position ? (options as IXYFrameOptions).position.x : undefined,
- y: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.y : undefined,
- anchorHorizontal: options.anchor.horizontal,
- anchorVertical: options.anchor.vertical,
- spaceHorizontal: options.space?.horizontal,
- spaceVertical: options.space?.vertical,
- rule: options.rule,
- alignmentX: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.x : undefined,
- alignmentY: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.y : undefined,
- lines: options.lines,
- wrap: options.wrap,
- }),
- );
- }
-}
+export const createFrameProperties = (options: IFrameOptions): XmlComponent =>
+ new BuilderElement({
+ name: "w:framePr",
+ attributes: {
+ anchorLock: {
+ key: "w:anchorLock",
+ value: options.anchorLock,
+ },
+ dropCap: {
+ key: "w:dropCap",
+ value: options.dropCap,
+ },
+ width: {
+ key: "w:w",
+ value: options.width,
+ },
+ height: {
+ key: "w:h",
+ value: options.height,
+ },
+ x: {
+ key: "w:x",
+ value: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.x : undefined,
+ },
+ y: {
+ key: "w:y",
+ value: (options as IXYFrameOptions).position ? (options as IXYFrameOptions).position.y : undefined,
+ },
+ anchorHorizontal: {
+ key: "w:hAnchor",
+ value: options.anchor.horizontal,
+ },
+ anchorVertical: {
+ key: "w:vAnchor",
+ value: options.anchor.vertical,
+ },
+ spaceHorizontal: {
+ key: "w:hSpace",
+ value: options.space?.horizontal,
+ },
+ spaceVertical: {
+ key: "w:vSpace",
+ value: options.space?.vertical,
+ },
+ rule: {
+ key: "w:hRule",
+ value: options.rule,
+ },
+ alignmentX: {
+ key: "w:xAlign",
+ value: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.x : undefined,
+ },
+ alignmentY: {
+ key: "w:yAlign",
+ value: (options as IAlignmentFrameOptions).alignment ? (options as IAlignmentFrameOptions).alignment.y : undefined,
+ },
+ lines: {
+ key: "w:lines",
+ value: options.lines,
+ },
+ wrap: {
+ key: "w:wrap",
+ value: options.wrap,
+ },
+ },
+ });
diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts
index 6e911cd1451..61ac8f78d0a 100644
--- a/src/file/paragraph/paragraph.spec.ts
+++ b/src/file/paragraph/paragraph.spec.ts
@@ -890,10 +890,7 @@ describe("Paragraph", () => {
it("should set frame attribute", () => {
const paragraph = new Paragraph({
frame: {
- position: {
- x: 1000,
- y: 3000,
- },
+ type: "alignment",
width: 4000,
height: 1000,
anchor: {
@@ -918,9 +915,7 @@ describe("Paragraph", () => {
"w:hAnchor": "margin",
"w:vAnchor": "margin",
"w:w": 4000,
- "w:x": 1000,
"w:xAlign": "center",
- "w:y": 3000,
"w:yAlign": "top",
},
},
diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts
index c427717115c..a160de93d50 100644
--- a/src/file/paragraph/properties.ts
+++ b/src/file/paragraph/properties.ts
@@ -13,7 +13,7 @@ import { HeadingLevel, Style } from "./formatting/style";
import { TabStop, TabStopDefinition, TabStopType } from "./formatting/tab-stop";
import { NumberProperties } from "./formatting/unordered-list";
import { WordWrap } from "./formatting/word-wrap";
-import { FrameProperties, IFrameOptions } from "./frame/frame-properties";
+import { createFrameProperties, IFrameOptions } from "./frame/frame-properties";
import { OutlineLevel } from "./links";
import { IRunOptions, RunProperties } from ".";
@@ -116,7 +116,7 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
}
if (options.frame) {
- this.push(new FrameProperties(options.frame));
+ this.push(createFrameProperties(options.frame));
}
if (options.widowControl !== undefined) {