Add image borders (#2472)
* Add image borders * Fix prettier * Fix spelling * Fix spelling * Finish feature * Update demo * Try and fix demo 14
This commit is contained in:
@ -54,7 +54,8 @@
|
|||||||
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
"\\.to\\.include\\.members\\(\\[[^\\]]+]\\)",
|
||||||
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
"/new [a-zA-Z]+\\({[^£]+}\\)/g",
|
||||||
"/<element name=\"[a-z]+\"/gi",
|
"/<element name=\"[a-z]+\"/gi",
|
||||||
"/<attribute name=\"[a-z]+\"/gi"
|
"/<attribute name=\"[a-z]+\"/gi",
|
||||||
|
"/key: \".+\"/"
|
||||||
],
|
],
|
||||||
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
"ignorePaths": ["package.json", "docs/api", "*.docx", "build"],
|
||||||
"allowCompoundWords": true,
|
"allowCompoundWords": true,
|
||||||
|
@ -92,6 +92,7 @@ rules:
|
|||||||
format:
|
format:
|
||||||
- camelCase
|
- camelCase
|
||||||
- PascalCase
|
- PascalCase
|
||||||
|
- UPPER_CASE # for constants
|
||||||
filter:
|
filter:
|
||||||
regex: (^[a-z]+:.+)|_attr|[0-9]
|
regex: (^[a-z]+:.+)|_attr|[0-9]
|
||||||
match: false
|
match: false
|
||||||
|
@ -121,9 +121,11 @@ const createLoremIpsumParagraphs = () => [
|
|||||||
"Vivamus euismod, sem eget molestie rhoncus, metus dui laoreet lacus, et lobortis est metus ut felis. Aenean imperdiet lacus nunc, vitae molestie orci ultrices nec. Cras egestas maximus diam, vitae efficitur nisl luctus imperdiet. Nulla pellentesque sodales ante, nec facilisis turpis. Vivamus at hendrerit enim, ac dictum lorem. Cras ",
|
"Vivamus euismod, sem eget molestie rhoncus, metus dui laoreet lacus, et lobortis est metus ut felis. Aenean imperdiet lacus nunc, vitae molestie orci ultrices nec. Cras egestas maximus diam, vitae efficitur nisl luctus imperdiet. Nulla pellentesque sodales ante, nec facilisis turpis. Vivamus at hendrerit enim, ac dictum lorem. Cras ",
|
||||||
),
|
),
|
||||||
new Paragraph(
|
new Paragraph(
|
||||||
"congue accumsan dui, non pretium sem auctor quis. Nunc a mauris vehicula, elementum ex vitae, sollicitudin eros. Nunc non sapien vitae justo sodales condimentum. Praesent nisl felis, tristique ac odio at, rhoncus porttitor orci. Morbi egestas placerat iaculis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In at lorem nec neque faucibus ultricies ut in ipsum.",
|
"congue accumsan dui, non pretium sem auctor quis. Nunc a mauris vehicula, elementum ex vitae, sollicitudin eros. Nunc non sapien vitae justo sodales condimentum. Praesent nisl felis, tristique ac odio at, rhoncus porttitor orci. Morbi egestas placerat iaculis.",
|
||||||
|
),
|
||||||
|
new Paragraph(
|
||||||
|
"Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In at lorem nec neque faucibus ultricies ut in ipsum.",
|
||||||
),
|
),
|
||||||
|
|
||||||
new Paragraph(
|
new Paragraph(
|
||||||
"Suspendisse fermentum feugiat augue eu convallis. Maecenas eros velit, efficitur sit amet posuere sed, tristique sit amet nisi. Donec vel convallis justo, id tempor neque. Nunc pulvinar maximus nulla, vitae congue lacus cursus ut. Morbi at mollis est, a vehicula nisi. Cras venenatis nibh vel massa interdum commodo. Nulla mattis ",
|
"Suspendisse fermentum feugiat augue eu convallis. Maecenas eros velit, efficitur sit amet posuere sed, tristique sit amet nisi. Donec vel convallis justo, id tempor neque. Nunc pulvinar maximus nulla, vitae congue lacus cursus ut. Morbi at mollis est, a vehicula nisi. Cras venenatis nibh vel massa interdum commodo. Nulla mattis ",
|
||||||
),
|
),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import {
|
import {
|
||||||
|
convertMillimetersToTwip,
|
||||||
Document,
|
Document,
|
||||||
HorizontalPositionAlign,
|
HorizontalPositionAlign,
|
||||||
HorizontalPositionRelativeFrom,
|
HorizontalPositionRelativeFrom,
|
||||||
@ -41,6 +42,11 @@ const doc = new Document({
|
|||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "FF0000",
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -55,6 +61,12 @@ const doc = new Document({
|
|||||||
vertical: true,
|
vertical: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
outline: {
|
||||||
|
type: "solidFill",
|
||||||
|
solidFillType: "rgb",
|
||||||
|
value: "0000FF",
|
||||||
|
width: convertMillimetersToTwip(600),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -9,10 +9,10 @@ import { TextWrappingType } from "../text-wrap";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
|
|
||||||
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
||||||
new Anchor(
|
new Anchor({
|
||||||
{
|
mediaData: {
|
||||||
fileName: "test.png",
|
fileName: "test.png",
|
||||||
stream: new Buffer(""),
|
stream: Buffer.from(""),
|
||||||
transformation: {
|
transformation: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 0,
|
x: 0,
|
||||||
@ -24,7 +24,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
transform: {
|
||||||
pixels: {
|
pixels: {
|
||||||
x: 100,
|
x: 100,
|
||||||
y: 100,
|
y: 100,
|
||||||
@ -35,7 +35,7 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
drawingOptions,
|
drawingOptions,
|
||||||
);
|
});
|
||||||
|
|
||||||
describe("Anchor", () => {
|
describe("Anchor", () => {
|
||||||
let anchor: Anchor;
|
let anchor: Anchor;
|
||||||
|
@ -6,7 +6,7 @@ import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../f
|
|||||||
import { Graphic } from "../inline/graphic";
|
import { Graphic } from "../inline/graphic";
|
||||||
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
||||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
import { DocProperties } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { AnchorAttributes } from "./anchor-attributes";
|
import { AnchorAttributes } from "./anchor-attributes";
|
||||||
@ -37,7 +37,15 @@ import { AnchorAttributes } from "./anchor-attributes";
|
|||||||
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
// <xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Anchor extends XmlComponent {
|
export class Anchor extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
drawingOptions,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly drawingOptions: IDrawingOptions;
|
||||||
|
}) {
|
||||||
super("wp:anchor");
|
super("wp:anchor");
|
||||||
|
|
||||||
const floating: IFloating = {
|
const floating: IFloating = {
|
||||||
@ -69,7 +77,7 @@ export class Anchor extends XmlComponent {
|
|||||||
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
||||||
this.root.push(new VerticalPosition(floating.verticalPosition));
|
this.root.push(new VerticalPosition(floating.verticalPosition));
|
||||||
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
||||||
this.root.push(new EffectExtent());
|
this.root.push(createEffectExtent({ top: 0, right: 0, bottom: 0, left: 0 }));
|
||||||
|
|
||||||
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
||||||
switch (drawingOptions.floating.wrap.type) {
|
switch (drawingOptions.floating.wrap.type) {
|
||||||
@ -92,6 +100,6 @@ export class Anchor extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new DocProperties(drawingOptions.docProperties));
|
this.root.push(new DocProperties(drawingOptions.docProperties));
|
||||||
this.root.push(new GraphicFrameProperties());
|
this.root.push(new GraphicFrameProperties());
|
||||||
this.root.push(new Graphic(mediaData, transform));
|
this.root.push(new Graphic({ mediaData, transform, outline: drawingOptions.outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
||||||
import { IFloating } from "./floating";
|
import { IFloating } from "./floating";
|
||||||
import { Inline } from "./inline";
|
import { createInline } from "./inline";
|
||||||
|
import { OutlineOptions } from "./inline/graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export interface IDistance {
|
export type IDistance = {
|
||||||
readonly distT?: number;
|
readonly distT?: number;
|
||||||
readonly distB?: number;
|
readonly distB?: number;
|
||||||
readonly distL?: number;
|
readonly distL?: number;
|
||||||
readonly distR?: number;
|
readonly distR?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IDrawingOptions {
|
export interface IDrawingOptions {
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Drawing">
|
// <xsd:complexType name="CT_Drawing">
|
||||||
@ -30,14 +32,16 @@ export class Drawing extends XmlComponent {
|
|||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (!drawingOptions.floating) {
|
if (!drawingOptions.floating) {
|
||||||
const inline = new Inline({
|
this.root.push(
|
||||||
mediaData: imageData,
|
createInline({
|
||||||
transform: imageData.transformation,
|
mediaData: imageData,
|
||||||
docProperties: drawingOptions.docProperties,
|
transform: imageData.transformation,
|
||||||
});
|
docProperties: drawingOptions.docProperties,
|
||||||
this.root.push(inline);
|
outline: drawingOptions.outline,
|
||||||
|
}),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
this.root.push(new Anchor({ mediaData: imageData, transform: imageData.transformation, drawingOptions }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
|
|
||||||
export class EffectExtentAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly b?: number;
|
|
||||||
readonly l?: number;
|
|
||||||
readonly r?: number;
|
|
||||||
readonly t?: number;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
b: "b",
|
|
||||||
l: "l",
|
|
||||||
r: "r",
|
|
||||||
t: "t",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,17 +1,31 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { EffectExtentAttributes } from "./effect-extent-attributes";
|
|
||||||
|
|
||||||
export class EffectExtent extends XmlComponent {
|
export type EffectExtentAttributes = {
|
||||||
public constructor() {
|
readonly top: number;
|
||||||
super("wp:effectExtent");
|
readonly right: number;
|
||||||
|
readonly bottom: number;
|
||||||
|
readonly left: number;
|
||||||
|
};
|
||||||
|
|
||||||
this.root.push(
|
export const createEffectExtent = ({ top, right, bottom, left }: EffectExtentAttributes): XmlComponent =>
|
||||||
new EffectExtentAttributes({
|
new BuilderElement<EffectExtentAttributes>({
|
||||||
b: 0,
|
name: "wp:effectExtent",
|
||||||
l: 0,
|
attributes: {
|
||||||
r: 0,
|
top: {
|
||||||
t: 0,
|
key: "t",
|
||||||
}),
|
value: top,
|
||||||
);
|
},
|
||||||
}
|
right: {
|
||||||
}
|
key: "r",
|
||||||
|
value: right,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
key: "b",
|
||||||
|
value: bottom,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
key: "l",
|
||||||
|
value: left,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -3,11 +3,20 @@ import { XmlComponent } from "@file/xml-components";
|
|||||||
|
|
||||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||||
import { Pic } from "./pic";
|
import { Pic } from "./pic";
|
||||||
|
import { OutlineOptions } from "./pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
export class GraphicData extends XmlComponent {
|
export class GraphicData extends XmlComponent {
|
||||||
private readonly pic: Pic;
|
private readonly pic: Pic;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphicData");
|
super("a:graphicData");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -16,7 +25,7 @@ export class GraphicData extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.pic = new Pic(mediaData, transform);
|
this.pic = new Pic({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.pic);
|
this.root.push(this.pic);
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,18 @@ import { BlipFill } from "./blip/blip-fill";
|
|||||||
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
||||||
import { PicAttributes } from "./pic-attributes";
|
import { PicAttributes } from "./pic-attributes";
|
||||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||||
|
import { OutlineOptions } from "./shape-properties/outline/outline";
|
||||||
|
|
||||||
export class Pic extends XmlComponent {
|
export class Pic extends XmlComponent {
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("pic:pic");
|
super("pic:pic");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -19,6 +28,6 @@ export class Pic extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(new NonVisualPicProperties());
|
this.root.push(new NonVisualPicProperties());
|
||||||
this.root.push(new BlipFill(mediaData));
|
this.root.push(new BlipFill(mediaData));
|
||||||
this.root.push(new ShapeProperties(transform));
|
this.root.push(new ShapeProperties({ transform, outline }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
|
||||||
describe("NoFill", () => {
|
describe("NoFill", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create", () => {
|
it("should create", () => {
|
||||||
const tree = new Formatter().format(new NoFill());
|
const tree = new Formatter().format(createNoFill());
|
||||||
expect(tree).to.deep.equal({
|
expect(tree).to.deep.equal({
|
||||||
"a:noFill": {},
|
"a:noFill": {},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
export class NoFill extends XmlComponent {
|
export const createNoFill = (): XmlComponent => new BuilderElement({ name: "a:noFill" });
|
||||||
public constructor() {
|
|
||||||
super("a:noFill");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,66 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { Outline } from "./outline";
|
|
||||||
|
|
||||||
describe("Outline", () => {
|
import { createOutline } from "./outline";
|
||||||
describe("#constructor()", () => {
|
import { SchemeColor } from "./scheme-color";
|
||||||
it("should create", () => {
|
|
||||||
const tree = new Formatter().format(new Outline());
|
describe("createOutline", () => {
|
||||||
expect(tree).to.deep.equal({
|
it("should create no fill", () => {
|
||||||
"a:ln": [
|
const tree = new Formatter().format(createOutline({ type: "noFill" }));
|
||||||
{
|
expect(tree).to.deep.equal({
|
||||||
"a:noFill": {},
|
"a:ln": [
|
||||||
},
|
{
|
||||||
],
|
_attr: {},
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
"a:noFill": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create solid rgb fill", () => {
|
||||||
|
const tree = new Formatter().format(createOutline({ type: "solidFill", solidFillType: "rgb", value: "FFFFFF" }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:ln": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:srgbClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "FFFFFF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create solid scheme fill", () => {
|
||||||
|
const tree = new Formatter().format(createOutline({ type: "solidFill", solidFillType: "scheme", value: SchemeColor.ACCENT1 }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:ln": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:schemeClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "accent1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,130 @@
|
|||||||
// http://officeopenxml.com/drwSp-outline.php
|
// http://officeopenxml.com/drwSp-outline.php
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { NoFill } from "./no-fill";
|
import { createNoFill } from "./no-fill";
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
export class Outline extends XmlComponent {
|
// <xsd:complexType name="CT_TextOutlineEffect">
|
||||||
public constructor() {
|
// <xsd:sequence>
|
||||||
super("a:ln");
|
// <xsd:group ref="EG_FillProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineDashProperties" minOccurs="0"/>
|
||||||
|
// <xsd:group ref="EG_LineJoinProperties" minOccurs="0"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="w" use="optional" type="a:ST_LineWidth"/>
|
||||||
|
// <xsd:attribute name="cap" use="optional" type="ST_LineCap"/>
|
||||||
|
// <xsd:attribute name="cmpd" use="optional" type="ST_CompoundLine"/>
|
||||||
|
// <xsd:attribute name="algn" use="optional" type="ST_PenAlignment"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
this.root.push(new NoFill());
|
// <xsd:simpleType name="ST_LineCap">
|
||||||
}
|
// <xsd:restriction base="xsd:string">
|
||||||
}
|
// <xsd:enumeration value="rnd"/>
|
||||||
|
// <xsd:enumeration value="sq"/>
|
||||||
|
// <xsd:enumeration value="flat"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const LineCap = {
|
||||||
|
ROUND: "rnd",
|
||||||
|
SQUARE: "sq",
|
||||||
|
FLAT: "flat",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_CompoundLine">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="sng"/>
|
||||||
|
// <xsd:enumeration value="dbl"/>
|
||||||
|
// <xsd:enumeration value="thickThin"/>
|
||||||
|
// <xsd:enumeration value="thinThick"/>
|
||||||
|
// <xsd:enumeration value="tri"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const CompoundLine = {
|
||||||
|
SINGLE: "sng",
|
||||||
|
DOUBLE: "dbl",
|
||||||
|
THICK_THIN: "thickThin",
|
||||||
|
THIN_THICK: "thinThick",
|
||||||
|
TRI: "tri",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PenAlignment">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="ctr"/>
|
||||||
|
// <xsd:enumeration value="in"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export const PenAlignment = {
|
||||||
|
CENTER: "ctr",
|
||||||
|
INSET: "in",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type OutlineAttributes = {
|
||||||
|
readonly width?: number;
|
||||||
|
readonly cap?: keyof typeof LineCap;
|
||||||
|
readonly compoundLine?: keyof typeof CompoundLine;
|
||||||
|
readonly align?: keyof typeof PenAlignment;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineNoFill = {
|
||||||
|
readonly type: "noFill";
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineRgbSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSchemeSolidFill = {
|
||||||
|
readonly type: "solidFill";
|
||||||
|
readonly solidFillType: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
type OutlineSolidFill = OutlineRgbSolidFill | OutlineSchemeSolidFill;
|
||||||
|
|
||||||
|
// <xsd:group name="EG_FillProperties">
|
||||||
|
// <xsd:choice>
|
||||||
|
// <xsd:element name="noFill" type="w:CT_Empty"/>
|
||||||
|
// <xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
|
||||||
|
// <xsd:element name="gradFill" type="CT_GradientFillProperties"/>
|
||||||
|
// </xsd:choice>
|
||||||
|
// </xsd:group>
|
||||||
|
type OutlineFillProperties = OutlineNoFill | OutlineSolidFill;
|
||||||
|
|
||||||
|
export type OutlineOptions = OutlineAttributes & OutlineFillProperties;
|
||||||
|
|
||||||
|
export const createOutline = (options: OutlineOptions): XmlComponent =>
|
||||||
|
new BuilderElement<OutlineAttributes>({
|
||||||
|
name: "a:ln",
|
||||||
|
attributes: {
|
||||||
|
width: {
|
||||||
|
key: "w",
|
||||||
|
value: options.width,
|
||||||
|
},
|
||||||
|
cap: {
|
||||||
|
key: "cap",
|
||||||
|
value: options.cap,
|
||||||
|
},
|
||||||
|
compoundLine: {
|
||||||
|
key: "cmpd",
|
||||||
|
value: options.compoundLine,
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
key: "algn",
|
||||||
|
value: options.align,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
options.type === "noFill"
|
||||||
|
? createNoFill()
|
||||||
|
: options.solidFillType === "rgb"
|
||||||
|
? createSolidFill({
|
||||||
|
type: "rgb",
|
||||||
|
value: options.value,
|
||||||
|
})
|
||||||
|
: createSolidFill({
|
||||||
|
type: "scheme",
|
||||||
|
value: options.value,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SolidRgbColorOptions = {
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SRgbColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSolidRgbColor = (options: SolidRgbColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SolidRgbColorOptions>({
|
||||||
|
name: "a:srgbClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,65 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
type SchemeColorOptions = {
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_SchemeColorVal">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="bg1"/>
|
||||||
|
// <xsd:enumeration value="tx1"/>
|
||||||
|
// <xsd:enumeration value="bg2"/>
|
||||||
|
// <xsd:enumeration value="tx2"/>
|
||||||
|
// <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="hlink"/>
|
||||||
|
// <xsd:enumeration value="folHlink"/>
|
||||||
|
// <xsd:enumeration value="dk1"/>
|
||||||
|
// <xsd:enumeration value="lt1"/>
|
||||||
|
// <xsd:enumeration value="dk2"/>
|
||||||
|
// <xsd:enumeration value="lt2"/>
|
||||||
|
// <xsd:enumeration value="phClr"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
|
||||||
|
// cspell:ignore folHlink, phClr, hlink
|
||||||
|
export const SchemeColor = {
|
||||||
|
BG1: "bg1",
|
||||||
|
TX1: "tx1",
|
||||||
|
BG2: "bg2",
|
||||||
|
TX2: "tx2",
|
||||||
|
ACCENT1: "accent1",
|
||||||
|
ACCENT2: "accent2",
|
||||||
|
ACCENT3: "accent3",
|
||||||
|
ACCENT4: "accent4",
|
||||||
|
ACCENT5: "accent5",
|
||||||
|
ACCENT6: "accent6",
|
||||||
|
HLINK: "hlink",
|
||||||
|
FOLHLINK: "folHlink",
|
||||||
|
DK1: "dk1",
|
||||||
|
LT1: "lt1",
|
||||||
|
DK2: "dk2",
|
||||||
|
LT2: "lt2",
|
||||||
|
PHCLR: "phClr",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SchemeColor">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export const createSchemeColor = (options: SchemeColorOptions): XmlComponent =>
|
||||||
|
new BuilderElement<SchemeColorOptions>({
|
||||||
|
name: "a:schemeClr",
|
||||||
|
attributes: {
|
||||||
|
value: {
|
||||||
|
key: "val",
|
||||||
|
value: options.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
|
||||||
|
import { createSolidFill } from "./solid-fill";
|
||||||
|
import { SchemeColor } from "./scheme-color";
|
||||||
|
|
||||||
|
describe("createSolidFill", () => {
|
||||||
|
it("should create of rgb", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "rgb", value: "FFFFFF" }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:srgbClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "FFFFFF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create of scheme", () => {
|
||||||
|
const tree = new Formatter().format(createSolidFill({ type: "scheme", value: SchemeColor.TX1 }));
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"a:solidFill": [
|
||||||
|
{
|
||||||
|
"a:schemeClr": {
|
||||||
|
_attr: {
|
||||||
|
val: "tx1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
|
import { createSchemeColor, SchemeColor } from "./scheme-color";
|
||||||
|
import { createSolidRgbColor } from "./rgb-color";
|
||||||
|
|
||||||
|
export type RgbColorOptions = {
|
||||||
|
readonly type: "rgb";
|
||||||
|
readonly value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SchemeColorOptions = {
|
||||||
|
readonly type: "scheme";
|
||||||
|
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SolidFillOptions = RgbColorOptions | SchemeColorOptions;
|
||||||
|
|
||||||
|
export const createSolidFill = (options: SolidFillOptions): XmlComponent =>
|
||||||
|
new BuilderElement({
|
||||||
|
name: "a:solidFill",
|
||||||
|
children: [options.type === "rgb" ? createSolidRgbColor(options) : createSchemeColor(options)],
|
||||||
|
});
|
@ -2,15 +2,15 @@
|
|||||||
import { IMediaDataTransformation } from "@file/media";
|
import { IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
import { Form } from "./form";
|
import { Form } from "./form";
|
||||||
// import { NoFill } from "./no-fill";
|
import { OutlineOptions, createOutline } from "./outline/outline";
|
||||||
// import { Outline } from "./outline/outline";
|
|
||||||
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
import { PresetGeometry } from "./preset-geometry/preset-geometry";
|
||||||
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
||||||
|
import { createNoFill } from "./outline/no-fill";
|
||||||
|
|
||||||
export class ShapeProperties extends XmlComponent {
|
export class ShapeProperties extends XmlComponent {
|
||||||
private readonly form: Form;
|
private readonly form: Form;
|
||||||
|
|
||||||
public constructor(transform: IMediaDataTransformation) {
|
public constructor({ outline, transform }: { readonly outline?: OutlineOptions; readonly transform: IMediaDataTransformation }) {
|
||||||
super("pic:spPr");
|
super("pic:spPr");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -23,7 +23,10 @@ export class ShapeProperties extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(this.form);
|
this.root.push(this.form);
|
||||||
this.root.push(new PresetGeometry());
|
this.root.push(new PresetGeometry());
|
||||||
// this.root.push(new NoFill());
|
|
||||||
// this.root.push(new Outline());
|
if (outline) {
|
||||||
|
this.root.push(createNoFill());
|
||||||
|
this.root.push(createOutline(outline));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { IMediaData, IMediaDataTransformation } from "@file/media";
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { GraphicData } from "./graphic-data";
|
import { GraphicData } from "./graphic-data";
|
||||||
|
import { OutlineOptions } from "./graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
class GraphicAttributes extends XmlAttributeComponent<{
|
class GraphicAttributes extends XmlAttributeComponent<{
|
||||||
readonly a: string;
|
readonly a: string;
|
||||||
@ -14,7 +15,15 @@ class GraphicAttributes extends XmlAttributeComponent<{
|
|||||||
export class Graphic extends XmlComponent {
|
export class Graphic extends XmlComponent {
|
||||||
private readonly data: GraphicData;
|
private readonly data: GraphicData;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({
|
||||||
|
mediaData,
|
||||||
|
transform,
|
||||||
|
outline,
|
||||||
|
}: {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
|
}) {
|
||||||
super("a:graphic");
|
super("a:graphic");
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new GraphicAttributes({
|
new GraphicAttributes({
|
||||||
@ -22,7 +31,7 @@ export class Graphic extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.data = new GraphicData(mediaData, transform);
|
this.data = new GraphicData({ mediaData, transform, outline });
|
||||||
|
|
||||||
this.root.push(this.data);
|
this.root.push(this.data);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
import { IDistance } from "../drawing";
|
|
||||||
|
|
||||||
// distT, distB etc have no effect on inline images, only floating
|
|
||||||
export class InlineAttributes extends XmlAttributeComponent<IDistance> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
distT: "distT",
|
|
||||||
distB: "distB",
|
|
||||||
distL: "distL",
|
|
||||||
distR: "distR",
|
|
||||||
};
|
|
||||||
}
|
|
58
src/file/drawing/inline/inline.spec.ts
Normal file
58
src/file/drawing/inline/inline.spec.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
import { createInline } from "./inline";
|
||||||
|
|
||||||
|
describe("Inline", () => {
|
||||||
|
it("should create with default effect extent", () => {
|
||||||
|
const tree = new Formatter().format(
|
||||||
|
createInline({
|
||||||
|
mediaData: {
|
||||||
|
fileName: "test.png",
|
||||||
|
stream: Buffer.from(""),
|
||||||
|
transformation: {
|
||||||
|
pixels: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
pixels: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
emus: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
docProperties: {
|
||||||
|
name: "test",
|
||||||
|
description: "test",
|
||||||
|
title: "test",
|
||||||
|
},
|
||||||
|
outline: { type: "solidFill", solidFillType: "rgb", value: "FFFFFF" },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree).toStrictEqual({
|
||||||
|
"wp:inline": expect.arrayContaining([
|
||||||
|
{
|
||||||
|
"wp:effectExtent": {
|
||||||
|
_attr: {
|
||||||
|
b: 19050,
|
||||||
|
l: 19050,
|
||||||
|
r: 19050,
|
||||||
|
t: 19050,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,18 +1,19 @@
|
|||||||
// http://officeopenxml.com/drwPicInline.php
|
// http://officeopenxml.com/drwPicInline.php
|
||||||
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
import { IMediaData, IMediaDataTransformation } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||||
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { createEffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
|
||||||
import { Graphic } from "./../inline/graphic";
|
import { Graphic } from "./../inline/graphic";
|
||||||
import { InlineAttributes } from "./inline-attributes";
|
import { OutlineOptions } from "./graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
|
|
||||||
interface InlineOptions {
|
type InlineOptions = {
|
||||||
readonly mediaData: IMediaData;
|
readonly mediaData: IMediaData;
|
||||||
readonly transform: IMediaDataTransformation;
|
readonly transform: IMediaDataTransformation;
|
||||||
readonly docProperties?: DocPropertiesOptions;
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
}
|
readonly outline?: OutlineOptions;
|
||||||
|
};
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Inline">
|
// <xsd:complexType name="CT_Inline">
|
||||||
// <xsd:sequence>
|
// <xsd:sequence>
|
||||||
@ -28,29 +29,41 @@ interface InlineOptions {
|
|||||||
// <xsd:attribute name="distL" 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="distR" type="ST_WrapDistance" use="optional"/>
|
||||||
// </xsd:complexType>
|
// </xsd:complexType>
|
||||||
export class Inline extends XmlComponent {
|
export const createInline = ({ mediaData, transform, docProperties, outline }: InlineOptions): XmlComponent =>
|
||||||
private readonly extent: Extent;
|
new BuilderElement({
|
||||||
private readonly graphic: Graphic;
|
name: "wp:inline",
|
||||||
|
attributes: {
|
||||||
public constructor({ mediaData, transform, docProperties }: InlineOptions) {
|
distanceTop: {
|
||||||
super("wp:inline");
|
key: "distT",
|
||||||
|
value: 0,
|
||||||
this.root.push(
|
},
|
||||||
new InlineAttributes({
|
distanceBottom: {
|
||||||
distT: 0,
|
key: "distB",
|
||||||
distB: 0,
|
value: 0,
|
||||||
distL: 0,
|
},
|
||||||
distR: 0,
|
distanceLeft: {
|
||||||
}),
|
key: "distL",
|
||||||
);
|
value: 0,
|
||||||
|
},
|
||||||
this.extent = new Extent(transform.emus.x, transform.emus.y);
|
distanceRight: {
|
||||||
this.graphic = new Graphic(mediaData, transform);
|
key: "distR",
|
||||||
|
value: 0,
|
||||||
this.root.push(this.extent);
|
},
|
||||||
this.root.push(new EffectExtent());
|
},
|
||||||
this.root.push(new DocProperties(docProperties));
|
children: [
|
||||||
this.root.push(new GraphicFrameProperties());
|
new Extent(transform.emus.x, transform.emus.y),
|
||||||
this.root.push(this.graphic);
|
createEffectExtent(
|
||||||
}
|
outline
|
||||||
}
|
? {
|
||||||
|
top: (outline.width ?? 9525) * 2,
|
||||||
|
right: (outline.width ?? 9525) * 2,
|
||||||
|
bottom: (outline.width ?? 9525) * 2,
|
||||||
|
left: (outline.width ?? 9525) * 2,
|
||||||
|
}
|
||||||
|
: { top: 0, right: 0, bottom: 0, left: 0 },
|
||||||
|
),
|
||||||
|
new DocProperties(docProperties),
|
||||||
|
new GraphicFrameProperties(),
|
||||||
|
new Graphic({ mediaData, transform, outline }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
@ -3,6 +3,7 @@ import { uniqueId } from "@util/convenience-functions";
|
|||||||
import { IContext, IXmlableObject } from "@file/xml-components";
|
import { IContext, IXmlableObject } from "@file/xml-components";
|
||||||
import { DocPropertiesOptions } from "@file/drawing/doc-properties/doc-properties";
|
import { DocPropertiesOptions } from "@file/drawing/doc-properties/doc-properties";
|
||||||
|
|
||||||
|
import { OutlineOptions } from "../../drawing/inline/graphic/graphic-data/pic/shape-properties/outline/outline";
|
||||||
import { Drawing, IFloating } from "../../drawing";
|
import { Drawing, IFloating } from "../../drawing";
|
||||||
import { IMediaTransformation } from "../../media";
|
import { IMediaTransformation } from "../../media";
|
||||||
import { IMediaData } from "../../media/data";
|
import { IMediaData } from "../../media/data";
|
||||||
@ -13,6 +14,7 @@ export interface IImageOptions {
|
|||||||
readonly transformation: IMediaTransformation;
|
readonly transformation: IMediaTransformation;
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
readonly altText?: DocPropertiesOptions;
|
readonly altText?: DocPropertiesOptions;
|
||||||
|
readonly outline?: OutlineOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ImageRun extends Run {
|
export class ImageRun extends Run {
|
||||||
@ -39,7 +41,11 @@ export class ImageRun extends Run {
|
|||||||
rotation: options.transformation.rotation ? options.transformation.rotation * 60000 : undefined,
|
rotation: options.transformation.rotation ? options.transformation.rotation * 60000 : undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const drawing = new Drawing(this.imageData, { floating: options.floating, docProperties: options.altText });
|
const drawing = new Drawing(this.imageData, {
|
||||||
|
floating: options.floating,
|
||||||
|
docProperties: options.altText,
|
||||||
|
outline: options.outline,
|
||||||
|
});
|
||||||
|
|
||||||
this.root.push(drawing);
|
this.root.push(drawing);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { IRunOptions, RunProperties } from "../../index";
|
|
||||||
import { Break } from "../../paragraph/run/break";
|
import { Break } from "../../paragraph/run/break";
|
||||||
import { Begin, End, Separate } from "../../paragraph/run/field";
|
import { Begin, End, Separate } from "../../paragraph/run/field";
|
||||||
import { PageNumber } from "../../paragraph/run/run";
|
import { IRunOptions, PageNumber } from "../../paragraph/run/run";
|
||||||
import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
|
import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
|
||||||
|
import { RunProperties } from "../../paragraph/run/properties";
|
||||||
import { DeletedNumberOfPages, DeletedNumberOfPagesSection, DeletedPage } from "./deleted-page-number";
|
import { DeletedNumberOfPages, DeletedNumberOfPagesSection, DeletedPage } from "./deleted-page-number";
|
||||||
import { DeletedText } from "./deleted-text";
|
import { DeletedText } from "./deleted-text";
|
||||||
|
|
||||||
|
@ -93,6 +93,8 @@ export class BuilderElement<T extends AttributeData> extends XmlComponent {
|
|||||||
this.root.push(new NextAttributeComponent(options.attributes));
|
this.root.push(new NextAttributeComponent(options.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Children
|
for (const child of options.children ?? []) {
|
||||||
|
this.root.push(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user