소스 검색

feat: Support Links in Exported SVG (#4791)

Jesse Jurman 3 년 전
부모
커밋
46e43baad1
4개의 변경된 파일53개의 추가작업 그리고 7개의 파일을 삭제
  1. 18 6
      src/renderer/renderElement.ts
  2. 5 0
      src/tests/fixtures/elementFixture.ts
  3. 16 0
      src/tests/scene/__snapshots__/export.test.ts.snap
  4. 14 1
      src/tests/scene/export.test.ts

+ 18 - 6
src/renderer/renderElement.ts

@@ -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 - 0
src/tests/fixtures/elementFixture.ts

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

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 16 - 0
src/tests/scene/__snapshots__/export.test.ts.snap


+ 14 - 1
src/tests/scene/export.test.ts

@@ -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();
+  });
 });

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.