Graphviz SVG for Obsidian

Hi –

I need to get the SVG generation of graphviz to work better for the macos obsidian app. The problem appear to be that html anchor elements ("<a …>") use “xlink:href” instead of plain old “href=”, and that the graphviz “class=” directives need to annotate the

Mermaid generates this, which does the url correctly, but apparently can’t be correctly css styled:

<g class="node default internal-link" id="flowchart-C-3586" transform="translate(297.81249237060547, 36.0000057220459)">
<rect class="basic label-container" style="" rx="0" ry="0" x="-85.75" y="-28.0000057220459" width="171.5" height="56.0000114440918"></rect>
<g class="label" style="" transform="translate(-78.25, -20.5000057220459)">
<foreignObject width="156.5" height="41.0000114440918">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">
<a class="internal-link" href="cooperation">cooperation</a>
</div></foreignObject></g></g>

Graphviz generates this, which does annotate the url correctly, but has all the correct css styling:

<g id="node21" class="node">
<title>OUT2</title>
<g id="a_node21"><a xlink:href="cooperation" xlink:title=" &nbsp;BASIC CATEGORY THEORY &nbsp;" target="_top">
<polygon fill="none" stroke="red" stroke-width="3" points="720.07,-647.48 510.07,-647.48 510.07,-611.48 720.07,-611.48 720.07,-647.48"></polygon>
<text text-anchor="middle" x="615.07" y="-625.78" font-family="Times,serif" font-size="14.00" fill="blue"> &nbsp;BASIC CATEGORY THEORY &nbsp;</text>
</a>
</g>
</g>

Hacking the graphviz generated SVG to this worked:

<g id="node21" class="node **default internal-link**">
<title>OUT2</title>
<g id="a_node21"><a xlink:title=" &nbsp;BASIC CATEGORY THEORY &nbsp;" target="_top" **class="internal-link"** **href**="cooperation">
<polygon fill="none" stroke="red" stroke-width="3" points="720.07,-647.48 510.07,-647.48 510.07,-611.48 720.07,-611.48 720.07,-647.48"></polygon>
<text text-anchor="middle" x="615.07" y="-625.78" font-family="Times,serif" font-size="14.00" fill="blue"> &nbsp;BASIC CATEGORY THEORY &nbsp;</text>
</a>
</g>
</g>

where the changes are in **bold**.

How should I go about making this change? Where in the source code should I look?

Thanks!

– Perry

the svg generator is here: plugin/core/gvrender_core_svg.c

The gitlab repo search is horrible, so I wasn’t able to find it until I got even more persistent.

Thanks!

Should I make my own fork of graphviz, or try to modify the existing graphviz to have this option?

I got the fix to work, now I need to do it for only the urls that are obsidian internal-links.

What would be the best way to implement this node definition:

  OUT2 [obsidian-internal-link, label="  THEORY  ", URL="cooperation"];

Main problem is that anchor emitters aren’t provided any information about the obj being rendered.

Threading that parameter into the begin_anchor functions would be messy, but it might be the way to do it?

What’s the thinking on this sort of thing?

Why do you want to replace xlinkhref with href?

Because obsidian doesn’t do internal links with xlink:href anchors, only href.

(I don’t know much about this topic) are hrefs more legit than xlink:href? Why does obsidian not handle xlink:href? Is href better than xlink:href?

Dunno. I get no response when I ask obsidian devs about that. I just have to work with how it is.

Why is the “xlink:” stuff generated?

It appears that href may be preferable to xlink:href in future versions of SVG.

I doubt there were any deep reasons for however we designed gvrender_core_svg.c (speaking as its primary author). Graphviz was an early adopter of SVG and there’s certainly some unnecessary baggage. Also in general XML is sort of the light that failed, isn’t it, though the SVG rendering model has preserved the best of why we liked PostScript, so much, right?

At this point any proposed change needs to be tested against the popular SVG rendering programs, or maybe it’s possible to emit both xlink:href and href for more compatibility.

Obsidian also requires "class=“internal-link” on the html/svg anchor.

I propose (but see below) something like a “obsidian-internal-link=true” argument (but without hyphens) on graphviz node (and whatever else can have “URL=” parameters) definitions to cause the emitted html/svg anchor to emit the anchor with both the addition of the above “class=” and the replacement of “xlink:html=” with “html” for that one anchor.

Actually there are two layers of “<g …>” produced surrounding the anchor, and I’m uncertain that I am covering all the cases in the seeming mess I produced. I’m planning to make another stab at it tonight.

I expect Graphviz to outlast Obsidian, so I don’t think im keen to have an obsidian-specific attribute name.

You can set class on nodes today. Maybe if href is preferred to xlink:href we could switch over entirely

Well right now, you can’t annotate svg anchors with “class=” (only the surrounding “<g …>” gets annotated), which is the actual thing needed, if you can do “href=”.

I guess I’m proposing two separate changes:

    • Permit “xlink:href=” to be changed to “href=”.
    • Permit svg anchors to have “class=”.

Yes, if preferred in the SVG standard, I would adhere to that.

I’d be in favor of unconditionally updating the href output from xlink:href to just use “href”, following the guidance Stephen posted on MDN. Feel free to mail a merge request about it, might need some tests updated too, and a changelog.md entry.

How about annotating anchors with the classlist specified in the node (and whatever) declaration?

Its there, so far, in “job”:

svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target,
                 char *id) {

but right now svg_begin_anchor does NOT generate a “class=” parameter for the anchor, but I have figured out how to do it:

  if ((str = agget(job->obj->u.n, "class")) && str[0]) {

If everything is “href=” instead of “xlink:href=”, then I’m done.

Is there a reason for the anchor to not inherit the classes?

Searching for “xlink:xref” yields a lot of tests, but more notably, a number of usages not in anchors. How to handle that?

Lots of these:

rtest/linux.x86/cairo_dot_cairo.svg:  <use xlink:href="#glyph0-1" x="741" y="25.699219"/>

but it looks like graphviz doesn’t generate “<use”?

My proposed href= fix is here:
https://github.com/wagle/graphviz/commit/233f554edb1b705b068c4cabd7e4ea39f561cec9

following that is my proposed class= fix:
https://github.com/wagle/graphviz/commit/67c1c24e6245a1cd0da4f2b813109f26c4976c7b

I’m not seeing how to convince my gitlab mirror to display these two diffs or to submit them as pull requests.

My gitlab repo (mirror of my github) is here (if that helps):
https://gitlab.com/cognodica/graphviz

What else would you like me to do, like modifying the testing, etc?

Where do I mail the merge requests?

I don’t know how you all handle “new features”.