ocsigen / tyxml

Build valid HTML and SVG documents
https://ocsigen.org/tyxml/
Other
163 stars 57 forks source link

Error "Unknown attribute in SVG element: stddeviation" when using ppx #307

Closed mooreryan closed 9 months ago

mooreryan commented 2 years ago

I have a preexisting SVG that I would like to process with the tyxml ppx. However, when doing so I get an error: Error: Unknown attribute in SVG element: stddeviation.

I'm not sure if this is a bug or if I'm misunderstanding something about the ppx.

Here is a tiny example to reproduce the problem.


I have this code (just a tiny example) that makes part of an svg and sticks it into a div. (The created html is a stand in for the actual svg that I would like to process.)

open Tyxml

let v =
  Html.div
    [
      Html.svg
        [
          Svg.defs
            [
              Svg.filter
                [
                  Svg.feGaussianBlur
                    ~a:[ Svg.a_in `SourceAlpha; Svg.a_stdDeviation (1.0, None) ]
                    [];
                ];
            ];
        ];
    ]

It compiles fine, and when I write it out to a string I get this html:

<div>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <defs>
      <filter>
        <feGaussianBlur in="sourceAlpha" stdDeviation="1"></feGaussianBlur>
      </filter>
    </defs>
  </svg>
</div>

When I read that html back in using the ppx like this:

let _y =
  [%html
    {|
<div>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <defs>
      <filter>
        <feGaussianBlur in="sourceAlpha" stdDeviation="1"></feGaussianBlur>
      </filter>
    </defs>
  </svg>
</div>
|}]

I get an error:

Error: Unknown attribute in SVG element: stddeviation
Drup commented 2 years ago

hmm, that might be due to some over-enthusiastic case normalisation ...

mooreryan commented 2 years ago

I looked into this some more and found that the Markup code either parsing or writing html (not sure yet which) is lowercasing the stddeviation, but not feGaussianBlur. Here is an example:

let () =
  let open Markup in
  string {|<feGaussianBlur in="sourceAlpha" stdDeviation="1"></feGaussianBlur>|}
  |> parse_html |> signals |> pretty_print |> write_html
  |> to_channel Out_channel.stdout

Which outputs:

<feGaussianBlur in="sourceAlpha" stddeviation="1"></feGaussianBlur>

I will continue to look into it.

mooreryan commented 2 years ago

I may have found the source of the problem. I noticed in the above example switching from parse_html to parse_xml works.

The tyxml-ppx uses Markup.parse_html.

https://github.com/ocsigen/tyxml/blob/47423cf70b804c67386583a9b7eccd9157316475/ppx/tyxml_ppx.ml#L291

Here are some links to lines in a couple of files showing what I think may be going on.

If you look in Markup.parse_html function, you will see a spot in which the attributes either get pushed through here, or adjusted with adjust_svg_attributes (here).

If you look at the adjust_svg_attributes function, it fixes the case of the stdDeviation attribute here.

I think the lowercasing comes in around here. In contrast, the xml_parser is fine for that toy example, because it doesn't lowercase anything first (I think...).

(Sorry for the mess of links!)


Anyway, I think that may be what's causing the issue here....

maurobringolf commented 1 year ago

Thanks for all the hints @mooreryan, I started looking into this issue as well because I tried parsing an <svg viewBox="...">...</svg> with tyxml-ppx.

I describe my findings here https://github.com/aantron/markup.ml/pull/69.

Drup commented 9 months ago

It looks like this is solved in markup, closing !