#1699 Allow images to work with Hyperlink

Add stack to IContext for prepForXml
This commit is contained in:
Dolan Miu
2022-12-26 15:12:44 +00:00
parent abcfd79f2f
commit fe8b0a6b2b
16 changed files with 506 additions and 26 deletions

View File

@ -0,0 +1,61 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { createHyperlinkClick, createHyperlinkHover } from "./doc-properties-children";
describe("Document Properties Children", () => {
describe("#createHyperlinkClick", () => {
it("should create a Hyperlink Click component", () => {
const tree = new Formatter().format(createHyperlinkClick("1", false));
expect(tree).to.deep.equal({
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
},
},
});
});
it("should create a Hyperlink Click component with xmlns:a", () => {
const tree = new Formatter().format(createHyperlinkClick("1", true));
expect(tree).to.deep.equal({
"a:hlinkClick": {
_attr: {
"r:id": "rId1",
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
});
});
});
describe("#createHyperlinkHover", () => {
it("should create a Hyperlink Hover component", () => {
const tree = new Formatter().format(createHyperlinkHover("1", false));
expect(tree).to.deep.equal({
"a:hlinkHover": {
_attr: {
"r:id": "rId1",
},
},
});
});
it("should create a Hyperlink Hover component with xmlns:a", () => {
const tree = new Formatter().format(createHyperlinkHover("1", true));
expect(tree).to.deep.equal({
"a:hlinkHover": {
_attr: {
"r:id": "rId1",
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
});
});
});
});

View File

@ -0,0 +1,57 @@
// <sequence>
// <element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1" />
// </sequence>
import { BuilderElement, XmlComponent } from "@file/xml-components";
// <xsd:complexType name="CT_Hyperlink">
// <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded" />
// <xsd:attribute name="tgtFrame" type="s:ST_String" use="optional" />
// <xsd:attribute name="tooltip" type="s:ST_String" use="optional" />
// <xsd:attribute name="docLocation" type="s:ST_String" use="optional" />
// <xsd:attribute name="history" type="s:ST_OnOff" use="optional" />
// <xsd:attribute name="anchor" type="s:ST_String" use="optional" />
// <xsd:attribute ref="r:id" />
// </xsd:complexType>
// TODO: Implement the rest of the attributes
export const createHyperlinkClick = (linkId: string, hasXmlNs: boolean): XmlComponent =>
new BuilderElement({
name: "a:hlinkClick",
attributes: {
...(hasXmlNs
? {
xmlns: {
key: "xmlns:a",
value: "http://schemas.openxmlformats.org/drawingml/2006/main",
},
}
: {}),
id: {
key: "r:id",
value: `rId${linkId}`,
},
},
});
export const createHyperlinkHover = (linkId: string, hasXmlNs: boolean): XmlComponent =>
new BuilderElement({
name: "a:hlinkHover",
attributes: {
...(hasXmlNs
? {
xmlns: {
key: "xmlns:a",
value: "http://schemas.openxmlformats.org/drawingml/2006/main",
},
}
: {}),
id: {
key: "r:id",
value: `rId${linkId}`,
},
},
});

View File

@ -1,19 +1,22 @@
import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_docPr_topic_ID0ES32OB.html
import { IContext, IXmlableObject, NextAttributeComponent, XmlComponent } from "@file/xml-components";
import { ConcreteHyperlink } from "@file/paragraph";
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",
};
}
import { createHyperlinkClick } from "./doc-properties-children";
// <complexType name="CT_NonVisualDrawingProps">
// <sequence>
// <element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1" />
// <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1" />
// </sequence>
// <attribute name="id" type="ST_DrawingElementId" use="required" />
// <attribute name="name" type="xsd:string" use="required" />
// <attribute name="descr" type="xsd:string" use="optional" default="" />
// <attribute name="hidden" type="xsd:boolean" use="optional" default="false" />
// </complexType>
export interface DocPropertiesOptions {
readonly name: string;
@ -26,12 +29,39 @@ export class DocProperties extends XmlComponent {
super("wp:docPr");
this.root.push(
new DocPropertiesAttributes({
id: uniqueNumericId(),
name,
description,
title,
new NextAttributeComponent({
id: {
key: "id",
value: uniqueNumericId(),
},
name: {
key: "name",
value: name,
},
description: {
key: "descr",
value: description,
},
title: {
key: "title",
value: title,
},
}),
);
}
public prepForXml(context: IContext): IXmlableObject | undefined {
for (let i = context.stack.length - 1; i >= 0; i--) {
const element = context.stack[i];
if (!(element instanceof ConcreteHyperlink)) {
continue;
}
this.root.push(createHyperlinkClick(element.linkId, true));
break;
}
return super.prepForXml(context);
}
}