Skip to content

Commit

Permalink
Support for upgraded UnoCSS impl
Browse files Browse the repository at this point in the history
  • Loading branch information
zaydek committed Jan 9, 2023
1 parent 842301c commit fc81755
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 119 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ attribution required.

## Technology Stack

[heroicons.dev](https://heroicons-viewer.netlify.app) has been around for a while (the first Heroicons website in existence 🤭) and has evolved. 🦕 The current technology stack is:
[heroicons.dev](https://heroicons-viewer.netlify.app) has been around for a while (the first Heroicons website in existence 🤭) and has evolved. The current technology stack is:

🥞 [Vite 🔗](https://vitejs.dev)<br>
🥞 [TypeScript 🔗](https://typescriptlang.org)<br>
Expand Down
53 changes: 53 additions & 0 deletions unitless.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Unitless CSS properties as described by Vanilla Extract
//
// https://github.com/vanilla-extract-css/vanilla-extract/blob/6068246343ceb58a04006f4ce9d9ff7ecc7a6c09/packages/css/src/transformCss.ts#L25
export const unitless: Record<string, boolean> = {
aspectRatio: true, // Added
animationIterationCount: true,
borderImage: true,
borderImageOutset: true,
borderImageSlice: true,
borderImageWidth: true,
boxFlex: true,
boxFlexGroup: true,
columnCount: true,
columns: true,
flex: true,
flexGrow: true,
flexShrink: true,
fontWeight: true,
gridArea: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnStart: true,
gridRow: true,
gridRowEnd: true,
gridRowStart: true,
initialLetter: true,
lineClamp: true,
lineHeight: true,
maxLines: true,
opacity: true,
order: true,
orphans: true,
scale: true, // Added
tabSize: true,
WebkitLineClamp: true,
widows: true,
zIndex: true,
zoom: true,

// SVG
fillOpacity: true,
floodOpacity: true,
maskBorder: true,
maskBorderOutset: true,
maskBorderSlice: true,
maskBorderWidth: true,
shapeImageThreshold: true,
stopOpacity: true,
strokeDashoffset: true,
strokeMiterlimit: true,
strokeOpacity: true,
strokeWidth: true,
}
188 changes: 70 additions & 118 deletions unocss.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { variantImportant, variantVariables } from "@unocss/preset-mini/variants
import transformerVariantGroup from "@unocss/transformer-variant-group"
import { Rule } from "unocss"
import { defineConfig } from "unocss/vite"
import { unitless } from "./unitless"

function convertSpaces(value: string) {
return value.replace(/_/g, " ")
Expand All @@ -11,17 +12,17 @@ function extractCSSVariables(value: string) {
return value.replace(/\$([a-zA-Z][a-zA-Z-0-9]*)/g, "var(--$1)")
}

function desugar(rawValue: undefined | string, { sign, px }: { sign?: string, px?: boolean } = {}): undefined | 0 | string {
sign ??= "" // TODO
px ??= true // TODO

if (rawValue === undefined) { return undefined }

function desugar(rawValue: string | undefined, { sign, px }: { sign?: string, px?: boolean } = {}) {
// No such value; eager return
if (rawValue === undefined) {
return undefined
}
sign ??= ""
px ??= true
// CSS variable; passthrough
const value = convertSpaces(extractCSSVariables(rawValue))
if (value.startsWith("$")) {
return value
} else if (value.startsWith("[") && value.endsWith("]")) { // TODO
return value.slice(1, -1)
} else {
if (px) {
return sign + value + (Number.isNaN(+value) ? "" : "px")
Expand All @@ -32,62 +33,36 @@ function desugar(rawValue: undefined | string, { sign, px }: { sign?: string, px
}

const rules: Rule[] = [
//// [/^((?:--|\$|-)?[a-z]+(?:-[a-z]+)*):(.+)$/, ([_, key, value]) => {
//// if (
//// key.startsWith("--") || // CSS variables
//// key.startsWith("$") || // CSS variables (syntax sugar)
//// key.startsWith("-webkit-") || // Safari and Chrome
//// key.startsWith("-moz-") || // Firefox
//// key.startsWith("-ms-") || // Microsoft Edge
//// key.startsWith("-o-") || // Opera
//// key in cssSpec
//// ) {
//// return { [key]: desugar(value) }
//// }
//// return {}
//// }],


[/^(-)?\[([^\\]+)\]-(.+)$/, ([_, sign, key, value]) => {
// Arbitrary key-value e.g. [property]-value
[/^(-)?\[([^\\]+)\]-(.+)$/, ([_, sign, property, value]) => {
const px = property in unitless
return {
[key]: desugar(value, { sign, px: false }),
[property]: desugar(value, { sign, px }),
}
}],

//// [/^\[(-)?((?:$)?[a-z]+(?:-[a-z]+)*):(.+)\]$/, ([_, sign, key, value]) => {
//// return {
//// [key]: desugar(value, { sign, px: false }),
//// }
//// }],

/*
* Positioning
*/
["absolute", { "position": "absolute" }],
["fixed", { "position": "fixed" }],
["relative", { "position": "relative" }],
["sticky", { "position": "sticky" }],

[/^(-?)inset-(.+)$/, ([_, sign, value]) => ({ "inset": desugar(value, { sign }) })],
[/^(-?)inset-x-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar(value, { sign }), "bottom": "auto", "left": desugar(value, { sign }) })],
[/^(-?)inset-y-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-t-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar(value, { sign }), "bottom": "auto", "left": desugar(value, { sign }) })],
[/^(-?)inset-r-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar(value, { sign }), "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-b-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar(value, { sign }), "bottom": desugar(value, { sign }), "left": desugar(value, { sign }) })],
[/^(-?)inset-l-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": desugar(value, { sign }), "left": desugar(value, { sign }) })],
[/^(-?)inset-tr-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar(value, { sign }), "bottom": "auto", "left": "auto" })],
[/^(-?)inset-br-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar(value, { sign }), "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-bl-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": "auto", "bottom": desugar(value, { sign }), "left": desugar(value, { sign }) })],
[/^(-?)inset-tl-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": "auto", "left": desugar(value, { sign }) })],
[/^(-?)t-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }) })],
[/^(-?)r-(.+)$/, ([_, sign, value]) => ({ "right": desugar(value, { sign }) })],
[/^(-?)b-(.+)$/, ([_, sign, value]) => ({ "bottom": desugar(value, { sign }) })],
[/^(-?)l-(.+)$/, ([_, sign, value]) => ({ "left": desugar(value, { sign }) })],
[/^z-(.+)$/, ([_, value]) => ({ "z-index": desugar(value, { px: false }) })],

/*
* Spacing
*/
["absolute", { "position": "absolute" }],
["fixed", { "position": "fixed" }],
["relative", { "position": "relative" }],
["sticky", { "position": "sticky" }],

[/^(-?)inset-(.+)$/, ([_, sign, value]) => ({ "inset": desugar(value, { sign }) })],
[/^(-?)inset-y-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-x-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar( value, { sign }), "bottom": "auto", "left": desugar( value, { sign }) })],
[/^(-?)inset-t-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar( value, { sign }), "bottom": "auto", "left": desugar( value, { sign }) })],
[/^(-?)inset-r-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar( value, { sign }), "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-b-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar( value, { sign }), "bottom": desugar(value, { sign }), "left": desugar( value, { sign }) })],
[/^(-?)inset-l-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": desugar(value, { sign }), "left": desugar( value, { sign }) })],
[/^(-?)inset-tr-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": desugar( value, { sign }), "bottom": "auto", "left": "auto" })],
[/^(-?)inset-br-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": desugar( value, { sign }), "bottom": desugar(value, { sign }), "left": "auto" })],
[/^(-?)inset-bl-(.+)$/, ([_, sign, value]) => ({ "top": "auto", "right": "auto", "bottom": desugar(value, { sign }), "left": desugar( value, { sign }) })],
[/^(-?)inset-tl-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }), "right": "auto", "bottom": "auto", "left": desugar( value, { sign }) })],
[/^(-?)t-(.+)$/, ([_, sign, value]) => ({ "top": desugar(value, { sign }) })],
[/^(-?)r-(.+)$/, ([_, sign, value]) => ({ "right": desugar(value, { sign }) })],
[/^(-?)b-(.+)$/, ([_, sign, value]) => ({ "bottom": desugar(value, { sign }) })],
[/^(-?)l-(.+)$/, ([_, sign, value]) => ({ "left": desugar(value, { sign }) })],
[/^z-(.+)$/, ([_, value]) => ({ "z-index": desugar(value, { px: false })})],

