Open ittayd opened 2 years ago
Hi @ittayd the distinction between SVG documents and SVG fragments embedded into HTML documents is not imposed by TiddlyWiki, it is how SVG works. The SVG spec does not permit the contents of an embedded SVG document to be styled via external CSS.
TiddlyWiki prefers to use embedded SVG fragments precisely because they are styleable, and not sandboxed like images.
I had a quick search for resources explaining the difference and found this that looks helpful:
https://www.oreilly.com/library/view/modern-svg/9781492048527/ch01.html
I'm not sure I follow. The Viz plugin (for graphviz diagrams) produces SVG snippets and I was able to style them. The mermaid plugin also styles the SVG snippets it produces.
Here is my stylesheet (a $:/tags/Stylesheet tiddler):
`
.viz :is(polygon[fill="none"][stroke="#000000"], ellipse) {
fill: <
.viz :is(path[stroke="#000000"], polyline[fill="none"][stroke="#000000"]) {
stroke: <
.viz :is(polygon[fill="#000000"][stroke="#000000"]) {
fill: <
.viz > svg > g > polygon[fill="#ffffff"] {
fill: <
I'm not sure I follow. The Viz plugin (for graphviz diagrams) produces SVG snippets and I was able to style them. The mermaid plugin also styles the SVG snippets it produces.
From your CSS it looks like viz is producing SVG fragments, which are displayed within an HTML document, and thus can be styled by the CSS associated with the document.
I think you are asking for the same styling capability to be available for SVG images (ie complete SVG documents), but that is not possible with the current SVG specification.
I think you are asking for the same styling capability to be available for SVG images (ie complete SVG documents), but that is not possible with the current SVG specification.
I think he is asking for a "convenient workflow" that should be supported by TW out of the box.
As I do understand it.
image/svg+xml
[img[myDiagram.svg]]
[img width=100; [myDiagram.svg]]
type
field is removed from the myDiagram.svg tiddler, the diagram is treated as wikitext
[img[xx]]
does not work anymore{{myDiagram}}
class
Since it should be possible to easily modify images even if they are already included into TW, we do have a major conflict now. ... The workflow got complicated and involves a lot of manual work, to make the systems compatible.
I think that's the main problems he faces. ... I do understand that, because from time to time I do have a similar problem with SVGs and Inkscape SVG program. ... I don't have a solution, but some ideas.
[svg[]]
link, that also allows styling as done with the image link [img[]]
I think option 1 would be the simplest one.
No promises --- Just some thoughts.
Hi @pmario in general it is not possible to automatically convert a self-contained SVG image into an embeddable SVG fragment.
The problem is that SVG images use IDs to reference gradients and other resources within the files. The IDs are defined by the image program to be unique within the image, but there's no guarantee that they will be unique when multiple images are merged into the same document.
@ittayd .. Which types of diagrams do you use from draw.io?
The problem is that SVG images use IDs to reference gradients and other resources within the files. The IDs are defined by the image program to be unique within the image, but there's no guarantee that they will be unique when multiple images are merged into the same document.
That's right. I did have a look at some SVG exports. They do use IDs ... But I think we can ask them, how they are produced and if they could be UUIDs ... would be worth a try.
I'm using fragments then. There are actually 3 use cases that I have: draw.io (use draw.io's 'embed svg' export, copy & paste), viz, mermaid where the last two create the SVG. Would be good to be able to style & include all.
And if self-contained images cannot be styled, then maybe there should be a way to treat fragements differently (different content type, an [embed-svg[]] inclusion)
TiddlyWiki prefers to use embedded SVG fragments precisely because they are styleable, and not sandboxed like images.
I didn't understand this, if I take an SVG fragment and paste it into a tiddler, then TW5 will render it as an image blob instead of leaving it as is. So it seems to me TW5 prefers to use SVGs as documents, and thus doesn't allow styling.
I didn't understand this, if I take an SVG fragment and paste it into a tiddler, then TW5 will render it as an image blob instead of leaving it as is. So it seems to me TW5 prefers to use SVGs as documents, and thus doesn't allow styling.
How does one of your SVG fragments look like?
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="121px" viewBox="-0.5 -0.5 121 61">
<defs/>
<g>
<rect x="0" y="0" width="120" height="60" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 30px; margin-left: 1px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tiddlywiki</div>
</div>
</div>
</foreignObject>
<text x="60" y="34" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tiddlywiki</text>
</switch>
</g>
</g>
<switch>
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
<a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
<text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text>
</a>
</switch>
</svg>
That should be the one we fixed with https://tiddlywiki.com/prerelease already. It will be implemented as an SVG fragment and it can be rendered now.
@pmario, can you point to the details of the change? I know of the fixes for the namespace (thanks!), but was not aware that using in a tiddler (with a content type and nice way to include) is also supported
That's the PR https://github.com/Jermolene/TiddlyWiki5/pull/6755 .. It was a low level fix for using inline SVGs. So it should fix it everywhere. ... If not, you should create a new issue.
TW does all the DOM handling itself using widgets. ... That allows us to use dynamic refresh if any tiddler is changed. If that tiddler isn't shown at the moment -- no refresh needed.
The specific problem was, that we did assign an SVG namespace to HTML elements, which the browser did ignore .... silently. ... It didn't show the element. That was the problem you found out. ... the hard way ;)
@pmario please See the image (I used the empty wiki linked from the prerelease page). The SVG is rendered as an image blob when using the content type image/svg+xml. If I don't use the content type, it is rendered as an inline SVG, but then I can't use it elsewhere with [img[]]. I can use transclusion but then can't set the height, width or class.
Which browser do you use? I'm using FF latest
NO content type
As I wrote in my "workflow" description. If it is type=image/svg+xml we can use [img[]]
links.
If it is text/vnd.tiddlywiki
it can be used as an "inline svg" ... BUT we can't use image links anymore. We have to use transclusions or macros to include them. As described in: https://github.com/Jermolene/TiddlyWiki5/issues/6730#issuecomment-1162887928 and the following posts
@pmario indeed, if I don't specify the content type, then the tiddler is rendered with an inline SVG. But, I can't use it in other tiddlers with [img[]], only transclusion, which doesn't allow me to specify height / width or class.
The ask here is to get both: so the tiddler content is rendered as an inline SVG and that it can be included with image links.
OK. The way I would go now, from all the info I know about your workflow.
4 tiddlers. The zip contains the tiddlers I did test it
data-class
since data-tag is used by the TW core already. But the docs is the same, since the mechanism is the same. It depends on you, if you want to with tags or titles for styling. The mechanism should give maximum flexibility by minimum maintenance. If you put some thought into the style definitions and the possibilities custom styling using data-tags give us.
title: svg-styles
tag: $:/tags/Stylesheet
[data-class="test.svg"] svg {
border: 2px solid pink;
width: 200px;
height: 300px;
}
[data-class="a-tag"] svg {
border: 2px solid green;
width: 160px;
padding: 20px;
}
title: svg-macros
tags: $:/tags/Macro
\define xsvg(title)
\whitespace trim
<div data-class=<<__title__>> >
<$transclude tiddler=<<__title__>> />
</div>
\end
\define tsvg(title)
\whitespace trim
<div data-class={{$title$!!tags}} >
<$transclude tiddler=<<__title__>> />
</div>
\end
title: test-tiddler
The xsvg macro uses the tiddler title to define the `data-class` attribute
<<xsvg "test.svg">>
The tsvg macro uses the SVG tiddler tags to define the `data-class` attribute
<<tsvg "test.svg">>
Thanks and that is what I'm doing, but it is not as comfortable as using a content type and [img[]] directive (which is ease of use as well)
Note that things like height and width are not so easy since there are no such attributes for a div, so need to revert to using an element style (when it's a per instance and not some global styling), which is cumbersome
Note that things like height and width are not so easy since there are no such attributes for a div, so need to revert to using an element style (when it's a per instance and not some global styling), which is cumbersome
Every element can use width and height but in this case we have to be more specific, since SVG has width and height attributes set. So it won't inherit those settings from it's DIV parent. ...
This specificity can be changed, if the SVG would have a class
attribute. But if we don't want to manually adjust the SVG it has to be done as in the example.
Thanks and that is what I'm doing, but it is not as comfortable as using a content type and [img[]] directive (which is ease of use as well)
The content type image/svg+xml is an official MIME-type that is part of the image main types browsers can handle ... Those image main types can all be used, using the html <img>
element. Since different image files like JPG, PNG and SVG have fundamentally different content, browsers need a specification how to deal with that content. ...
Since we want to be able to use the [img[xxx]]
wikitext link with different image formats we use the <img>
element. If that IMG element is used every browser will encode the image into a img:data element. We CAN NOT change that.
If we want to use SVG as inline SVG we can either create some macros, as I did here, or we can create a new [svg[xx]]
image link, that can only handle inline SVGs.
As Jeremy pointed out at: https://github.com/Jermolene/TiddlyWiki5/issues/6758#issuecomment-1175982429 it's not possible to directly use every SVG as an inline SVG, since there are some attributes like IDs that will cause problems.
TW uses handcrafted SVGs for all icons, because we can style them. We can control how those SVGs look like. ... BUT ... we can not control, how SVGs look, that are imported by users.
If they want to use it with [img[]]
links we use the IMG html element and the browser deals with it. ... No problems
If users want to use inline SVGs so they can use CSS for styling, they have to use macros and they have to take care, that the SVG content doesn't cause problems. ...
period
According to MDN, div doesn't support height/width attributes (not talking about css properties).
Can't TW invent a mime type (much like for tiddlers) for inline SVGs (or, "svgs that TW should not convert to img with blob")? Maybe then TW can know how to treat them when included through [img[]]
I am interested in using .SVG files and inline SVG+XML content soon to build UIs with TW. I'll check into this. It wouldn't really be hard to write an [svg[]]
widget that would allow you to wrap the transcluded svg in an element in order to style it.
I am interested in using .SVG files and inline SVG+XML content soon to build UIs with TW. I'll check into this. It wouldn't really be hard to write an [svg[]] widget that would allow you to wrap the transcluded svg in an element in order to style it.
That's true. But the devil is in the details. See: https://github.com/Jermolene/TiddlyWiki5/issues/6758#issuecomment-1175982429
@pmario After some SVG research, it seems like TW already has the capacity to make IDs unique because we parse the raw HTML/SVG code and use widgets to render it. Appending the tiddler-title to each ID would be a safe enough fix. Even if the tiddler is transcluded mutliple times, the "(non)unique IDs" all point to the right data. Another idea would be to internally use the <<qualify>>
functionality to generate a unique-to-the-widget-tree-position ID.
Another idea would be to internally use the
<<qualify>>
functionality to generate a unique-to-the-widget-tree-position ID.
The <<qualify>>
function can only create a uniqe name on the tiddler level, and not on the widget level
@pmario which is why appending the "title of the SVG tiddler" to all the IDs inside the SVG is the way to start, and I honestly think that can be done at render time. That should be enough to make it work. For example, if you translcude [[ThisIcon.svg]]
around all over the place, but all of the IDs inside read ThisIcon.svg/ID####
, then anytime that specific ID is called as url(ID)
, the DOM will pick up the first one rendered with id="ThisIcon.svg/ID####"
and find the "right" gradient, effect, etc. I will do some more research.
@pmario After some SVG research, it seems like TW already has the capacity to make IDs unique because we parse the raw HTML/SVG code and use widgets to render it. Appending the tiddler-title to each ID would be a safe enough fix. Even if the tiddler is transcluded mutliple times, the "(non)unique IDs" all point to the right data. Another idea would be to internally use the
<<qualify>>
functionality to generate a unique-to-the-widget-tree-position ID.
Hi @joshuafontany it is correct that we can construct SVG fragments that use wikitext features to ensure unique IDs, and it is a useful technique (I did some work on wikitext generation of SVGs here).
But the problem in the OP is the desire to be able to use already existing SVG images that expect to be viewed as an image as SVG fragments that expect to be embedded in HTML. The implication is that we'd need a process to automatically qualify the IDs referred to in the SVG. Way back in 2011/12 I did experiment with something along those lines as part of TW5, but found that a general purpose, universal solution would be too complicated to be able to explain to end users.
I think there's scope for tools to help with the conversion process, but I'd be more hopeful that they would take the form of interactive authoring aids, rather than attempting solve the problem in a general way.
@Jermolene, you're right about the id references that are inside the svg already.
I encountered it with the mermaid plugin that used mermaid.js that doesn't qualify ids. I ended up solving this by modifying the widget to put the svg inside a shadow dom.
That created another problem which is that this dom doesn't have the styling tiddlers. It's on my todo list to have the widget pull them, but it'll be nice if this wrapping and pulling will be part of tw5, so everyone can use it in a consistent way.
Is your feature request related to a problem? Please describe. SVGs seem to be second class to images in TW5. In particular, a tiddler with content type image/svg+xml is rendered as an image with a data blob as its src instead of the SVG as is. Using the SVG in other tiddlers through [img[]] has the same result.
In particular, this means SVGs cannot be styled
Describe the solution you'd like A tiddler with content type image/svg+xml will be rendered as an SVG DOM. An [svg[]] way of including SVGs in other tiddlers (does it make sense to make the [[]] format be open to extention with more types ?)
Describe alternatives you've considered There is a workaround which is to not use the correct content type and use transclusion, but that more awkward (in particular since transclusion doesn't allow to set dimensions or class, so a wrapper is required to achieve those)