lpil / html-lustre-converter

HTML -> Lustre
https://lpil.github.io/html-lustre-converter/
29 stars 7 forks source link

Converting an SVG containing a `text` tag uses `element("text"...)` instead of `svg.text(...)` #14

Open guillheu opened 1 week ago

guillheu commented 1 week ago

When converting an SVG that contains text tags, the resulting gleam code uses element("text", [attributes], [html.text("Some text")]). The resulting page did not display any text in the SVG as a result. When manually replacing the offending instances with svg.text([attributes], "Some Text") the embedded text does display correctly.

lpil commented 1 week ago

Could you give an example please 🙏

guillheu commented 1 week ago

Given the following example from Excalidraw (font style defs omitted for brevity)

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250.61675521945938 133.23856582099086" width="250.61675521945938" height="133.23856582099086">
  <!-- svg-source:excalidraw -->
  <g stroke-linecap="round" transform="translate(10 10) rotate(0 115.30837760972969 56.61928291049543)">
    <path d="M28.31 0 C94.96 0.34, 163.03 1.53, 202.31 0 M28.31 0 C81.46 -0.32, 135.57 -1.03, 202.31 0 M202.31 0 C221.29 1.65, 228.68 9.01, 230.62 28.31 M202.31 0 C219.69 0.03, 228.55 8.12, 230.62 28.31 M230.62 28.31 C232.33 49.48, 232.53 70.53, 230.62 84.93 M230.62 28.31 C229.66 47.24, 229.52 65.01, 230.62 84.93 M230.62 84.93 C232.17 103.77, 220.17 114.73, 202.31 113.24 M230.62 84.93 C229.35 102.14, 220.61 114.96, 202.31 113.24 M202.31 113.24 C157.52 113.18, 111.5 116.09, 28.31 113.24 M202.31 113.24 C153.6 114.63, 106.88 113.53, 28.31 113.24 M28.31 113.24 C10.99 112.38, -1.57 105.09, 0 84.93 M28.31 113.24 C8.1 115.04, -1.36 101.51, 0 84.93 M0 84.93 C0.18 69.32, -0.09 50.99, 0 28.31 M0 84.93 C-0.87 68.18, 0.3 53.47, 0 28.31 M0 28.31 C1.78 11.07, 8.98 -1.79, 28.31 0 M0 28.31 C-1.04 9.6, 9.57 0.41, 28.31 0" stroke="#1971c2" stroke-width="4" fill="none">
    </path>
  </g>
  <g transform="translate(71.40218864488588 49.11928291049537) rotate(0 53.90618896484375 17.5)">
    <text x="53.90618896484375" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Example</text>
  </g>
</svg>

Running it through the converter generates the following code

svg.svg(
  [
    attribute("height", "133.23856582099086"),
    attribute("width", "250.61675521945938"),
    attribute("viewBox", "0 0 250.61675521945938 133.23856582099086"),
    attribute("xmlns", "http://www.w3.org/2000/svg"),
    attribute("version", "1.1"),
  ],
  [
    svg.g(
      [
        attribute(
          "transform",
          "translate(10 10) rotate(0 115.30837760972969 56.61928291049543)",
        ),
        attribute("stroke-linecap", "round"),
      ],
      [
        svg.path([
          attribute("fill", "none"),
          attribute("stroke-width", "4"),
          attribute("stroke", "#1971c2"),
          attribute(
            "d",
            "M28.31 0 C94.96 0.34, 163.03 1.53, 202.31 0 M28.31 0 C81.46 -0.32, 135.57 -1.03, 202.31 0 M202.31 0 C221.29 1.65, 228.68 9.01, 230.62 28.31 M202.31 0 C219.69 0.03, 228.55 8.12, 230.62 28.31 M230.62 28.31 C232.33 49.48, 232.53 70.53, 230.62 84.93 M230.62 28.31 C229.66 47.24, 229.52 65.01, 230.62 84.93 M230.62 84.93 C232.17 103.77, 220.17 114.73, 202.31 113.24 M230.62 84.93 C229.35 102.14, 220.61 114.96, 202.31 113.24 M202.31 113.24 C157.52 113.18, 111.5 116.09, 28.31 113.24 M202.31 113.24 C153.6 114.63, 106.88 113.53, 28.31 113.24 M28.31 113.24 C10.99 112.38, -1.57 105.09, 0 84.93 M28.31 113.24 C8.1 115.04, -1.36 101.51, 0 84.93 M0 84.93 C0.18 69.32, -0.09 50.99, 0 28.31 M0 84.93 C-0.87 68.18, 0.3 53.47, 0 28.31 M0 28.31 C1.78 11.07, 8.98 -1.79, 28.31 0 M0 28.31 C-1.04 9.6, 9.57 0.41, 28.31 0",
          ),
        ]),
      ],
    ),
    svg.g(
      [
        attribute(
          "transform",
          "translate(71.40218864488588 49.11928291049537) rotate(0 53.90618896484375 17.5)",
        ),
      ],
      [
        element(
          "text",
          [
            attribute("dominant-baseline", "alphabetic"),
            attribute("direction", "ltr"),
            attribute("style", "white-space: pre;"),
            attribute("text-anchor", "middle"),
            attribute("fill", "#1971c2"),
            attribute("font-size", "28px"),
            attribute("font-family", "Excalifont, Xiaolai, Segoe UI Emoji"),
            attribute("y", "24.668"),
            attribute("x", "53.90618896484375"),
          ],
          [html.text("Example")],
        ),
      ],
    ),
  ],
)

