feat: Support Links in Exported SVG (#4791)
This commit is contained in:
parent
bd35b682fa
commit
46e43baad1
@ -836,6 +836,18 @@ export const renderElementToSvg = (
|
||||
const cy = (y2 - y1) / 2 - (element.y - y1);
|
||||
const degree = (180 * element.angle) / Math.PI;
|
||||
const generator = rsvg.generator;
|
||||
|
||||
// element to append node to, most of the time svgRoot
|
||||
let root = svgRoot;
|
||||
|
||||
// if the element has a link, create an anchor tag and make that the new root
|
||||
if (element.link) {
|
||||
const anchorTag = svgRoot.ownerDocument!.createElementNS(SVG_NS, "a");
|
||||
anchorTag.setAttribute("href", element.link);
|
||||
root.appendChild(anchorTag);
|
||||
root = anchorTag;
|
||||
}
|
||||
|
||||
switch (element.type) {
|
||||
case "selection": {
|
||||
// Since this is used only during editing experience, which is canvas based,
|
||||
@ -863,7 +875,7 @@ export const renderElementToSvg = (
|
||||
offsetY || 0
|
||||
}) rotate(${degree} ${cx} ${cy})`,
|
||||
);
|
||||
svgRoot.appendChild(node);
|
||||
root.appendChild(node);
|
||||
break;
|
||||
}
|
||||
case "line":
|
||||
@ -898,7 +910,7 @@ export const renderElementToSvg = (
|
||||
}
|
||||
group.appendChild(node);
|
||||
});
|
||||
svgRoot.appendChild(group);
|
||||
root.appendChild(group);
|
||||
break;
|
||||
}
|
||||
case "freedraw": {
|
||||
@ -923,7 +935,7 @@ export const renderElementToSvg = (
|
||||
path.setAttribute("fill", element.strokeColor);
|
||||
path.setAttribute("d", getFreeDrawSvgPath(element));
|
||||
node.appendChild(path);
|
||||
svgRoot.appendChild(node);
|
||||
root.appendChild(node);
|
||||
break;
|
||||
}
|
||||
case "image": {
|
||||
@ -944,7 +956,7 @@ export const renderElementToSvg = (
|
||||
|
||||
symbol.appendChild(image);
|
||||
|
||||
svgRoot.prepend(symbol);
|
||||
root.prepend(symbol);
|
||||
}
|
||||
|
||||
const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use");
|
||||
@ -965,7 +977,7 @@ export const renderElementToSvg = (
|
||||
}) rotate(${degree} ${cx} ${cy})`,
|
||||
);
|
||||
|
||||
svgRoot.appendChild(use);
|
||||
root.appendChild(use);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1012,7 +1024,7 @@ export const renderElementToSvg = (
|
||||
text.setAttribute("direction", direction);
|
||||
node.appendChild(text);
|
||||
}
|
||||
svgRoot.appendChild(node);
|
||||
root.appendChild(node);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
throw new Error(`Unimplemented type ${element.type}`);
|
||||
|
5
src/tests/fixtures/elementFixture.ts
vendored
5
src/tests/fixtures/elementFixture.ts
vendored
@ -37,3 +37,8 @@ export const diamondFixture: ExcalidrawElement = {
|
||||
...elementBase,
|
||||
type: "diamond",
|
||||
};
|
||||
export const rectangleWithLinkFixture: ExcalidrawElement = {
|
||||
...elementBase,
|
||||
type: "rectangle",
|
||||
link: "excalidraw.com",
|
||||
};
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,6 +1,10 @@
|
||||
import { NonDeletedExcalidrawElement } from "../../element/types";
|
||||
import * as exportUtils from "../../scene/export";
|
||||
import { diamondFixture, ellipseFixture } from "../fixtures/elementFixture";
|
||||
import {
|
||||
diamondFixture,
|
||||
ellipseFixture,
|
||||
rectangleWithLinkFixture,
|
||||
} from "../fixtures/elementFixture";
|
||||
|
||||
describe("exportToSvg", () => {
|
||||
const ELEMENT_HEIGHT = 100;
|
||||
@ -112,4 +116,13 @@ describe("exportToSvg", () => {
|
||||
);
|
||||
expect(svgElement.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("with elements that have a link", async () => {
|
||||
const svgElement = await exportUtils.exportToSvg(
|
||||
[rectangleWithLinkFixture],
|
||||
DEFAULT_OPTIONS,
|
||||
null,
|
||||
);
|
||||
expect(svgElement.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user