From 7f86385b09d5e609b79be0384e65d41116fd5c36 Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 14 Mar 2021 17:00:42 +0000 Subject: [PATCH 1/3] #269 Text Frame (Text Box) --- .nycrc | 8 +- demo/60-text-frame.ts | 71 +++++++++++ docs/_coverpage.md | 2 +- src/file/drawing/floating/align.spec.ts | 2 +- src/file/drawing/floating/align.ts | 2 +- .../drawing/floating/floating-position.ts | 18 +-- .../floating/horizontal-position.spec.ts | 3 +- .../floating/vertical-position.spec.ts | 3 +- src/file/index.ts | 1 + .../paragraph/frame/frame-properties.spec.ts | 86 ++++++++++++++ src/file/paragraph/frame/frame-properties.ts | 111 ++++++++++++++++++ src/file/paragraph/frame/index.ts | 1 + src/file/paragraph/index.ts | 1 + src/file/paragraph/paragraph.spec.ts | 48 ++++++++ src/file/paragraph/properties.ts | 6 + src/file/shared/alignment.ts | 15 +++ src/file/shared/index.ts | 1 + 17 files changed, 354 insertions(+), 25 deletions(-) create mode 100644 demo/60-text-frame.ts create mode 100644 src/file/paragraph/frame/frame-properties.spec.ts create mode 100644 src/file/paragraph/frame/frame-properties.ts create mode 100644 src/file/paragraph/frame/index.ts create mode 100644 src/file/shared/alignment.ts create mode 100644 src/file/shared/index.ts diff --git a/.nycrc b/.nycrc index 63dce4516c..c521820b91 100644 --- a/.nycrc +++ b/.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" ], diff --git a/demo/60-text-frame.ts b/demo/60-text-frame.ts new file mode 100644 index 0000000000..0759a4e6c7 --- /dev/null +++ b/demo/60-text-frame.ts @@ -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); +}); diff --git a/docs/_coverpage.md b/docs/_coverpage.md index c3db65386d..a2db37dc5f 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -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) diff --git a/src/file/drawing/floating/align.spec.ts b/src/file/drawing/floating/align.spec.ts index 906aa8732f..b181725709 100644 --- a/src/file/drawing/floating/align.spec.ts +++ b/src/file/drawing/floating/align.spec.ts @@ -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()", () => { diff --git a/src/file/drawing/floating/align.ts b/src/file/drawing/floating/align.ts index 2ffa4ac52b..5eba22c6a9 100644 --- a/src/file/drawing/floating/align.ts +++ b/src/file/drawing/floating/align.ts @@ -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) { diff --git a/src/file/drawing/floating/floating-position.ts b/src/file/drawing/floating/floating-position.ts index 6c5ad7f332..82652bbf91 100644 --- a/src/file/drawing/floating/floating-position.ts +++ b/src/file/drawing/floating/floating-position.ts @@ -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; diff --git a/src/file/drawing/floating/horizontal-position.spec.ts b/src/file/drawing/floating/horizontal-position.spec.ts index 6faafb4f7e..705e637dd5 100644 --- a/src/file/drawing/floating/horizontal-position.spec.ts +++ b/src/file/drawing/floating/horizontal-position.spec.ts @@ -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", () => { diff --git a/src/file/drawing/floating/vertical-position.spec.ts b/src/file/drawing/floating/vertical-position.spec.ts index ff34f762ef..20f4cbe62a 100644 --- a/src/file/drawing/floating/vertical-position.spec.ts +++ b/src/file/drawing/floating/vertical-position.spec.ts @@ -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", () => { diff --git a/src/file/index.ts b/src/file/index.ts index 18f0a595e4..63761d4555 100644 --- a/src/file/index.ts +++ b/src/file/index.ts @@ -14,3 +14,4 @@ export * from "./footer-wrapper"; export * from "./header"; export * from "./footnotes"; export * from "./track-revision"; +export * from "./shared"; diff --git a/src/file/paragraph/frame/frame-properties.spec.ts b/src/file/paragraph/frame/frame-properties.spec.ts new file mode 100644 index 0000000000..d0cccc8c7a --- /dev/null +++ b/src/file/paragraph/frame/frame-properties.spec.ts @@ -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, + }, + }, + }); + }); + }); +}); diff --git a/src/file/paragraph/frame/frame-properties.ts b/src/file/paragraph/frame/frame-properties.ts new file mode 100644 index 0000000000..13a7e72745 --- /dev/null +++ b/src/file/paragraph/frame/frame-properties.ts @@ -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, + }), + ); + } +} diff --git a/src/file/paragraph/frame/index.ts b/src/file/paragraph/frame/index.ts new file mode 100644 index 0000000000..92a61d95ef --- /dev/null +++ b/src/file/paragraph/frame/index.ts @@ -0,0 +1 @@ +export * from "./frame-properties"; diff --git a/src/file/paragraph/index.ts b/src/file/paragraph/index.ts index d68c1d7f03..c1b59e4deb 100644 --- a/src/file/paragraph/index.ts +++ b/src/file/paragraph/index.ts @@ -4,3 +4,4 @@ export * from "./properties"; export * from "./run"; export * from "./links"; export * from "./math"; +export * from "./frame"; diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 6b1f3c0fe0..5b2f95ed58 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -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({ diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts index e8fc29a713..29bcc0613e 100644 --- a/src/file/paragraph/properties.ts +++ b/src/file/paragraph/properties.ts @@ -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 { diff --git a/src/file/shared/alignment.ts b/src/file/shared/alignment.ts new file mode 100644 index 0000000000..03e395b5fd --- /dev/null +++ b/src/file/shared/alignment.ts @@ -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", +} \ No newline at end of file diff --git a/src/file/shared/index.ts b/src/file/shared/index.ts new file mode 100644 index 0000000000..bc61bbe9ca --- /dev/null +++ b/src/file/shared/index.ts @@ -0,0 +1 @@ +export * from "./alignment"; From e7eca14e1e982d200c6aa50d0f6528d20084983e Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 14 Mar 2021 17:03:50 +0000 Subject: [PATCH 2/3] Fix prettier issues --- src/file/shared/alignment.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file/shared/alignment.ts b/src/file/shared/alignment.ts index 03e395b5fd..5909025891 100644 --- a/src/file/shared/alignment.ts +++ b/src/file/shared/alignment.ts @@ -12,4 +12,4 @@ export enum VerticalPositionAlign { INSIDE = "inside", OUTSIDE = "outside", TOP = "top", -} \ No newline at end of file +} From cc32a7b2d381bb6c0d44b27436c653d977f05f8c Mon Sep 17 00:00:00 2001 From: Dolan Date: Sun, 14 Mar 2021 18:12:52 +0000 Subject: [PATCH 3/3] Add text frame documentation --- demo/{60-text-frame.ts => 61-text-frame.ts} | 0 docs/_coverpage.md | 2 +- docs/_sidebar.md | 1 + docs/usage/bullet-points.md | 1 + docs/usage/paragraph.md | 23 +++++-- docs/usage/text-frames.md | 69 +++++++++++++++++++++ 6 files changed, 90 insertions(+), 6 deletions(-) rename demo/{60-text-frame.ts => 61-text-frame.ts} (100%) create mode 100644 docs/usage/text-frames.md diff --git a/demo/60-text-frame.ts b/demo/61-text-frame.ts similarity index 100% rename from demo/60-text-frame.ts rename to demo/61-text-frame.ts diff --git a/docs/_coverpage.md b/docs/_coverpage.md index a2db37dc5f..330479a04f 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -3,7 +3,7 @@ > Easily generate .docx files with JS/TS. Works for Node and on the Browser. :100: - Simple, declarative API -- 50+ usage examples +- 60+ usage examples - Battle tested, mature, 98%+ coverage [GitHub](https://github.com/dolanmiu/docx) diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 2538e975c7..7fa4e9f745 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -22,6 +22,7 @@ * [Page Numbers](usage/page-numbers.md) * [Change Tracking](usage/change-tracking.md) * [Math](usage/math.md) + * [Text Frames](usage/text-frames.md) * Styling * [Styling with JS](usage/styling-with-js.md) * [Styling with XML](usage/styling-with-xml.md) diff --git a/docs/usage/bullet-points.md b/docs/usage/bullet-points.md index 159241b3b0..cf2c5bda54 100644 --- a/docs/usage/bullet-points.md +++ b/docs/usage/bullet-points.md @@ -1,5 +1,6 @@ # Bullet Points +!> Bullet Points requires an understanding of [Paragraphs](usage/paragraph.md). ## Example To make a bullet point, simply make a paragraph into a bullet point: diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md index ceb4e0aa34..f824d9d44b 100644 --- a/docs/usage/paragraph.md +++ b/docs/usage/paragraph.md @@ -32,7 +32,7 @@ const paragraph = new Paragraph({ }); ``` -After you create the paragraph, you must add the paragraph into the `document's section`. Learn more about `sections` here: +After you create the paragraph, you must add the paragraph into a `section`: ```ts doc.addSection({ @@ -74,9 +74,11 @@ This is the list of options for a paragraph. A detailed explanation is below: | keepNext | `boolean` | Optional | | | children | `(TextRun or PictureRun or Hyperlink)[]` | Optional | | | style | `string` | Optional | | -| tabStop | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | | -| bullet | `{ level: number }` | Optional | | -| numbering | `{ num: ConcreteNumbering; level: number; custom?: boolean }` | Optional | | +| [tabStop](usage/tab-stops) | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | | +| [bullet](usage/bullet-points) | `{ level: number }` | Optional | | +| [numbering](usage/numbering) | `{ num: ConcreteNumbering; level: number; custom?: boolean }` | Optional | | +| [widowControl](#widow-control) | `boolean` | Optional | | +| [frame](usage/text-frames.md) | `IFrameOptions` | Optional | | ## Text @@ -157,6 +159,17 @@ const paragraph = new Paragraph({ }); ``` +## Widow Control + +Allow First/Last Line to Display on a Separate Page + +```ts +const paragraph = new Paragraph({ + text: "shading", + widowControl: true, +}); +``` + ## Spacing Adding spacing between paragraphs @@ -195,7 +208,7 @@ const paragraph = new Paragraph({ ## Styles -To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/docx/wiki/Styling +To create styles, please refer to the [styling documentation](usage/styling-with-js) ![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu") diff --git a/docs/usage/text-frames.md b/docs/usage/text-frames.md new file mode 100644 index 0000000000..473138d16e --- /dev/null +++ b/docs/usage/text-frames.md @@ -0,0 +1,69 @@ +# Text Frames + +Also known as `Text Boxes` + +!> Text Frames requires an understanding of [Paragraphs](usage/paragraph.md). + +> Text frames are paragraphs of text in a document which are positioned in a separate region or frame in the document, and can be positioned with a specific size and position relative to non-frame paragraphs in the current document. + +## Intro + +To make a `Text Frame`, simply add the `frame` property on a paragraph. `Borders` can be applied to frame simply by adding the `border` attribute. + +```ts +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, + }), + ], +}); +```