Notice in particular the definition for the text tag

        element(
          "text",
          [

When rendering this in a lustre app like so :

import lustre
import lustre/attribute.{attribute}
import lustre/element.{element}
import lustre/element/html.{div}
import lustre/element/svg

pub fn main() {
  let app = lustre.simple(init, update, view)
  let assert Ok(_) = lustre.start(app, "#app", Nil)

  Nil
}

fn init(_flags) {
  Nil
}

fn update(_model, _msg) {
  Nil
}

fn view(_model) {
  div([], [build_example_svg()])
}

fn build_example_svg() -> element.Element(_) {
// rendering svg
}

... the resulting web page using the lustre dev tools shows up like this in my browser (brave, up-to-date) : image

Then, replacing the offending text tag definition like so :

[
          svg.text(
            [
                // attributes remain the same
            ],
            "Example",  // replacing html.text("Example")
          ),

the page correctly displays the text image

Full lustre app code before fix ```gleam import lustre import lustre/attribute.{attribute} import lustre/element.{element} import lustre/element/html.{div} import lustre/element/svg pub fn main() { let app = lustre.simple(init, update, view) let assert Ok(_) = lustre.start(app, "#app", Nil) Nil } fn init(_flags) { Nil } fn update(_model, _msg) { Nil } fn view(_model) { div([], [build_example_svg()]) } fn build_example_svg() -> element.Element(_) { svg.svg( [ attribute("height", "133.23856582099086"), attribute("width", "250.61675521945938"), attribute("viewBox", "0 0 250.61675521945938 133.23856582099086"), attribute("xmlns", "http://www.w3.org/2000/svg"), attribute("version", "1.1"), ], [ svg.g( [ attribute( "transform", "translate(10 10) rotate(0 115.30837760972969 56.61928291049543)", ), attribute("stroke-linecap", "round"), ], [ svg.path([ attribute("fill", "none"), attribute("stroke-width", "4"), attribute("stroke", "#1971c2"), attribute( "d", "M28.31 0 C94.96 0.34, 163.03 1.53, 202.31 0 M28.31 0 C81.46 -0.32, 135.57 -1.03, 202.31 0 M202.31 0 C221.29 1.65, 228.68 9.01, 230.62 28.31 M202.31 0 C219.69 0.03, 228.55 8.12, 230.62 28.31 M230.62 28.31 C232.33 49.48, 232.53 70.53, 230.62 84.93 M230.62 28.31 C229.66 47.24, 229.52 65.01, 230.62 84.93 M230.62 84.93 C232.17 103.77, 220.17 114.73, 202.31 113.24 M230.62 84.93 C229.35 102.14, 220.61 114.96, 202.31 113.24 M202.31 113.24 C157.52 113.18, 111.5 116.09, 28.31 113.24 M202.31 113.24 C153.6 114.63, 106.88 113.53, 28.31 113.24 M28.31 113.24 C10.99 112.38, -1.57 105.09, 0 84.93 M28.31 113.24 C8.1 115.04, -1.36 101.51, 0 84.93 M0 84.93 C0.18 69.32, -0.09 50.99, 0 28.31 M0 84.93 C-0.87 68.18, 0.3 53.47, 0 28.31 M0 28.31 C1.78 11.07, 8.98 -1.79, 28.31 0 M0 28.31 C-1.04 9.6, 9.57 0.41, 28.31 0", ), ]), ], ), svg.g( [ attribute( "transform", "translate(71.40218864488588 49.11928291049537) rotate(0 53.90618896484375 17.5)", ), ], [ element( "text", [ attribute("dominant-baseline", "alphabetic"), attribute("direction", "ltr"), attribute("style", "white-space: pre;"), attribute("text-anchor", "middle"), attribute("fill", "#1971c2"), attribute("font-size", "28px"), attribute("font-family", "Excalifont, Xiaolai, Segoe UI Emoji"), attribute("y", "24.668"), attribute("x", "53.90618896484375"), ], [html.text("Example")], ), ], ), ], ) } ```
Full lustre app code after fix ```gleam import lustre import lustre/attribute.{attribute} import lustre/element.{element} import lustre/element/html.{div} import lustre/element/svg pub fn main() { let app = lustre.simple(init, update, view) let assert Ok(_) = lustre.start(app, "#app", Nil) Nil } fn init(_flags) { Nil } fn update(_model, _msg) { Nil } fn view(_model) { div([], [build_example_svg()]) } fn build_example_svg() -> element.Element(_) { svg.svg( [ attribute("height", "133.23856582099086"), attribute("width", "250.61675521945938"), attribute("viewBox", "0 0 250.61675521945938 133.23856582099086"), attribute("xmlns", "http://www.w3.org/2000/svg"), attribute("version", "1.1"), ], [ svg.g( [ attribute( "transform", "translate(10 10) rotate(0 115.30837760972969 56.61928291049543)", ), attribute("stroke-linecap", "round"), ], [ svg.path([ attribute("fill", "none"), attribute("stroke-width", "4"), attribute("stroke", "#1971c2"), attribute( "d", "M28.31 0 C94.96 0.34, 163.03 1.53, 202.31 0 M28.31 0 C81.46 -0.32, 135.57 -1.03, 202.31 0 M202.31 0 C221.29 1.65, 228.68 9.01, 230.62 28.31 M202.31 0 C219.69 0.03, 228.55 8.12, 230.62 28.31 M230.62 28.31 C232.33 49.48, 232.53 70.53, 230.62 84.93 M230.62 28.31 C229.66 47.24, 229.52 65.01, 230.62 84.93 M230.62 84.93 C232.17 103.77, 220.17 114.73, 202.31 113.24 M230.62 84.93 C229.35 102.14, 220.61 114.96, 202.31 113.24 M202.31 113.24 C157.52 113.18, 111.5 116.09, 28.31 113.24 M202.31 113.24 C153.6 114.63, 106.88 113.53, 28.31 113.24 M28.31 113.24 C10.99 112.38, -1.57 105.09, 0 84.93 M28.31 113.24 C8.1 115.04, -1.36 101.51, 0 84.93 M0 84.93 C0.18 69.32, -0.09 50.99, 0 28.31 M0 84.93 C-0.87 68.18, 0.3 53.47, 0 28.31 M0 28.31 C1.78 11.07, 8.98 -1.79, 28.31 0 M0 28.31 C-1.04 9.6, 9.57 0.41, 28.31 0", ), ]), ], ), svg.g( [ attribute( "transform", "translate(71.40218864488588 49.11928291049537) rotate(0 53.90618896484375 17.5)", ), ], [ svg.text( [ attribute("dominant-baseline", "alphabetic"), attribute("direction", "ltr"), attribute("style", "white-space: pre;"), attribute("text-anchor", "middle"), attribute("fill", "#1971c2"), attribute("font-size", "28px"), attribute("font-family", "Excalifont, Xiaolai, Segoe UI Emoji"), attribute("y", "24.668"), attribute("x", "53.90618896484375"), ], "Example", ), ], ), ], ) } ```
lpil commented 1 week ago

Thank you 💜