npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@pastweb/vite-plugin-css-tools

v1.0.9

Published

plugin for Css Utility Modules

Downloads

70

Readme

Vite plugin for CSS Tools

A Vite plugin inspired to CSS Modules and Tailwind CSS framework.

  • Reduce the css size nesting the selectors where convenient.
  • Handle CSS modules.
  • Scopes CSS variables.
  • Calculate utilities on the fly and assign them in the CSS module object.
  • Remove the unused classes.

For more info about tools and the options check the CSS Tools page.

install

npm i -D @pastweb/vite-plugin-css-tools

Usage

import { defineConfig } from 'vite'
import preact from '@preact/preset-vite'
import { cssTools } from '@pastweb/vite-plugin-css-tools';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    preact(), // or any other framework plugin
    cssTools({ ...options }),
  ],
})

Summary

Options

All options are available as described in the documentation, with the exception for the following: getModules, getUtilityModules and test which are used internally in the vite plugin. usedClasses is a boolean (true by default) in case you don't want to use the astPlugins in order to remove the unused classes from the css. The mode functionality in the utility option is set to readable for development and encoded for production by default, and the output functionality is not available as it is used internally in order to collect all the utilities which will be rendered in the main css output file in oder to be available as soon as possible.

AstPlugins

The AstPlugin is a plugin which read the javascript source file in order to exctract the classNames used in your source code. This list o classes are later passes to css-tools in order to remove the unused classes from the resultant css code. There are already internal plugins in order to provide this functionality for the most used Front End frameworks such as react, preact, vue and svelte.

You can check the example for rimmel.

astPlugin example:

export default defineConfig({
  plugins: [
    cssTools({
      astPlugins: [
        {
          name: 'react',
          import: {
            source: /^react\/?(jsx-runtime|jsx-dev-runtime)?/,
            specifier: /^createElement$|^jsx(s|DEV)?$/,
            defaultSpecifier: 'createElement',
          },
          ast: {
            ['CallExpression'](node, specifiers) {
              if (!specifiers.has(node.callee.name)) return;
              if (node.arguments[1].type !== 'ObjectExpression') return;
              
              const [ properties ] = node.arguments[1]; // the ast node representing the props object
              
              if (!properties) return;
              
              for (const { type, name, value } of properties) {
                if (type === 'Property' && name === 'className') return value;
              }
            }
          },
        },
      ],
    }),
  ],
});

In the example above is described an astPlugin for react.

  • name: the plugin name (it gets the framework name by convention);
  • import: the import information needed to identify the the ast node (in the above example the react jsx or createEleemnt function) which will be passed the the ast function later.
    • source: is a regular expression for detect the framework import line.
    • specifier: is a regular expression for detect the function specifier/s which will be passed as second parameterr Set<string> to the ast function.
    • defaultSpecifier: is optional and is the default value to be used.
  • ast: is an Object Record<string, (node: Node, specifiers: Set<string>) => void | Node | [ string, string ] | Promise<void | Node | [ string, string ]>. How you can see the ast function can be an async function and it can returns void for no operation, an array [ filePath, classNames ] or the ast Node which represent the classes string. Even the string composition are supported as like any class composition function like clsx for react which follows this parameters syntax. To analyze your code you can use astexplorer selecting acorn as ast standard;

example:

<script>
  import clsx from 'clsx';
  import classes from './Panel.module.css';

  const isOpen = false;
  const fullWidth = true;
</script>


<div class={classes.Panel}>
  <div class={clsx([classes['panel' + '-' + 'header'], { isOpen }])} fullWidth:fullWidth>
    <div class={classes['panel-box']}>
      this is the Panel Header
    </div>
  </div>
  this is the content
  <div class={clsx([classes['panel-footer'], { isOpen }])}>
    <div class={classes['panel-box']}>
      this is the panel footer
    </div>
  </div>
</div>

How you can see in the example above the clsx function conditional assignment as the svelte native conditional assignment are supported. This is valid even for vue, which use an internal function for the conditional assignment.

example:

<script setup>
  import { shallowReactive } from 'vue';
  import classes from './Panel.module.css';

  const state = shallowReactive({ isOpen: false });
</script>

<template>
  <div :class="classes.Panel">
    <div :class="[classes['panel' + '-' + 'header'], { isOpen: state.isOpen }]">
      <div :class="classes['panel-box']">
        this is the Panel Header
      </div>
    </div>
    this is the content
    <div :class="[classes['panel-footer'], { isOpen: state.isOpen }]">
      <div :class="classes['panel-box']">
        this is the panel footer
      </div>
    </div>
  </div>
</template>

Limitations

How you can see in the examples above, to be able to process the css you need to import the css file in the js file even if you are using a SFC framework. The css declared inside the tag <style> of a single file component will be not processed. If lightningcss is used in the vite configuration, the plugin will not process the css.