snabbdom / snabbdom

A virtual DOM library with focus on simplicity, modularity, powerful features and performance.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem with Tailwind style complex class names?

tslocke opened this issue · comments

I recently switched to using snabbdom to efficiently update the page preview in a web builder I'm working on.

The HTML contains Tailwind classes, e.g.class='block my-2 rounded bg-[#A31F24] text-white px-3 py-1'

I sometimes get an error from my call to patch(oldVnode, newVnode):

DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('a.block.my-2.rounded.bg-[') is not a valid name.

My patch function looks like this

import * as sd from "snabbdom"

const patch = sd.init([
  sd.classModule,
  sd.attributesModule,
  sd.datasetModule,
  sd.styleModule,
  sd.eventListenersModule,
])

Is this expected? Is there a workaround?

p.s. as a newbie, I'm not sure if I've got the right modules there -- all I want is "make this dom exactly like this other dom" (and the dom does include data attributes and style attributes, and does have event listeners on it)

Thanks!

Still facing this issue. Is there any way to configure things so that class is just treated like a regular string attribute?

Thanks

I've worked around this. The problem was partially related to my use of toVNode.

I've worked around this with a fork of toVNode that removes the hash from the vnode's sel and includes the class in data.attributes.

As far as I can tell the sel is only used as a kind of key to target updates correctly, so it should be fine to strip '#' chars from class names.

The fix would be in this code in createElm (init.ts)

      // Parse selector
      const hashIdx = sel.indexOf("#");
      const dotIdx = sel.indexOf(".", hashIdx);

In searches for '.' only later in the string than '#' (if present). I think it needs to be the other way around. It should only consider a '#' to be the hashIdx if it is before the first '.' But not tested

I guess this bug is very old, but no one has encountered it since using # in a class name is not very common (at least prior to this Tailwind feature). Thanks for reporting it!

The bug about the selector parsing definitely needs fixing. If you're interested in making a PR for that you're very welcome to do so.

Another question is whether it is appropriate for toVnode to put classes in the selector compared to setting them with the attributes module. It's not clear to me if one is strictly better than the other. So that issue probably needs some more contemplating.

#1116 should address the selector parsing issue. Would be useful if you can confirm that this solves your original problem 😊

fix parsing of selector with # in class names

Is . possible in ids? 🙂

Good point. According to MDN the id can in theory contain anything but whitespace. But they also note:

For example, . has a special meaning in CSS (it starts a class selector). While valid, unless you are careful to escape it when used as part of a CSS selector, it won't be recognized as part of the element's id.

So for a selector foo.bar#baz one could imagine parsing this as either an id foo.bar or class bar#baz and in a CSS selector string the latter will be the meaning.