Skip to content

Conversation

@binhtddev
Copy link
Contributor

Reason:

  • JSX cannot use NS for svg, math, etc.
  • Increase portablility of Van Components by inheriting curNS of their parents
  • Simplify tags function

Reason:
- JSX cannot use NS for svg, math, etc.
- Increase portablility of Van Components by inheriting `curNS` of their
parents
- Simplify `tags` function
@thednp
Copy link
Contributor

thednp commented Jun 6, 2025

Interesting find, are you using van-jsx?

@binhtddev
Copy link
Contributor Author

@thednp, No, I'm not actually using van-jsx. I built zdom, which is based on Van but specifically designed to work with JSX.

While developing zdom, I ran into an issue where Van struggled to create elements like svg and math.
My solution in zdom involves creating lazy DOM objects. This allows me to check the xmlns from the parent element and then correctly apply it to its children.

Plus, I noticed that the van-jsx type definitions are quite large. My method is much simpler and doesn't require translating CSS objects. I'd be happy to contribute another PR to add official Van JSX support if this idea gets some traction.

@thednp
Copy link
Contributor

thednp commented Jun 7, 2025

Please post some test JSX I can have a look. You can also test it right now here.

UPDATE: I tested a sample SVG markup as JSX and didn't work. It might have to do with the createElement we use, will check that later today.

@thednp
Copy link
Contributor

thednp commented Jun 7, 2025

I can confirm that's exactly the problem, I already have a working fix, mode details soon.

@thednp
Copy link
Contributor

thednp commented Jun 7, 2025

In short this is the fix:

    const nameSpace = props["xmlns"];
    const newElement = nameSpace ? van.tags(nameSpace)[jsxTag](props, children) : van.tags[jsxTag](props, children);

In long: we also need to update the handling of the attributes as well.

@binhtddev
Copy link
Contributor Author

In short this is the fix:

    const nameSpace = props["xmlns"];
    const newElement = nameSpace ? van.tags(nameSpace)[jsxTag](props, children) : van.tags[jsxTag](props, children);

In long: we also need to update the handling of the attributes as well.

The problem is that children cannot inherit the xmlns of the parent. Furthermore, children elements are evaluated before their parent. I think the proper workaround is use my high order function withNS which will be evaluated before the passed function.

@thednp
Copy link
Contributor

thednp commented Jun 7, 2025

I don't think @Tao-VanJS is going to approve this PR since we can have workarounds, but I might be wrong about that. Will investigate further layer today.

@Tao-VanJS
Copy link
Member

Tao-VanJS commented Jun 8, 2025

I don't think you need to change VanJS to achieve what you want. Here is the sample code based on your idea:

let curNs

const superTag = (name, ...args) => (curNs ? van.tags(curNs) : van.tags)[name](...args)

const superTags = new Proxy(superTag, {get: (target, name) => target.bind(null, name)})

const withNs = (ns, fn) => {
  const oldNs = curNs
  curNs = ns
  try {
    return fn()
  } finally {
    curNs = oldNs
  }
}

const {div, circle, path, svg, math, mi, mn, mo, mrow, msup} = superTags

const Smiley = () => svg({width: "16px", viewBox: "0 0 50 50"},
  circle({cx: "25", cy: "25", "r": "20", stroke: "black", "stroke-width": "2", fill: "yellow"}),
  circle({cx: "16", cy: "20", "r": "2", stroke: "black", "stroke-width": "2", fill: "black"}),
  circle({cx: "34", cy: "20", "r": "2", stroke: "black", "stroke-width": "2", fill: "black"}),
  path({"d": "M 15 30 Q 25 40, 35 30", stroke: "black", "stroke-width": "2", fill: "transparent"}),
)

const Euler = () => math(
  msup(mi("e"), mrow(mi("i"), mi("π"))), mo("+"), mn("1"), mo("="), mn("0"),
)

van.add(document.body,
  div(withNs("http://www.w3.org/2000/svg", Smiley)),
  div(withNs("http://www.w3.org/1998/Math/MathML", Euler)),
)

Preview via: https://jsfiddle.net/tjz45e1n/1/

@binhtddev binhtddev closed this Jun 8, 2025
@thednp
Copy link
Contributor

thednp commented Jun 8, 2025

@Tao-VanJS thanks for dropping by! Based on your suggestion I've fixed the vite-plugin-vanjs (JSX) to work automatically with namespace elements. Will update it soon.

@binhtddev
Copy link
Contributor Author

Thank @Tao-VanJS , I just wanted to have an official workaround. Maybe @thednp will have good way to fix van-jsx based on your elegant example.

@thednp
Copy link
Contributor

thednp commented Jun 8, 2025

@binhtran432k in fact VanJS with our vite-plugin-vanjs is (possibly) the only framework to officially support MathML, in a couple of hours that is :)

@thednp
Copy link
Contributor

thednp commented Jun 8, 2025

@binhtran432k you can now test vite-plugin-vanjs@0.1.10 with fixes for namespace elements, you can even not specify a namespace at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants