feat: Support Links in Exported SVG (#4791)

This commit is contained in:
Jesse Jurman 2022-02-25 15:42:10 -05:00 committed by GitHub
parent bd35b682fa
commit 46e43baad1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 7 deletions

View File

@ -836,6 +836,18 @@ export const renderElementToSvg = (
const cy = (y2 - y1) / 2 - (element.y - y1); const cy = (y2 - y1) / 2 - (element.y - y1);
const degree = (180 * element.angle) / Math.PI; const degree = (180 * element.angle) / Math.PI;
const generator = rsvg.generator; 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) { switch (element.type) {
case "selection": { case "selection": {
// Since this is used only during editing experience, which is canvas based, // Since this is used only during editing experience, which is canvas based,
@ -863,7 +875,7 @@ export const renderElementToSvg = (
offsetY || 0 offsetY || 0
}) rotate(${degree} ${cx} ${cy})`, }) rotate(${degree} ${cx} ${cy})`,
); );
svgRoot.appendChild(node); root.appendChild(node);
break; break;
} }
case "line": case "line":
@ -898,7 +910,7 @@ export const renderElementToSvg = (
} }
group.appendChild(node); group.appendChild(node);
}); });
svgRoot.appendChild(group); root.appendChild(group);
break; break;
} }
case "freedraw": { case "freedraw": {
@ -923,7 +935,7 @@ export const renderElementToSvg = (
path.setAttribute("fill", element.strokeColor); path.setAttribute("fill", element.strokeColor);
path.setAttribute("d", getFreeDrawSvgPath(element)); path.setAttribute("d", getFreeDrawSvgPath(element));
node.appendChild(path); node.appendChild(path);
svgRoot.appendChild(node); root.appendChild(node);
break; break;
} }
case "image": { case "image": {
@ -944,7 +956,7 @@ export const renderElementToSvg = (
symbol.appendChild(image); symbol.appendChild(image);
svgRoot.prepend(symbol); root.prepend(symbol);
} }
const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use"); const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use");
@ -965,7 +977,7 @@ export const renderElementToSvg = (
}) rotate(${degree} ${cx} ${cy})`, }) rotate(${degree} ${cx} ${cy})`,
); );
svgRoot.appendChild(use); root.appendChild(use);
} }
break; break;
} }
@ -1012,7 +1024,7 @@ export const renderElementToSvg = (
text.setAttribute("direction", direction); text.setAttribute("direction", direction);
node.appendChild(text); node.appendChild(text);
} }
svgRoot.appendChild(node); root.appendChild(node);
} else { } else {
// @ts-ignore // @ts-ignore
throw new Error(`Unimplemented type ${element.type}`); throw new Error(`Unimplemented type ${element.type}`);

View File

@ -37,3 +37,8 @@ export const diamondFixture: ExcalidrawElement = {
...elementBase, ...elementBase,
type: "diamond", type: "diamond",
}; };
export const rectangleWithLinkFixture: ExcalidrawElement = {
...elementBase,
type: "rectangle",
link: "excalidraw.com",
};

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,10 @@
import { NonDeletedExcalidrawElement } from "../../element/types"; import { NonDeletedExcalidrawElement } from "../../element/types";
import * as exportUtils from "../../scene/export"; import * as exportUtils from "../../scene/export";
import { diamondFixture, ellipseFixture } from "../fixtures/elementFixture"; import {
diamondFixture,
ellipseFixture,
rectangleWithLinkFixture,
} from "../fixtures/elementFixture";
describe("exportToSvg", () => { describe("exportToSvg", () => {
const ELEMENT_HEIGHT = 100; const ELEMENT_HEIGHT = 100;
@ -112,4 +116,13 @@ describe("exportToSvg", () => {
); );
expect(svgElement.innerHTML).toMatchSnapshot(); 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();
});
}); });