SVG support
fdietze opened this issue · 21 comments
What needs to be done to support SVG? I'll need this soon.
Basically we'd need to define SVG tags and attributes in the same manner as we defined those for HTML elements. So in terms of types it's all very similar to what we already have.
If I recall correctly, ScalaTags already has those listings. I'm not sure how complete those are, as we saw we needed quite a bit of work to get its HTML attribute listings to our desired shape.
However, I haven't looked at SVG spec in detail. I don't know how complicated the types are, and whether we'd need reflected attributes for SVG elements.
So, in practical terms, to a first approximation, we need to:
- Create generic
svg/Attrs.scala
trait with typed listings of SVG attributes - Same for
svg/Tags.scala
(might need multiple files similar to how HTML tags are done) - Add JS-specific type aliases of the above to
jsdom/defs/package.scala
- Probably need a new key class:
SvgAttr
(I don't think we should reuse Attr for that), and a canonical builder for it (seecanonical
dir). Don't want to accidentally use SVG attrs on HTML elements, and without #13 not sure what else we can do. Not sure about this, and IIRC you're not using these concrete classes in Outwatch, so I guess I'll need to think about this some time later. - For the
Tag
class, I think no need to createSvgTag
, maybe Tag[SVGElement] would be enough. Not sure. - Lastly, we'd need to add SVG to the bundle in CompileTest. I think I'm ok allowing naming collisions between SVG and HTML, since most librarries will probably choose to namespace everything svg-related. Things within SVG should probably be free of collisions and follow the same naming guidelines as our HTML stuff
Unfortunately I don't think I'll have the time to do all this work any time soon (I also don't expect my own need for SVG in the next few months), so you'll need to carry the load on this one, sorry. I can still help with soft stuff like advice / reviews / design.
For reference: https://developer.mozilla.org/en-US/docs/Web/SVG
Thank you for the explanation, I will give it a try soon.
Would like to work on this together ,what's the current status?
Is it possible to provide some implicits and reuse part of scalatags
library?
@doofin Probably, but it would need to be part of your app, not part of SDT.
You can create a Modifier
that gets the JS DOM element created by ScalaTags and appends it to the given element in its apply
method. Then you could use that Modifier
as a child element in your code.
@doofin Nice, let's do that together. I think I will have some time tomorrow to start on a branch.
@raquo thanks! After adding svg support for scala dom types ,how to add that to laminar?
@doofin As a starting point, Laminar's bundle
object will need to include new svg traits, most probably in an inner svg
object to namespace things better.
Laminar will probably need a bunch of changes to introduce the distinction between DOM Elements and DOM HTMLElements. Some of those changes will actually need to happen in Scala DOM Builder, and maybe even also in Scala DOM TestUtils. I was anticipating an eventual need for this distinction from the very beginning and can deal with the Laminar / SDB side of things once the design of SVG support in SDT is established.
PS if borrowing code from ScalaTags please make sure to preserve any "MDN" marking in the comments – this is an indicator for a different license which we also honor in SDT's license.
@raquo Thanks,we do have to pay attention to license while using code from other project
I have added the svgAttrs file and a few props,please check their correctness
It seems that pull requests page is not a good place to put information,for that a merge would permanently close the pr,so I put everything here:
For reference:
- https://developer.mozilla.org/en-US/docs/Web/SVG
- SVG-Tags in scalatags with MDN documentation:
https://github.com/lihaoyi/scalatags/blob/44cbd0602d40186d33d39b8d4a259f681d2e4a3b/scalatags/shared/src/main/scala/scalatags/generic/SvgTags.scala - SVG tag to dom-type association in scalatags
https://github.com/lihaoyi/scalatags/blob/44cbd0602d40186d33d39b8d4a259f681d2e4a3b/scalatags/js/src/main/scala/scalatags/jsdom/SvgTags.scala
- (half finished) Create generic
svg/Attrs.scala
trait with typed listings of SVG attributes
(created : https://github.com/raquo/scala-dom-types/blob/svg/shared/src/main/scala/com/raquo/domtypes/generic/defs/attrs/svgAttrs.scala ) - Same for
svg/Tags.scala
(might need multiple files similar to how HTML tags are done)
(created: https://github.com/raquo/scala-dom-types/blob/svg/shared/src/main/scala/com/raquo/domtypes/generic/defs/tags/SvgTags.scala ) - Add JS-specific type aliases of the above to
jsdom/defs/package.scala
(https://github.com/raquo/scala-dom-types/blob/svg/js/src/main/scala/com/raquo/domtypes/jsdom/defs/package.scala) - Probably need a new key class:
SvgAttr
(I don't think we should reuse Attr for that), and a canonical builder for it (seecanonical
dir). Don't want to accidentally use SVG attrs on HTML elements, and without #13 not sure what else we can do. Not sure about this, and IIRC you're not using these concrete classes in Outwatch, so I guess I'll need to think about this some time later.
(Don't understand this point,Currently I am reusinglazy val accentHeight = stringAttr("accent-height")
,will there be problems?
) - For the
Tag
class, I think no need to createSvgTag
, maybe Tag[SVGElement] would be enough. Not sure.
(Currently as T[SvgElement]) - Lastly, we'd need to add SVG to the bundle in CompileTest. I think I'm ok allowing naming collisions between SVG and HTML, since most librarries will probably choose to namespace everything svg-related. Things within SVG should probably be free of collisions and follow the same naming guidelines as our HTML stuff
- SVG Namespaces? (No need to do this in domtypes?)
fixes #20
It seems that SVG Namespaces?
thing should be done in dom-builders and replace dom.document.createElement
with dom.document.createElementNs
?
Let's clear up the terminology first. When I said "choose to namespace everything svg-related" I meant that consuming libraries such as Scala DOM Builder and Laminar will be responsible for making an svg
object that would extend all the new traits you created.
Now there's also the XML/SVG namespacing that you're referring to now, let's think how to deal with that.
Dom Builder has a trait ElementApi
, which has a method def createNode[Ref <: BaseElementRef](element: N with Element[N, Ref, BaseRef]): Ref
. Despite a bit misleading name and type signature, we currently use it to create HTML elements only.
I think createNode should really be called createElement, and we need a new method called createElementNs that we would use for namespaced SVG. Now, JsElement
will probably need to become a trait that is extended by JsHtmlElement (same implementation as right now), and JsSvgElement (kind of the same as JsHtmlElement but calling the createElementNS method).
Roughly I think that's the idea. I didn't have a chance to look deeper into this yet, sorry.
@doofin So we will need to start working this up the chain to Scala DOM Builder, and at that point we will need to make a simple test, and for this I need an example SVG file from you. It should have a few different SVG elements in it (not more than 10), and those elements should have attributes which accept different kinds of values – for example numbers and strings, or I don't know, booleans? The more different types the better. This SVG file should render something obvious like maybe geometric shapes of various colors and sizes.
We will then take this SVG file and use it as a test case in Scala DOM Builder to make sure that our functionality works.