Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrading to mermaid 10.6.1 breaks the sequence diagram parsing logic #38

Closed
zsviczian opened this issue Nov 22, 2023 · 2 comments
Closed

Comments

@zsviczian
Copy link
Contributor

zsviczian commented Nov 22, 2023

@ad1992, I use the mermaid object that comes with Obsidian. Obsidian upgraded to 10.6.1 which broke the sequence diagram parsing logic.
I am sharing my solution here, so when you eventually upgrade mermaid-to-excalidraw to mermaid 10.6.1 you don't need to go through the same debugging.
Look for the lines with //zsviczian
Essentially the sequence of elements changed in the SVG file and lineNode = topRootNode.previousElementSibling as SVGLineElement; returns null. Also the logic for avoiding the overlapping vertical line changed...
I hope you find this helpful.

const parseActor = (actors: { [key: string]: Actor }, containerEl: Element) => {
  const actorRootNodes = Array.from(containerEl.querySelectorAll(".actor"))
    .filter((node) => node.tagName === "text")
    .map((actor) => actor.tagName === "text" && actor.parentElement);
  const lineNodes = containerEl.querySelectorAll("line"); //zsviczian
  const nodes: Array<Node[]> = [];
  const lines: Array<Line> = [];
  const actorsLength = Object.keys(actors).length;
  Object.values(actors).forEach((actor, index) => {
    //@ts-ignore
    // For each actor there are two nodes top and bottom which is connected by a line
    const topRootNode = actorRootNodes[index] as SVGGElement;
    //@ts-ignore
    const bottomRootNode = actorRootNodes[actorsLength + index] as SVGGElement;

    if (!topRootNode) {
      throw "root not found";
    }
    const text = actor.description;
    if (actor.type === "participant") {
      // creating top actor node element
      const topNodeElement = createContainerElement(
        topRootNode.firstChild as SVGSVGElement,
        "rectangle",
        { id: `${actor.name}-top`, text, subtype: "actor" }
      );
      if (!topNodeElement) {
        throw "Top Node element not found!";
      }
      nodes.push([topNodeElement]);

      // creating bottom actor node element
      const bottomNodeElement = createContainerElement(
        bottomRootNode.firstChild as SVGSVGElement,
        "rectangle",
        { id: `${actor.name}-bottom`, text, subtype: "actor" }
      );
      nodes.push([bottomNodeElement]);

      // Get the line connecting the top and bottom nodes. As per the DOM, the line is rendered as first child of parent element
      const lineNode = lineNodes[index]; //zsviczian

      if (lineNode?.tagName !== "line") {
        throw "Line not found";
      }
      const startX = Number(lineNode.getAttribute("x1"));
      if (!bottomNodeElement.height) { //zsviczian
        throw "Bottom node element height is null";
      }
      const startY = topNodeElement.y; //zsviczian
      // Make sure lines don't overlap with the nodes, in mermaid it overlaps but isn't visible as its pushed back and containers are non transparent
      const endY = bottomNodeElement.y + bottomNodeElement.height; //zsviczian
      const endX = Number(lineNode.getAttribute("x2"));
      const line = createLineElement(lineNode, startX, startY, endX, endY);
      lines.push(line);
    } else if (actor.type === "actor") {
      const topNodeElement = createActorSymbol(topRootNode, text, {
        id: `${actor.name}-top`,
      });
      nodes.push(topNodeElement);
      const bottomNodeElement = createActorSymbol(bottomRootNode, text, {
        id: `${actor.name}-bottom`,
      });
      nodes.push(bottomNodeElement);

      // Get the line connecting the top and bottom nodes. As per the DOM, the line is rendered as first child of parent element
      const lineNode = lineNodes[index]; //zsviczian

      if (lineNode?.tagName !== "line") {
        throw "Line not found";
      }
      const startX = Number(lineNode.getAttribute("x1"));
      const startY = Number(lineNode.getAttribute("y1"));

      const endX = Number(lineNode.getAttribute("x2"));
      // Make sure lines don't overlap with the nodes, in mermaid it overlaps but isn't visible as its pushed back and containers are non transparent
      const bottomEllipseNode = bottomNodeElement.find(
        (node): node is Container => node.type === "ellipse"
      );
      if (bottomEllipseNode) {
        const endY = bottomEllipseNode.y;
        const line = createLineElement(lineNode, startX, startY, endX, endY);
        lines.push(line);
      }
    }
  });
@ad1992
Copy link
Member

ad1992 commented Nov 27, 2023

Hi @zsviczian 👋🏻 just back from time off, yes the sequence diagrams ordering was updated, I had already fixed the issue in mermaid js here and now it works absolutely fine, however, I am waiting for them to ship the next release, so I will either release it from fork if needed (in case the official release is delayed). So the above patch won't be needed.

@ad1992
Copy link
Member

ad1992 commented Apr 16, 2024

This has been fixed in the latest version so closing

@ad1992 ad1992 closed this as completed Apr 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants