// http://officeopenxml.com/WPparagraph-textFrames.php import { HorizontalPositionAlign, VerticalPositionAlign } from "@file/shared/alignment"; import { HeightRule } from "@file/table"; import { BuilderElement, XmlComponent } from "@file/xml-components"; export const DropCapType = { NONE: "none", DROP: "drop", MARGIN: "margin", } as const; export const FrameAnchorType = { MARGIN: "margin", PAGE: "page", TEXT: "text", } as const; export const FrameWrap = { AROUND: "around", AUTO: "auto", NONE: "none", // eslint-disable-next-line @typescript-eslint/naming-convention NOT_BESIDE: "notBeside", THROUGH: "through", TIGHT: "tight", } as const; interface IBaseFrameOptions { readonly anchorLock?: boolean; readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType]; readonly width: number; readonly height: number; readonly wrap?: (typeof FrameWrap)[keyof typeof FrameWrap]; readonly lines?: number; readonly anchor: { readonly horizontal: (typeof FrameAnchorType)[keyof typeof FrameAnchorType]; readonly vertical: (typeof FrameAnchorType)[keyof typeof FrameAnchorType]; }; readonly space?: { readonly horizontal: number; readonly vertical: number; }; readonly rule?: (typeof HeightRule)[keyof typeof HeightRule]; } export interface IXYFrameOptions extends IBaseFrameOptions { readonly type: "absolute"; readonly position: { readonly x: number; readonly y: number; }; } export interface IAlignmentFrameOptions extends IBaseFrameOptions { readonly type: "alignment"; readonly alignment: { readonly x: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign]; readonly y: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign]; }; } // Be wary of Typescript's Open types: // https://stackoverflow.com/q/46370222/3481582 export type IFrameOptions = IXYFrameOptions | IAlignmentFrameOptions; // // // // // // // // // // // // // // // // // type FramePropertiesAttributes = { readonly anchorLock?: boolean; readonly dropCap?: (typeof DropCapType)[keyof typeof DropCapType]; readonly width: number; readonly height: number; readonly x?: number; readonly y?: number; readonly wrap?: (typeof FrameWrap)[keyof typeof FrameWrap]; readonly lines?: number; readonly anchorHorizontal?: (typeof FrameAnchorType)[keyof typeof FrameAnchorType]; readonly anchorVertical?: (typeof FrameAnchorType)[keyof typeof FrameAnchorType]; readonly spaceHorizontal?: number; readonly spaceVertical?: number; readonly rule?: (typeof HeightRule)[keyof typeof HeightRule]; readonly alignmentX?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign]; readonly alignmentY?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign]; }; 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, }, }, });