postcss-windicss icon indicating copy to clipboard operation
postcss-windicss copied to clipboard

Utility Groups (Why not?!)

Open deleonio opened this issue 5 years ago • 11 comments

That is currently not possible?!

  • https://windicss.org/guide/features.html#%F0%9F%8E%B3-utility-groups
class="hover:(border-green-600 shadow-lg)"

We give the parser the files and he extract the css classes. Why he did not detect the utility groups?

deleonio avatar Apr 10 '21 01:04 deleonio

It requires transformations to the source file, not just serving the css. Which I don't think it's capable for postcss's plugin interface.

antfu avatar Apr 10 '21 01:04 antfu

Is it possible to push the css as string instead of a file path?

deleonio avatar Apr 10 '21 07:04 deleonio

Sorry what do you mean?

antfu avatar Apr 10 '21 09:04 antfu

Sorry, the extractFile function receive the css as string and should make the group handling too.

https://github.com/windicss/vite-plugin-windicss/blob/ce166a0334f1a36e9d24513caf391a53585ac249/packages/plugin-utils/src/createUtils.ts#L161

But it does not work in my case.

deleonio avatar Apr 10 '21 11:04 deleonio

🤦 Embarrassing, now I understand it too. The detection works.

image

🤔 ... I will think about it.

deleonio avatar Apr 10 '21 14:04 deleonio

Hello @antfu,

I implemented a tiny devtool script that transforms the class declaration like Windi under the hood.

But today I have no idea how to dynamically insert it into the development code.

// windi stuff
const regexClassGroup = /([!\w+-][\w+:_/-]*?\w):\(([\w\s/-]*?)\)/gm;
function transformGroups(str: string) {
  return str.replace(regexClassGroup, (_, a: string, b: string) =>
    b
      .split(/\s/g)
      .map((i) => `${a}:${i}`)
      .join(' ')
  );
}

// devtool
document.addEventListener('DOMNodeInserted', (event: MutationEvent) => {
  const nodes: NodeListOf<HTMLElement> = event.relatedNode.querySelectorAll('[class]');
  nodes.forEach((node: HTMLElement) => {
    const transformed = transformGroups(node.getAttribute('class') || '');
    if (node.getAttribute('class') != transformed) {
      node.setAttribute('class', transformed);
    }
  });
});

image

deleonio avatar Apr 11 '21 22:04 deleonio

Oh, like a runtime?

antfu avatar Apr 12 '21 02:04 antfu

I could try to inject the devtool snippet only in development mode.

deleonio avatar Apr 12 '21 05:04 deleonio

Update prototype - valid W3C - https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

const regexClassGroup = /([!\w+-][\w+:_/-]*?\w):\(([\w\s/-]*?)\)/gm;
function transformGroups(str: string) {
  return str.replace(regexClassGroup, (_, a: string, b: string) =>
    b
      .split(/\s/g)
      .map((i) => `${a}:${i}`)
      .join(' ')
  );
}

new MutationObserver((records: MutationRecord[]) => {
  records.forEach((record: MutationRecord) => {
    record.addedNodes.forEach((node: Node) => {
      const nodes: NodeListOf<HTMLElement> | undefined = node.parentElement?.querySelectorAll('[class]');
      if (nodes) {
        nodes.forEach((node: HTMLElement) => {
          const transformed = transformGroups(node.getAttribute('class') || '');
          if (node.getAttribute('class') != transformed) {
            node.setAttribute('class', transformed);
          }
        });
      }
    });
  });
}).observe(document.body, {
  attributes: true,
  childList: true,
  subtree: true,
});

deleonio avatar Apr 19 '21 21:04 deleonio

Interesting, do you think we can make a package called windicss-groups-runtime-polyfill or something so people can opt-in by simply importing it via npm or CDN.

/cc @voorjaar do you feel we can make this one official?

antfu avatar Apr 19 '21 21:04 antfu

Hi! Is this usable now? Really wanted to have variant grouping.

George-Miao avatar Jan 20 '22 14:01 George-Miao