[/^(-?)m-(.+)$/, ([_, sign, value]) => ({ "margin": desugar(value, { sign }) })],
[/^(-?)my-(.+)$/, ([_, sign, value]) => ({ "margin-top": desugar(value, { sign }), "margin-bottom": desugar(value, { sign }) })],
[/^(-?)mx-(.+)$/, ([_, sign, value]) => ({ "margin-right": desugar(value, { sign }), "margin-left": desugar(value, { sign }) })],
Expand All @@ -103,54 +78,39 @@ const rules: Rule[] = [
[/^pb-(.+)$/, ([_, value]) => ({ "padding-bottom": desugar(value) })],
[/^pl-(.+)$/, ([_, value]) => ({ "padding-left": desugar(value) })],

/*
* Flexbox
*/
[/^justify-self-(.+)$/, ([_, value]) => ({ "justify-self": desugar(value, { px: false }) })],
[/^align-self-(.+)$/, ([_, value]) => ({ "align-self": desugar(value, { px: false }) })],
[/^flex-grow-(.+)$/, ([_, value]) => ({ "flex-grow": desugar(value, { px: false }) })],
[/^flex-shrink-(.+)$/, ([_, value]) => ({ "flex-shrink": desugar(value, { px: false }) })],
[/^flex-basis-(.+)$/, ([_, value]) => ({ "flex-basis": desugar(value) })],

["flex", { "display": "flex" }],
["inline-flex", { "display": "inline-flex" }],
["flex-row", { "flex-direction": "row" }],
["flex-col", { "flex-direction": "column" }],

[/^justify-(.+)$/, ([_, value]) => ({ "justify-content": desugar(value, { px: false }) })],
[/^align-(.+)$/, ([_, value]) => ({ "align-items": desugar(value, { px: false }) })],
[/^flex-wrap-(.+)$/, ([_, value]) => ({ "flex-wrap": desugar(value, { px: false }) })],

/*
* CSS Grid
*/
["grid", { "display": "grid" }],
[/^justify-self-(.+)$/, ([_, value]) => ({ "justify-self": desugar(value, { px: false }) })],
[/^align-self-(.+)$/, ([_, value]) => ({ "align-self": desugar(value, { px: false }) })],
[/^flex-grow-(.+)$/, ([_, value]) => ({ "flex-grow": desugar(value, { px: false }) })],
[/^flex-shrink-(.+)$/, ([_, value]) => ({ "flex-shrink": desugar(value, { px: false }) })],
[/^flex-basis-(.+)$/, ([_, value]) => ({ "flex-basis": desugar(value) })],

["flex", { "display": "flex" }],
["inline-flex", { "display": "inline-flex" }],
["flex-row", { "flex-direction": "row" }],
["flex-col", { "flex-direction": "column" }],

[/^justify-(.+)$/, ([_, value]) => ({ "justify-content": desugar(value, { px: false }) })],
[/^align-(.+)$/, ([_, value]) => ({ "align-items": desugar(value, { px: false }) })],
[/^flex-wrap-(.+)$/, ([_, value]) => ({ "flex-wrap": desugar(value, { px: false }) })],
[/^order-(.+)$/, ([_, value]) => ({ "order": desugar(value, { px: false }) })],

["grid", { "display": "grid" }],
[/^grid-(.+)$/, ([_, value]) => ({ "display": "grid", "grid-template": Number.isNaN(+value) ? desugar(value, { px: false }) : `repeat(${desugar(value, { px: false })}, 1fr)` })],
[/^grid-rows-(.+)$/, ([_, value]) => ({ "display": "grid", "grid-template-rows": Number.isNaN(+value) ? desugar(value, { px: false }) : `repeat(${desugar(value, { px: false })}, 1fr)` })],
[/^grid-cols-(.+)$/, ([_, value]) => ({ "display": "grid", "grid-template-columns": Number.isNaN(+value) ? desugar(value, { px: false }) : `repeat(${desugar(value, { px: false })}, 1fr)` })],

/*
* Gap
*/
[/^gap-(.+)$/, ([_, value]) => ({ "gap": desugar(value) })],
[/^gap-y-(.+)$/, ([_, value]) => ({ "row-gap": desugar(value) })],
[/^gap-x-(.+)$/, ([_, value]) => ({ "column-gap": desugar(value) })],

/*
* Sizing
*/
[/^h-(.+)$/, ([_, value]) => ({ "height": desugar(value) })],
[/^min-h-(.+)$/, ([_, value]) => ({ "min-height": desugar(value) })],
[/^max-h-(.+)$/, ([_, value]) => ({ "max-height": desugar(value) })],
[/^w-(.+)$/, ([_, value]) => ({ "width": desugar(value) })],
[/^min-w-(.+)$/, ([_, value]) => ({ "min-width": desugar(value) })],
[/^max-w-(.+)$/, ([_, value]) => ({ "max-width": desugar(value) })],
[/^aspect-(.+)$/, ([_, value]) => ({ "aspect-ratio": desugar(value, { px: false }) })],

/*
* Border-radius
*/
[/^gap-(.+)$/, ([_, value]) => ({ "gap": desugar(value) })],
[/^gap-y-(.+)$/, ([_, value]) => ({ "row-gap": desugar(value) })],
[/^gap-x-(.+)$/, ([_, value]) => ({ "column-gap": desugar(value) })],

[/^h-(.+)$/, ([_, value]) => ({ "height": desugar(value) })],
[/^min-h-(.+)$/, ([_, value]) => ({ "min-height": desugar(value) })],
[/^max-h-(.+)$/, ([_, value]) => ({ "max-height": desugar(value) })],
[/^w-(.+)$/, ([_, value]) => ({ "width": desugar(value) })],
[/^min-w-(.+)$/, ([_, value]) => ({ "min-width": desugar(value) })],
[/^max-w-(.+)$/, ([_, value]) => ({ "max-width": desugar(value) })],
[/^aspect-(.+)$/, ([_, value]) => ({ "aspect-ratio": desugar(value, { px: false }) })],

[/^rounded-(.+)$/, ([_, value]) => ({ "border-radius": desugar(value) })],
[/^rounded-t-(.+)$/, ([_, value]) => ({ "border-top-left-radius": desugar(value), "border-top-right-radius": desugar(value) })],
[/^rounded-r-(.+)$/, ([_, value]) => ({ "border-top-right-radius": desugar(value), "border-bottom-right-radius": desugar(value) })],
Expand All @@ -161,25 +121,17 @@ const rules: Rule[] = [
[/^rounded-bl-(.+)$/, ([_, value]) => ({ "border-bottom-left-radius": desugar(value) })],
[/^rounded-tl-(.+)$/, ([_, value]) => ({ "border-top-left-radius": desugar(value) })],

/*
* Decoration (shorthands)
*/
[/^color-(.+)$/, ([_, value]) => ({ "color": desugar(value, { px: false }) })],
[/^bg-color-(.+)$/, ([_, value]) => ({ "background-color": desugar(value, { px: false }) })],
[/^bg-image-(.+)$/, ([_, value]) => ({ "background-image": desugar(value, { px: false }) })],
[/^shadow-(.+)$/, ([_, value]) => ({ "box-shadow": desugar(value, { px: false }) })],
[/^color-(.+)$/, ([_, value]) => ({ "color": desugar(value, { px: false }) })],
[/^bg-color-(.+)$/, ([_, value]) => ({ "background-color": desugar(value, { px: false }) })],
[/^shadow-(.+)$/, ([_, value]) => ({ "box-shadow": desugar(value, { px: false }) })],
]

////////////////////////////////////////////////////////////////////////////////

export default defineConfig({
presets: [], // No-op UnoCSS
presets: [],
rules,
transformers: [
transformerVariantGroup(),
],
transformers: [transformerVariantGroup()],
variants: [
variantImportant, // !key=typed(value) syntax
variantVariables, // [selector]:key=typed(value) syntax
variantImportant, // E.g. !property-value
variantVariables, // E.g. [variable]:property-value
],
})

0 comments on commit fc81755

Please sign in to comment.