Skip to main content

mapcss

Tiny, composable Atomic CSS engine

deno land nest.land

release deno version deno doc

test codecov DeepSource DeepScan grade

Semver Conventional Commits semantic-release: angular license


:construction: This project is currently in beta release. All interfaces are subject to change.

Usage

mapcss provides several preset.

For example, using presetTw, you can use the utility class of TailwindCSS.

import { generate, presetTw } from "https://deno.land/x/mapcss@$VERSION/mod.ts";

const code = `<div className="relative flex">
  <p className="text-red-500/20"></p>  
</div>
`;
const result = generate({ preset: [presetTw()] }, code);
console.log(result.css);
/*
  .relative{position:relative;}
  .flex{display:flex;}
  .text-red-500\/20{color:rgb(239 68 68/.2);}
*/

You may need --unstable and --allow-read flag to Deno.

What

mapcss is an Atomic-oriented CSS generator.

It is strongly influenced by TailwindCSS and UnocCSS, but with the following differences.

  • Mapping is free. And you can define a very flexible mapping syntax.
  • Deno is fully supported.

identifier to CSS-in-JS

The essence of mapcss is to map an identifier to a CSS Statement with JavaScript Object notation (CSS-in-JS).

A Map is a Plain Object with a hierarchical structure, which can be expressed concisely with Object literals.

For example, the following CSS Statement can be mapped as follows:

.inline-block{display: inline;}
import type { CSSMap } from "https://deno.land/x/mapcss@$VERSION/mod.ts";
const cssMap: CSSMap = {
  inline: {
    block: { display: "inline" },
  },
};

It is also possible to express dynamic identifiers using regular expressions.

.z-123{z-index: 123;}
import type { CSSMap } from "https://deno.land/x/mapcss@$VERSION/mod.ts";
const rePositiveNumber = /^(\d+)$/;
const cssMap: CSSMap = {
  z: [
    // It actually checks the validity of the numbers
    [rePositiveNumber, ([, number]) => ({ zIndex: Number(number) })],
  ],
};

We support the first class because it is the most frequent mapping to CSS declaration block.

For the definition of any CSS Statement, CSS-in-JS representation is also supported.

@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}
.container{width: 100%;}
import type { CSSMap } from "https://deno.land/x/mapcss@$VERSION/mod.ts";
const cssMap: CSSMap = {
  // className: .container
  container: (_, { className }) => ({
    type: "css",
    value: {
      "@media (min-width: 640px)": {
        [className]: {
          maxWidth: "640px",
        },
      },
      [className]: {
        width: "100%",
      },
    },
  }),
};

The Object search model

Explore the object hierarchy based on identifier. Hierarchy traversal is much more performant than flat traversal.

For example, the computational complexity of regular expression matching from a flat structure is O(N).

If the search finds CSS-in-JS, it will be converted to AST. The AST currently uses the postcss AST.

This will benefit from the postcss ecosystem.

Finally, we show the conversion transition.

token -> DeepMap { identifier -> CSS-in-JS } -> AST -> Style Sheet

License

Copyright © 2021-present TomokiMiyauci.

Released under the MIT license