Merge pull request #1741 from dolanmiu/feat/alt-text
#756 Adding alt text feature
This commit is contained in:
18
.github/workflows/demos.yml
vendored
18
.github/workflows/demos.yml
vendored
@ -73,15 +73,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
xml-file: build/extracted-doc/word/document.xml
|
xml-file: build/extracted-doc/word/document.xml
|
||||||
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
||||||
# - name: Run Demo
|
- name: Run Demo
|
||||||
# run: npm run ts-node -- ./demo/5-images.ts
|
run: npm run ts-node -- ./demo/5-images.ts
|
||||||
# - name: Extract Word Document
|
- name: Extract Word Document
|
||||||
# run: npm run extract
|
run: npm run extract
|
||||||
# - name: Validate XML
|
- name: Validate XML
|
||||||
# uses: ChristophWurst/xmllint-action@v1
|
uses: ChristophWurst/xmllint-action@v1
|
||||||
# with:
|
with:
|
||||||
# xml-file: build/extracted-doc/word/document.xml
|
xml-file: build/extracted-doc/word/document.xml
|
||||||
# xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
xml-schema-file: ooxml-schemas/microsoft/wml-2010.xsd
|
||||||
- name: Run Demo
|
- name: Run Demo
|
||||||
run: npm run ts-node -- ./demo/6-page-borders.ts
|
run: npm run ts-node -- ./demo/6-page-borders.ts
|
||||||
- name: Extract Word Document
|
- name: Extract Word Document
|
||||||
|
@ -25,6 +25,11 @@ const doc = new Document({
|
|||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
|
altText: {
|
||||||
|
title: "This is an ultimate title",
|
||||||
|
description: "This is an ultimate image",
|
||||||
|
name: "My Ultimate Image",
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -252,13 +252,36 @@ const image = new ImageRun({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Alternative Text
|
||||||
|
|
||||||
|
Specifies common non-visual DrawingML properties. A name, title and description for a picture can be specified.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const image = new ImageRun({
|
||||||
|
data: fs.readFileSync("./demo/images/pizza.gif"),
|
||||||
|
altText: {
|
||||||
|
title: "This is an ultimate title",
|
||||||
|
description: "This is an ultimate image",
|
||||||
|
name: "My Ultimate Image",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| ----------- | -------- | -------- | ------------------------------------ |
|
||||||
|
| name | `string` | Required | `Specimen A` |
|
||||||
|
| title | `string` | Required | `My awesome title of my image` |
|
||||||
|
| description | `string` | Required | `My awesome description of my image` |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Add image to the document
|
### Add image to the document
|
||||||
|
|
||||||
Importing Images from file system path
|
Importing Images from file system path
|
||||||
|
|
||||||
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/5-images.ts ':include')
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/5-images.ts ":include")
|
||||||
|
|
||||||
_Source: https://github.com/dolanmiu/docx/blob/master/demo/5-images.ts_
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/5-images.ts_
|
||||||
|
|
||||||
@ -266,7 +289,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/5-images.ts_
|
|||||||
|
|
||||||
Example showing how to add image to headers and footers
|
Example showing how to add image to headers and footers
|
||||||
|
|
||||||
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/9-images-in-header-and-footer.ts ':include')
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/9-images-in-header-and-footer.ts ":include")
|
||||||
|
|
||||||
_Source: https://github.com/dolanmiu/docx/blob/master/demo/9-images-in-header-and-footer.ts_
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/9-images-in-header-and-footer.ts_
|
||||||
|
|
||||||
@ -274,6 +297,6 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/9-images-in-header-an
|
|||||||
|
|
||||||
Example showing how to float images on top of text and optimally give a `margin`
|
Example showing how to float images on top of text and optimally give a `margin`
|
||||||
|
|
||||||
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/38-text-wrapping.ts ':include')
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/38-text-wrapping.ts ":include")
|
||||||
|
|
||||||
_Source: https://github.com/dolanmiu/docx/blob/master/demo/38-text-wrapping.ts_
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/38-text-wrapping.ts_
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { assert } from "chai";
|
import { assert, expect } from "chai";
|
||||||
|
import { SinonStub, stub } from "sinon";
|
||||||
|
|
||||||
|
import { Formatter } from "@export/formatter";
|
||||||
|
import * as convenienceFunctions from "@util/convenience-functions";
|
||||||
|
|
||||||
import { Utility } from "tests/utility";
|
import { Utility } from "tests/utility";
|
||||||
|
|
||||||
@ -36,6 +40,14 @@ const createAnchor = (drawingOptions: IDrawingOptions): Anchor =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
describe("Anchor", () => {
|
describe("Anchor", () => {
|
||||||
|
before(() => {
|
||||||
|
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
||||||
|
});
|
||||||
|
|
||||||
let anchor: Anchor;
|
let anchor: Anchor;
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
@ -362,5 +374,236 @@ describe("Anchor", () => {
|
|||||||
relativeHeight: 120,
|
relativeHeight: 120,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create a Drawing with doc properties", () => {
|
||||||
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
zIndex: 120,
|
||||||
|
},
|
||||||
|
docProperties: {
|
||||||
|
name: "test",
|
||||||
|
description: "test",
|
||||||
|
title: "test",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(anchor);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"wp:anchor": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
allowOverlap: "1",
|
||||||
|
behindDoc: "0",
|
||||||
|
distB: 0,
|
||||||
|
distL: 0,
|
||||||
|
distR: 0,
|
||||||
|
distT: 0,
|
||||||
|
layoutInCell: "1",
|
||||||
|
locked: "0",
|
||||||
|
relativeHeight: 120,
|
||||||
|
simplePos: "0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:simplePos": {
|
||||||
|
_attr: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:positionH": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
relativeFrom: "page",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:posOffset": ["0"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:positionV": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
relativeFrom: "page",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:posOffset": ["0"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:extent": {
|
||||||
|
_attr: {
|
||||||
|
cx: 952500,
|
||||||
|
cy: 952500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:effectExtent": {
|
||||||
|
_attr: {
|
||||||
|
b: 0,
|
||||||
|
l: 0,
|
||||||
|
r: 0,
|
||||||
|
t: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:wrapNone": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:docPr": {
|
||||||
|
_attr: {
|
||||||
|
descr: "test",
|
||||||
|
id: 0,
|
||||||
|
name: "test",
|
||||||
|
title: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"wp:cNvGraphicFramePr": [
|
||||||
|
{
|
||||||
|
"a:graphicFrameLocks": {
|
||||||
|
_attr: {
|
||||||
|
noChangeAspect: 1,
|
||||||
|
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:graphic": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:graphicData": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
uri: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pic:pic": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"xmlns:pic": "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pic:nvPicPr": [
|
||||||
|
{
|
||||||
|
"pic:cNvPr": {
|
||||||
|
_attr: {
|
||||||
|
descr: "",
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pic:cNvPicPr": [
|
||||||
|
{
|
||||||
|
"a:picLocks": {
|
||||||
|
_attr: {
|
||||||
|
noChangeArrowheads: 1,
|
||||||
|
noChangeAspect: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pic:blipFill": [
|
||||||
|
{
|
||||||
|
"a:blip": {
|
||||||
|
_attr: {
|
||||||
|
cstate: "none",
|
||||||
|
"r:embed": "rId{test.png}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:srcRect": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:stretch": [
|
||||||
|
{
|
||||||
|
"a:fillRect": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pic:spPr": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
bwMode: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:xfrm": [
|
||||||
|
{
|
||||||
|
_attr: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:off": {
|
||||||
|
_attr: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:ext": {
|
||||||
|
_attr: {
|
||||||
|
cx: 952500,
|
||||||
|
cy: 952500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:prstGeom": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
prst: "rect",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a:avLst": {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -90,7 +90,7 @@ export class Anchor extends XmlComponent {
|
|||||||
this.root.push(new WrapNone());
|
this.root.push(new WrapNone());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root.push(new 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));
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "@file/xml-components";
|
|
||||||
|
|
||||||
export class DocPropertiesAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly id?: number;
|
|
||||||
readonly name?: string;
|
|
||||||
readonly descr?: string;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
id: "id",
|
|
||||||
name: "name",
|
|
||||||
descr: "descr",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,15 +1,36 @@
|
|||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
|
||||||
import { DocPropertiesAttributes } from "./doc-properties-attributes";
|
import { uniqueNumericId } from "@util/convenience-functions";
|
||||||
|
|
||||||
|
class DocPropertiesAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly id?: number;
|
||||||
|
readonly name?: string;
|
||||||
|
readonly description?: string;
|
||||||
|
readonly title?: string;
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
id: "id",
|
||||||
|
name: "name",
|
||||||
|
description: "descr",
|
||||||
|
title: "title",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocPropertiesOptions {
|
||||||
|
readonly name: string;
|
||||||
|
readonly description: string;
|
||||||
|
readonly title: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class DocProperties extends XmlComponent {
|
export class DocProperties extends XmlComponent {
|
||||||
public constructor() {
|
public constructor({ name, description, title }: DocPropertiesOptions = { name: "", description: "", title: "" }) {
|
||||||
super("wp:docPr");
|
super("wp:docPr");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new DocPropertiesAttributes({
|
new DocPropertiesAttributes({
|
||||||
id: 0,
|
id: uniqueNumericId(),
|
||||||
name: "",
|
name,
|
||||||
descr: "",
|
description,
|
||||||
|
title,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
import { SinonStub, stub } from "sinon";
|
||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
|
import * as convenienceFunctions from "@util/convenience-functions";
|
||||||
|
|
||||||
import { Drawing, IDrawingOptions } from "./drawing";
|
import { Drawing, IDrawingOptions } from "./drawing";
|
||||||
|
|
||||||
@ -26,6 +28,14 @@ const createDrawing = (drawingOptions?: IDrawingOptions): Drawing =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
describe("Drawing", () => {
|
describe("Drawing", () => {
|
||||||
|
before(() => {
|
||||||
|
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
||||||
|
});
|
||||||
|
|
||||||
let currentBreak: Drawing;
|
let currentBreak: Drawing;
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
@ -68,6 +78,7 @@ describe("Drawing", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -298,6 +309,7 @@ describe("Drawing", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { IMediaData } from "@file/media";
|
import { IMediaData } from "@file/media";
|
||||||
import { XmlComponent } from "@file/xml-components";
|
import { XmlComponent } from "@file/xml-components";
|
||||||
|
|
||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
|
import { DocPropertiesOptions } from "./doc-properties/doc-properties";
|
||||||
import { IFloating } from "./floating";
|
import { IFloating } from "./floating";
|
||||||
import { Inline } from "./inline";
|
import { Inline } from "./inline";
|
||||||
|
|
||||||
@ -13,6 +15,7 @@ export interface IDistance {
|
|||||||
|
|
||||||
export interface IDrawingOptions {
|
export interface IDrawingOptions {
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Drawing">
|
// <xsd:complexType name="CT_Drawing">
|
||||||
@ -29,7 +32,11 @@ export class Drawing extends XmlComponent {
|
|||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (!drawingOptions.floating) {
|
if (!drawingOptions.floating) {
|
||||||
this.inline = new Inline(imageData, imageData.transformation);
|
this.inline = new Inline({
|
||||||
|
mediaData: imageData,
|
||||||
|
transform: imageData.transformation,
|
||||||
|
docProperties: drawingOptions.docProperties,
|
||||||
|
});
|
||||||
this.root.push(this.inline);
|
this.root.push(this.inline);
|
||||||
} else {
|
} else {
|
||||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
||||||
|
@ -1,13 +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 { XmlComponent } from "@file/xml-components";
|
||||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
import { DocProperties, DocPropertiesOptions } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { EffectExtent } 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 { InlineAttributes } from "./inline-attributes";
|
||||||
|
|
||||||
|
interface InlineOptions {
|
||||||
|
readonly mediaData: IMediaData;
|
||||||
|
readonly transform: IMediaDataTransformation;
|
||||||
|
readonly docProperties?: DocPropertiesOptions;
|
||||||
|
}
|
||||||
|
|
||||||
// <xsd:complexType name="CT_Inline">
|
// <xsd:complexType name="CT_Inline">
|
||||||
// <xsd:sequence>
|
// <xsd:sequence>
|
||||||
// <xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
// <xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
||||||
@ -26,7 +32,7 @@ export class Inline extends XmlComponent {
|
|||||||
private readonly extent: Extent;
|
private readonly extent: Extent;
|
||||||
private readonly graphic: Graphic;
|
private readonly graphic: Graphic;
|
||||||
|
|
||||||
public constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
public constructor({ mediaData, transform, docProperties }: InlineOptions) {
|
||||||
super("wp:inline");
|
super("wp:inline");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
@ -43,7 +49,7 @@ export class Inline extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(this.extent);
|
this.root.push(this.extent);
|
||||||
this.root.push(new EffectExtent());
|
this.root.push(new EffectExtent());
|
||||||
this.root.push(new DocProperties());
|
this.root.push(new DocProperties(docProperties));
|
||||||
this.root.push(new GraphicFrameProperties());
|
this.root.push(new GraphicFrameProperties());
|
||||||
this.root.push(this.graphic);
|
this.root.push(this.graphic);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ describe("Paragraph", () => {
|
|||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueId as SinonStub).restore();
|
(convenienceFunctions.uniqueId as SinonStub).restore();
|
||||||
|
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import { Formatter } from "@export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { Comment, CommentRangeEnd, CommentRangeStart, CommentReference, Comments } from "./comment-run";
|
import { Comment, CommentRangeEnd, CommentRangeStart, CommentReference, Comments } from "./comment-run";
|
||||||
@ -40,6 +41,17 @@ describe("CommentReference", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Comment", () => {
|
describe("Comment", () => {
|
||||||
|
let clock: sinon.SinonFakeTimers;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const now = new Date(1999, 0, 1);
|
||||||
|
clock = sinon.useFakeTimers(now.getTime());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create", () => {
|
it("should create", () => {
|
||||||
const component = new Comment({
|
const component = new Comment({
|
||||||
@ -72,6 +84,37 @@ describe("Comment", () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create by using default date", () => {
|
||||||
|
const component = new Comment({
|
||||||
|
id: 0,
|
||||||
|
text: "test-comment",
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(component);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:comment": [
|
||||||
|
{ _attr: { "w:id": 0, "w:date": "1999-01-01T00:00:00.000Z" } },
|
||||||
|
{
|
||||||
|
"w:p": [
|
||||||
|
{
|
||||||
|
"w:r": [
|
||||||
|
{
|
||||||
|
"w:t": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"xml:space": "preserve",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-comment",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,10 +11,12 @@ import { ImageRun } from "./image-run";
|
|||||||
describe("ImageRun", () => {
|
describe("ImageRun", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
stub(convenienceFunctions, "uniqueId").callsFake(() => "test-unique-id");
|
||||||
|
stub(convenienceFunctions, "uniqueNumericId").callsFake(() => 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
(convenienceFunctions.uniqueId as SinonStub).restore();
|
(convenienceFunctions.uniqueId as SinonStub).restore();
|
||||||
|
(convenienceFunctions.uniqueNumericId as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
@ -125,6 +127,7 @@ describe("ImageRun", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -375,6 +378,7 @@ describe("ImageRun", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -629,6 +633,7 @@ describe("ImageRun", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -886,6 +891,7 @@ describe("ImageRun", () => {
|
|||||||
descr: "",
|
descr: "",
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: "",
|
||||||
|
title: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { uniqueId } from "@util/convenience-functions";
|
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 { Drawing, IFloating } from "../../drawing";
|
import { Drawing, IFloating } from "../../drawing";
|
||||||
import { IMediaTransformation } from "../../media";
|
import { IMediaTransformation } from "../../media";
|
||||||
@ -11,6 +12,7 @@ export interface IImageOptions {
|
|||||||
readonly data: Buffer | string | Uint8Array | ArrayBuffer;
|
readonly data: Buffer | string | Uint8Array | ArrayBuffer;
|
||||||
readonly transformation: IMediaTransformation;
|
readonly transformation: IMediaTransformation;
|
||||||
readonly floating?: IFloating;
|
readonly floating?: IFloating;
|
||||||
|
readonly altText?: DocPropertiesOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ImageRun extends Run {
|
export class ImageRun extends Run {
|
||||||
@ -37,7 +39,7 @@ 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 });
|
const drawing = new Drawing(this.imageData, { floating: options.floating, docProperties: options.altText });
|
||||||
|
|
||||||
this.root.push(drawing);
|
this.root.push(drawing);
|
||||||
}
|
}
|
||||||
@ -49,15 +51,16 @@ export class ImageRun extends Run {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private convertDataURIToBinary(dataURI: string): Uint8Array {
|
private convertDataURIToBinary(dataURI: string): Uint8Array {
|
||||||
// https://gist.github.com/borismus/1032746
|
|
||||||
// https://github.com/mafintosh/base64-to-uint8array
|
|
||||||
const BASE64_MARKER = ";base64,";
|
|
||||||
|
|
||||||
const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
|
|
||||||
|
|
||||||
if (typeof atob === "function") {
|
if (typeof atob === "function") {
|
||||||
|
// https://gist.github.com/borismus/1032746
|
||||||
|
// https://github.com/mafintosh/base64-to-uint8array
|
||||||
|
const BASE64_MARKER = ";base64,";
|
||||||
|
const base64Index = dataURI.indexOf(BASE64_MARKER);
|
||||||
|
|
||||||
|
const base64IndexWithOffset = base64Index === -1 ? 0 : base64Index + BASE64_MARKER.length;
|
||||||
|
|
||||||
return new Uint8Array(
|
return new Uint8Array(
|
||||||
atob(dataURI.substring(base64Index))
|
atob(dataURI.substring(base64IndexWithOffset))
|
||||||
.split("")
|
.split("")
|
||||||
.map((c) => c.charCodeAt(0)),
|
.map((c) => c.charCodeAt(0)),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user