(defsuite "tw-bg-colour" (deftest "bg-sky-500 → hsl" (assert= (tw-resolve-style "bg-sky-500") "background-color:hsl(199,89%,53%)")) (deftest "bg-emerald-100" (assert= (tw-resolve-style "bg-emerald-100") "background-color:hsl(160,84%,93%)")) (deftest "bg-amber-300" (assert= (tw-resolve-style "bg-amber-300") "background-color:hsl(38,92%,77%)")) (deftest "bg-stone-200" (assert= (tw-resolve-style "bg-stone-200") "background-color:hsl(25,6%,87%)")) (deftest "bg-slate-700" (assert= (tw-resolve-style "bg-slate-700") "background-color:hsl(215,16%,38%)")) (deftest "bg-red-600" (assert= (tw-resolve-style "bg-red-600") "background-color:hsl(0,72%,45%)")) (deftest "bg-blue-500" (assert= (tw-resolve-style "bg-blue-500") "background-color:hsl(217,91%,53%)")) (deftest "bg-violet-500" (assert= (tw-resolve-style "bg-violet-500") "background-color:hsl(263,70%,53%)")) (deftest "bg-pink-400" (assert= (tw-resolve-style "bg-pink-400") "background-color:hsl(330,81%,64%)")) (deftest "bg-white → #ffffff" (assert= (tw-resolve-style "bg-white") "background-color:#ffffff")) (deftest "bg-black → #000000" (assert= (tw-resolve-style "bg-black") "background-color:#000000")) (deftest "bg-transparent" (assert= (tw-resolve-style "bg-transparent") "background-color:transparent")) (deftest "bg-current → currentColor" (assert= (tw-resolve-style "bg-current") "background-color:currentColor")) (deftest "bg-inherit" (assert= (tw-resolve-style "bg-inherit") "background-color:inherit"))) (defsuite "tw-text-colour" (deftest "text-sky-700" (assert= (tw-resolve-style "text-sky-700") "color:hsl(199,89%,38%)")) (deftest "text-stone-600" (assert= (tw-resolve-style "text-stone-600") "color:hsl(25,6%,45%)")) (deftest "text-emerald-500" (assert= (tw-resolve-style "text-emerald-500") "color:hsl(160,84%,53%)")) (deftest "text-white" (assert= (tw-resolve-style "text-white") "color:#ffffff")) (deftest "text-black" (assert= (tw-resolve-style "text-black") "color:#000000")) (deftest "text-current" (assert= (tw-resolve-style "text-current") "color:currentColor"))) (defsuite "tw-border-colour" (deftest "border-sky-200" (assert= (tw-resolve-style "border-sky-200") "border-color:hsl(199,89%,87%)")) (deftest "border-emerald-300" (assert= (tw-resolve-style "border-emerald-300") "border-color:hsl(160,84%,77%)")) (deftest "border-stone-400" (assert= (tw-resolve-style "border-stone-400") "border-color:hsl(25,6%,64%)")) (deftest "border-transparent" (assert= (tw-resolve-style "border-transparent") "border-color:transparent"))) (defsuite "tw-shade-to-lightness" (deftest "shade 0 → 100" (assert= (shade-to-lightness 0) 100)) (deftest "shade 50 → 97" (assert= (shade-to-lightness 50) 97)) (deftest "shade 100 → 93" (assert= (shade-to-lightness 100) 93)) (deftest "shade 200 → 87" (assert= (shade-to-lightness 200) 87)) (deftest "shade 300 → 77" (assert= (shade-to-lightness 300) 77)) (deftest "shade 400 → 64" (assert= (shade-to-lightness 400) 64)) (deftest "shade 500 → 53" (assert= (shade-to-lightness 500) 53)) (deftest "shade 600 → 45" (assert= (shade-to-lightness 600) 45)) (deftest "shade 700 → 38" (assert= (shade-to-lightness 700) 38)) (deftest "shade 800 → 30" (assert= (shade-to-lightness 800) 30)) (deftest "shade 900 → 21" (assert= (shade-to-lightness 900) 21)) (deftest "shade 950 → 13" (assert= (shade-to-lightness 950) 13))) (defsuite "tw-colour-bases" (deftest "sky" (assert= (colour "sky" 500) "hsl(199,89%,53%)")) (deftest "emerald" (assert= (colour "emerald" 500) "hsl(160,84%,53%)")) (deftest "red" (assert= (colour "red" 500) "hsl(0,72%,53%)")) (deftest "amber" (assert= (colour "amber" 500) "hsl(38,92%,53%)")) (deftest "slate" (assert= (colour "slate" 500) "hsl(215,16%,53%)")) (deftest "stone" (assert= (colour "stone" 500) "hsl(25,6%,53%)")) (deftest "blue" (assert= (colour "blue" 500) "hsl(217,91%,53%)")) (deftest "violet" (assert= (colour "violet" 500) "hsl(263,70%,53%)")) (deftest "pink" (assert= (colour "pink" 500) "hsl(330,81%,53%)")) (deftest "cyan" (assert= (colour "cyan" 500) "hsl(188,94%,53%)")) (deftest "teal" (assert= (colour "teal" 500) "hsl(173,80%,53%)")) (deftest "indigo" (assert= (colour "indigo" 500) "hsl(239,84%,53%)")) (deftest "purple" (assert= (colour "purple" 500) "hsl(271,81%,53%)")) (deftest "rose" (assert= (colour "rose" 500) "hsl(350,89%,53%)")) (deftest "lime" (assert= (colour "lime" 500) "hsl(84,78%,53%)")) (deftest "yellow" (assert= (colour "yellow" 500) "hsl(48,96%,53%)")) (deftest "orange" (assert= (colour "orange" 500) "hsl(25,95%,53%)")) (deftest "green" (assert= (colour "green" 500) "hsl(142,71%,53%)")) (deftest "gray" (assert= (colour "gray" 500) "hsl(220,9%,53%)")) (deftest "zinc" (assert= (colour "zinc" 500) "hsl(240,5%,53%)")) (deftest "neutral" (assert= (colour "neutral" 500) "hsl(0,0%,53%)")) (deftest "fuchsia is a known base" (assert= (colour "fuchsia" 500) "hsl(292,84%,53%)")) (deftest "shade variation: sky-100" (assert= (colour "sky" 100) "hsl(199,89%,93%)")) (deftest "shade variation: sky-900" (assert= (colour "sky" 900) "hsl(199,89%,21%)"))) (defsuite "tw-border-radius" (deftest "rounded → 0.25rem" (assert= (tw-resolve-style "rounded") "border-radius:0.25rem")) (deftest "rounded-none → 0" (assert= (tw-resolve-style "rounded-none") "border-radius:0")) (deftest "rounded-sm → 0.125rem" (assert= (tw-resolve-style "rounded-sm") "border-radius:0.125rem")) (deftest "rounded-md → 0.375rem" (assert= (tw-resolve-style "rounded-md") "border-radius:0.375rem")) (deftest "rounded-lg → 0.5rem" (assert= (tw-resolve-style "rounded-lg") "border-radius:0.5rem")) (deftest "rounded-xl → 0.75rem" (assert= (tw-resolve-style "rounded-xl") "border-radius:0.75rem")) (deftest "rounded-2xl → 1rem" (assert= (tw-resolve-style "rounded-2xl") "border-radius:1rem")) (deftest "rounded-3xl → 1.5rem" (assert= (tw-resolve-style "rounded-3xl") "border-radius:1.5rem")) (deftest "rounded-full → 9999px" (assert= (tw-resolve-style "rounded-full") "border-radius:9999px")) (deftest "rounded-t-lg — directional top" (assert= (tw-resolve-style "rounded-t-lg") "border-top-left-radius:0.5rem;border-top-right-radius:0.5rem")) (deftest "rounded-b-md — directional bottom" (assert= (tw-resolve-style "rounded-b-md") "border-bottom-left-radius:0.375rem;border-bottom-right-radius:0.375rem")) (deftest "rounded-l-xl — directional left" (assert= (tw-resolve-style "rounded-l-xl") "border-top-left-radius:0.75rem;border-bottom-left-radius:0.75rem")) (deftest "rounded-r — directional right default" (assert= (tw-resolve-style "rounded-r") "border-top-right-radius:0.25rem;border-bottom-right-radius:0.25rem"))) (defsuite "tw-border-width" (deftest "border → 1px" (assert= (tw-resolve-style "border") "border-width:1px")) (deftest "border-0" (assert= (tw-resolve-style "border-0") "border-width:0px")) (deftest "border-2" (assert= (tw-resolve-style "border-2") "border-width:2px")) (deftest "border-4" (assert= (tw-resolve-style "border-4") "border-width:4px")) (deftest "border-8" (assert= (tw-resolve-style "border-8") "border-width:8px")) (deftest "border-t → top 1px" (assert= (tw-resolve-style "border-t") "border-top-width:1px")) (deftest "border-b → bottom 1px" (assert= (tw-resolve-style "border-b") "border-bottom-width:1px")) (deftest "border-l → left 1px" (assert= (tw-resolve-style "border-l") "border-left-width:1px")) (deftest "border-r → right 1px" (assert= (tw-resolve-style "border-r") "border-right-width:1px")) (deftest "border-t-2 → top 2px" (assert= (tw-resolve-style "border-t-2") "border-top-width:2px"))) (defsuite "tw-shadow" (deftest "shadow — default" (assert= (tw-resolve-style "shadow") "box-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)")) (deftest "shadow-sm" (assert= (tw-resolve-style "shadow-sm") "box-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05)")) (deftest "shadow-md" (assert= (tw-resolve-style "shadow-md") "box-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)")) (deftest "shadow-lg" (assert= (tw-resolve-style "shadow-lg") "box-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)")) (deftest "shadow-xl" (assert= (tw-resolve-style "shadow-xl") "box-shadow:0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)")) (deftest "shadow-2xl" (assert= (tw-resolve-style "shadow-2xl") "box-shadow:0 25px 50px -12px rgb(0 0 0 / 0.25)")) (deftest "shadow-inner" (assert= (tw-resolve-style "shadow-inner") "box-shadow:inset 0 2px 4px 0 rgb(0 0 0 / 0.05)")) (deftest "shadow-none" (assert= (tw-resolve-style "shadow-none") "box-shadow:0 0 #0000"))) (defsuite "tw-opacity" (deftest "opacity-0" (assert= (tw-resolve-style "opacity-0") "opacity:0")) (deftest "opacity-5" (assert= (tw-resolve-style "opacity-5") "opacity:0.05")) (deftest "opacity-10" (assert= (tw-resolve-style "opacity-10") "opacity:0.1")) (deftest "opacity-25" (assert= (tw-resolve-style "opacity-25") "opacity:0.25")) (deftest "opacity-50" (assert= (tw-resolve-style "opacity-50") "opacity:0.5")) (deftest "opacity-75" (assert= (tw-resolve-style "opacity-75") "opacity:0.75")) (deftest "opacity-100" (assert= (tw-resolve-style "opacity-100") "opacity:1"))) (defsuite "tw-transition" (deftest "transition" (assert= (tw-resolve-style "transition") "transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms")) (deftest "transition-colors" (assert= (tw-resolve-style "transition-colors") "transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms")) (deftest "transition-none" (assert= (tw-resolve-style "transition-none") "transition-property:none")) (deftest "duration-150" (assert= (tw-resolve-style "duration-150") "transition-duration:150ms")) (deftest "duration-300" (assert= (tw-resolve-style "duration-300") "transition-duration:300ms")) (deftest "ease-linear" (assert= (tw-resolve-style "ease-linear") "transition-timing-function:linear")) (deftest "ease-in-out" (assert= (tw-resolve-style "ease-in-out") "transition-timing-function:cubic-bezier(0.4,0,0.2,1)")) (deftest "animate-spin" (assert= (tw-resolve-style "animate-spin") "animation:spin 1s linear infinite")) (deftest "animate-none" (assert= (tw-resolve-style "animate-none") "animation:none"))) (defsuite "tw-cursor" (deftest "cursor-pointer" (assert= (tw-resolve-style "cursor-pointer") "cursor:pointer")) (deftest "cursor-default" (assert= (tw-resolve-style "cursor-default") "cursor:default")) (deftest "cursor-not-allowed" (assert= (tw-resolve-style "cursor-not-allowed") "cursor:not-allowed")) (deftest "cursor-wait" (assert= (tw-resolve-style "cursor-wait") "cursor:wait")) (deftest "cursor-text" (assert= (tw-resolve-style "cursor-text") "cursor:text")) (deftest "cursor-move" (assert= (tw-resolve-style "cursor-move") "cursor:move")) (deftest "cursor-grab" (assert= (tw-resolve-style "cursor-grab") "cursor:grab"))) (defsuite "tw-style-misc" (deftest "underline" (assert= (tw-resolve-style "underline") "text-decoration-line:underline")) (deftest "overline" (assert= (tw-resolve-style "overline") "text-decoration-line:overline")) (deftest "no-underline" (assert= (tw-resolve-style "no-underline") "text-decoration-line:none")) (deftest "line-through" (assert= (tw-resolve-style "line-through") "text-decoration-line:line-through")) (deftest "select-none" (assert= (tw-resolve-style "select-none") "user-select:none")) (deftest "select-text" (assert= (tw-resolve-style "select-text") "user-select:text")) (deftest "appearance-none" (assert= (tw-resolve-style "appearance-none") "appearance:none")) (deftest "pointer-events-none" (assert= (tw-resolve-style "pointer-events-none") "pointer-events:none")) (deftest "pointer-events-auto" (assert= (tw-resolve-style "pointer-events-auto") "pointer-events:auto")) (deftest "outline-none" (assert= (tw-resolve-style "outline-none") "outline:2px solid transparent;outline-offset:2px")) (deftest "outline — solid" (assert= (tw-resolve-style "outline") "outline-style:solid")) (deftest "scale-95" (assert= (tw-resolve-style "scale-95") "transform:scale(0.95)")) (deftest "scale-105" (assert= (tw-resolve-style "scale-105") "transform:scale(1.05)")) (deftest "scale-150" (assert= (tw-resolve-style "scale-150") "transform:scale(1.5)")) (deftest "rotate-45" (assert= (tw-resolve-style "rotate-45") "transform:rotate(45deg)")) (deftest "rotate-90" (assert= (tw-resolve-style "rotate-90") "transform:rotate(90deg)")) (deftest "rotate-180" (assert= (tw-resolve-style "rotate-180") "transform:rotate(180deg)"))) (defsuite "tw-display" (deftest "flex" (assert= (tw-resolve-layout "flex") "display:flex")) (deftest "block" (assert= (tw-resolve-layout "block") "display:block")) (deftest "hidden" (assert= (tw-resolve-layout "hidden") "display:none")) (deftest "grid" (assert= (tw-resolve-layout "grid") "display:grid")) (deftest "inline" (assert= (tw-resolve-layout "inline") "display:inline")) (deftest "inline-block" (assert= (tw-resolve-layout "inline-block") "display:inline-block")) (deftest "inline-flex" (assert= (tw-resolve-layout "inline-flex") "display:inline-flex")) (deftest "inline-grid" (assert= (tw-resolve-layout "inline-grid") "display:inline-grid")) (deftest "table" (assert= (tw-resolve-layout "table") "display:table")) (deftest "contents" (assert= (tw-resolve-layout "contents") "display:contents"))) (defsuite "tw-flex-direction" (deftest "flex-row" (assert= (tw-resolve-layout "flex-row") "flex-direction:row")) (deftest "flex-col" (assert= (tw-resolve-layout "flex-col") "flex-direction:column")) (deftest "flex-row-reverse" (assert= (tw-resolve-layout "flex-row-reverse") "flex-direction:row-reverse")) (deftest "flex-col-reverse" (assert= (tw-resolve-layout "flex-col-reverse") "flex-direction:column-reverse")) (deftest "flex-wrap" (assert= (tw-resolve-layout "flex-wrap") "flex-wrap:wrap")) (deftest "flex-nowrap" (assert= (tw-resolve-layout "flex-nowrap") "flex-wrap:nowrap")) (deftest "flex-wrap-reverse" (assert= (tw-resolve-layout "flex-wrap-reverse") "flex-wrap:wrap-reverse"))) (defsuite "tw-flex-shorthand" (deftest "flex-1" (assert= (tw-resolve-layout "flex-1") "flex:1 1 0%")) (deftest "flex-auto" (assert= (tw-resolve-layout "flex-auto") "flex:1 1 auto")) (deftest "flex-initial" (assert= (tw-resolve-layout "flex-initial") "flex:0 1 auto")) (deftest "flex-none" (assert= (tw-resolve-layout "flex-none") "flex:none")) (deftest "grow" (assert= (tw-resolve-layout "grow") "flex-grow:1")) (deftest "grow-0" (assert= (tw-resolve-layout "grow-0") "flex-grow:0")) (deftest "shrink" (assert= (tw-resolve-layout "shrink") "flex-shrink:1")) (deftest "shrink-0" (assert= (tw-resolve-layout "shrink-0") "flex-shrink:0")) (deftest "basis-auto" (assert= (tw-resolve-layout "basis-auto") "flex-basis:auto")) (deftest "basis-full" (assert= (tw-resolve-layout "basis-full") "flex-basis:100%")) (deftest "basis-0" (assert= (tw-resolve-layout "basis-0") "flex-basis:0px")) (deftest "basis-1/2" (assert= (tw-resolve-layout "basis-1/2") "flex-basis:50%")) (deftest "basis-4" (assert= (tw-resolve-layout "basis-4") "flex-basis:1rem"))) (defsuite "tw-justify" (deftest "justify-start" (assert= (tw-resolve-layout "justify-start") "justify-content:flex-start")) (deftest "justify-end" (assert= (tw-resolve-layout "justify-end") "justify-content:flex-end")) (deftest "justify-center" (assert= (tw-resolve-layout "justify-center") "justify-content:center")) (deftest "justify-between" (assert= (tw-resolve-layout "justify-between") "justify-content:space-between")) (deftest "justify-around" (assert= (tw-resolve-layout "justify-around") "justify-content:space-around")) (deftest "justify-evenly" (assert= (tw-resolve-layout "justify-evenly") "justify-content:space-evenly")) (deftest "justify-stretch" (assert= (tw-resolve-layout "justify-stretch") "justify-content:stretch"))) (defsuite "tw-alignment" (deftest "items-start" (assert= (tw-resolve-layout "items-start") "align-items:flex-start")) (deftest "items-end" (assert= (tw-resolve-layout "items-end") "align-items:flex-end")) (deftest "items-center" (assert= (tw-resolve-layout "items-center") "align-items:center")) (deftest "items-baseline" (assert= (tw-resolve-layout "items-baseline") "align-items:baseline")) (deftest "items-stretch" (assert= (tw-resolve-layout "items-stretch") "align-items:stretch")) (deftest "self-auto" (assert= (tw-resolve-layout "self-auto") "align-self:auto")) (deftest "self-start" (assert= (tw-resolve-layout "self-start") "align-self:flex-start")) (deftest "self-end" (assert= (tw-resolve-layout "self-end") "align-self:flex-end")) (deftest "self-center" (assert= (tw-resolve-layout "self-center") "align-self:center")) (deftest "self-stretch" (assert= (tw-resolve-layout "self-stretch") "align-self:stretch")) (deftest "self-baseline" (assert= (tw-resolve-layout "self-baseline") "align-self:baseline")) (deftest "content-start" (assert= (tw-resolve-layout "content-start") "align-content:flex-start")) (deftest "content-center" (assert= (tw-resolve-layout "content-center") "align-content:center")) (deftest "content-between" (assert= (tw-resolve-layout "content-between") "align-content:space-between")) (deftest "content-around" (assert= (tw-resolve-layout "content-around") "align-content:space-around")) (deftest "content-stretch" (assert= (tw-resolve-layout "content-stretch") "align-content:stretch"))) (defsuite "tw-order" (deftest "order-1" (assert= (tw-resolve-layout "order-1") "order:1")) (deftest "order-12" (assert= (tw-resolve-layout "order-12") "order:12")) (deftest "order-first" (assert= (tw-resolve-layout "order-first") "order:-9999")) (deftest "order-last" (assert= (tw-resolve-layout "order-last") "order:9999")) (deftest "order-none" (assert= (tw-resolve-layout "order-none") "order:0"))) (defsuite "tw-padding" (deftest "p-0" (assert= (tw-resolve-layout "p-0") "padding:0px")) (deftest "p-px" (assert= (tw-resolve-layout "p-px") "padding:1px")) (deftest "p-1" (assert= (tw-resolve-layout "p-1") "padding:0.25rem")) (deftest "p-2" (assert= (tw-resolve-layout "p-2") "padding:0.5rem")) (deftest "p-3" (assert= (tw-resolve-layout "p-3") "padding:0.75rem")) (deftest "p-4" (assert= (tw-resolve-layout "p-4") "padding:1rem")) (deftest "p-6" (assert= (tw-resolve-layout "p-6") "padding:1.5rem")) (deftest "p-8" (assert= (tw-resolve-layout "p-8") "padding:2rem")) (deftest "px-4" (assert= (tw-resolve-layout "px-4") "padding-left:1rem;padding-right:1rem")) (deftest "py-2" (assert= (tw-resolve-layout "py-2") "padding-top:0.5rem;padding-bottom:0.5rem")) (deftest "pt-4" (assert= (tw-resolve-layout "pt-4") "padding-top:1rem")) (deftest "pb-4" (assert= (tw-resolve-layout "pb-4") "padding-bottom:1rem")) (deftest "pl-2" (assert= (tw-resolve-layout "pl-2") "padding-left:0.5rem")) (deftest "pr-2" (assert= (tw-resolve-layout "pr-2") "padding-right:0.5rem"))) (defsuite "tw-margin" (deftest "m-0" (assert= (tw-resolve-layout "m-0") "margin:0px")) (deftest "m-auto" (assert= (tw-resolve-layout "m-auto") "margin:auto")) (deftest "m-2" (assert= (tw-resolve-layout "m-2") "margin:0.5rem")) (deftest "m-4" (assert= (tw-resolve-layout "m-4") "margin:1rem")) (deftest "mt-2" (assert= (tw-resolve-layout "mt-2") "margin-top:0.5rem")) (deftest "mt-8" (assert= (tw-resolve-layout "mt-8") "margin-top:2rem")) (deftest "mb-4" (assert= (tw-resolve-layout "mb-4") "margin-bottom:1rem")) (deftest "ml-2" (assert= (tw-resolve-layout "ml-2") "margin-left:0.5rem")) (deftest "mr-2" (assert= (tw-resolve-layout "mr-2") "margin-right:0.5rem")) (deftest "mx-auto" (assert= (tw-resolve-layout "mx-auto") "margin-left:auto;margin-right:auto")) (deftest "my-4" (assert= (tw-resolve-layout "my-4") "margin-top:1rem;margin-bottom:1rem"))) (defsuite "tw-gap" (deftest "gap-1" (assert= (tw-resolve-layout "gap-1") "gap:0.25rem")) (deftest "gap-4" (assert= (tw-resolve-layout "gap-4") "gap:1rem")) (deftest "gap-8" (assert= (tw-resolve-layout "gap-8") "gap:2rem")) (deftest "gap-0" (assert= (tw-resolve-layout "gap-0") "gap:0px")) (deftest "gap-x-4" (assert= (tw-resolve-layout "gap-x-4") "column-gap:1rem")) (deftest "gap-y-2" (assert= (tw-resolve-layout "gap-y-2") "row-gap:0.5rem")) (deftest "space-x-4 → child margin-left" (assert= (get (tw-resolve-layout "space-x-4") :css) "margin-left:1rem")) (deftest "space-y-2 → child margin-top" (assert= (get (tw-resolve-layout "space-y-2") :css) "margin-top:0.5rem"))) (defsuite "tw-space-child-selectors" (deftest "space-y-2 returns dict with :suffix" (assert= (get (tw-resolve-layout "space-y-2") :suffix) ">*+*")) (deftest "space-x-4 returns dict with :suffix" (assert= (get (tw-resolve-layout "space-x-4") :suffix) ">*+*")) (deftest "space-y-4 css is margin-top" (assert= (get (tw-resolve-layout "space-y-4") :css) "margin-top:1rem")) (deftest "space-x-2 css is margin-left" (assert= (get (tw-resolve-layout "space-x-2") :css) "margin-left:0.5rem")) (deftest "space-y-0 css is margin-top:0px" (assert= (get (tw-resolve-layout "space-y-0") :css) "margin-top:0px")) (deftest "space-y-8 css is margin-top:2rem" (assert= (get (tw-resolve-layout "space-y-8") :css) "margin-top:2rem")) (deftest "space-y-4 full rule uses child selector" (let ((result (tw-process-token "space-y-4"))) (assert= (get result "rule") ".sx-space-y-4>*+*{margin-top:1rem}"))) (deftest "space-x-2 full rule uses child selector" (let ((result (tw-process-token "space-x-2"))) (assert= (get result "rule") ".sx-space-x-2>*+*{margin-left:0.5rem}"))) (deftest "gap-4 does NOT use child selector" (let ((result (tw-process-token "gap-4"))) (assert= (get result "rule") ".sx-gap-4{gap:1rem}"))) (deftest "hover:space-y-2 rule includes pseudo + child selector" (let ((result (tw-process-token "hover:space-y-2"))) (assert= (get result "rule") ".sx-hover-space-y-2:hover>*+*{margin-top:0.5rem}")))) (defsuite "tw-spacing-value" (deftest "0 → 0px" (assert= (tw-spacing-value "0") "0px")) (deftest "px → 1px" (assert= (tw-spacing-value "px") "1px")) (deftest "0.5 → 0.125rem" (assert= (tw-spacing-value "0.5") "0.125rem")) (deftest "1 → 0.25rem" (assert= (tw-spacing-value "1") "0.25rem")) (deftest "1.5 → 0.375rem" (assert= (tw-spacing-value "1.5") "0.375rem")) (deftest "2 → 0.5rem" (assert= (tw-spacing-value "2") "0.5rem")) (deftest "4 → 1rem" (assert= (tw-spacing-value "4") "1rem")) (deftest "8 → 2rem" (assert= (tw-spacing-value "8") "2rem")) (deftest "12 → 3rem" (assert= (tw-spacing-value "12") "3rem")) (deftest "16 → 4rem" (assert= (tw-spacing-value "16") "4rem")) (deftest "20 → 5rem" (assert= (tw-spacing-value "20") "5rem")) (deftest "24 → 6rem" (assert= (tw-spacing-value "24") "6rem")) (deftest "auto → auto" (assert= (tw-spacing-value "auto") "auto"))) (defsuite "tw-grid" (deftest "grid-cols-1" (assert= (tw-resolve-layout "grid-cols-1") "grid-template-columns:repeat(1,minmax(0,1fr))")) (deftest "grid-cols-2" (assert= (tw-resolve-layout "grid-cols-2") "grid-template-columns:repeat(2,minmax(0,1fr))")) (deftest "grid-cols-3" (assert= (tw-resolve-layout "grid-cols-3") "grid-template-columns:repeat(3,minmax(0,1fr))")) (deftest "grid-cols-12" (assert= (tw-resolve-layout "grid-cols-12") "grid-template-columns:repeat(12,minmax(0,1fr))")) (deftest "grid-cols-none" (assert= (tw-resolve-layout "grid-cols-none") "grid-template-columns:none")) (deftest "grid-rows-3" (assert= (tw-resolve-layout "grid-rows-3") "grid-template-rows:repeat(3,minmax(0,1fr))")) (deftest "grid-rows-none" (assert= (tw-resolve-layout "grid-rows-none") "grid-template-rows:none")) (deftest "grid-flow-row" (assert= (tw-resolve-layout "grid-flow-row") "grid-auto-flow:row")) (deftest "grid-flow-col" (assert= (tw-resolve-layout "grid-flow-col") "grid-auto-flow:column")) (deftest "col-span-2" (assert= (tw-resolve-layout "col-span-2") "grid-column:span 2 / span 2")) (deftest "col-span-full" (assert= (tw-resolve-layout "col-span-full") "grid-column:1 / -1")) (deftest "col-start-1" (assert= (tw-resolve-layout "col-start-1") "grid-column-start:1")) (deftest "col-end-3" (assert= (tw-resolve-layout "col-end-3") "grid-column-end:3")) (deftest "row-span-2" (assert= (tw-resolve-layout "row-span-2") "grid-row:span 2 / span 2")) (deftest "row-span-full" (assert= (tw-resolve-layout "row-span-full") "grid-row:1 / -1")) (deftest "row-start-1" (assert= (tw-resolve-layout "row-start-1") "grid-row-start:1"))) (defsuite "tw-position" (deftest "relative" (assert= (tw-resolve-layout "relative") "position:relative")) (deftest "absolute" (assert= (tw-resolve-layout "absolute") "position:absolute")) (deftest "fixed" (assert= (tw-resolve-layout "fixed") "position:fixed")) (deftest "sticky" (assert= (tw-resolve-layout "sticky") "position:sticky")) (deftest "static" (assert= (tw-resolve-layout "static") "position:static"))) (defsuite "tw-inset" (deftest "top-0" (assert= (tw-resolve-layout "top-0") "top:0px")) (deftest "top-4" (assert= (tw-resolve-layout "top-4") "top:1rem")) (deftest "right-0" (assert= (tw-resolve-layout "right-0") "right:0px")) (deftest "bottom-0" (assert= (tw-resolve-layout "bottom-0") "bottom:0px")) (deftest "left-0" (assert= (tw-resolve-layout "left-0") "left:0px")) (deftest "left-4" (assert= (tw-resolve-layout "left-4") "left:1rem")) (deftest "inset-0" (assert= (tw-resolve-layout "inset-0") "inset:0px")) (deftest "inset-4" (assert= (tw-resolve-layout "inset-4") "inset:1rem")) (deftest "inset-x-4" (assert= (tw-resolve-layout "inset-x-4") "left:1rem;right:1rem")) (deftest "inset-y-0" (assert= (tw-resolve-layout "inset-y-0") "top:0px;bottom:0px"))) (defsuite "tw-z-index" (deftest "z-0" (assert= (tw-resolve-layout "z-0") "z-index:0")) (deftest "z-10" (assert= (tw-resolve-layout "z-10") "z-index:10")) (deftest "z-20" (assert= (tw-resolve-layout "z-20") "z-index:20")) (deftest "z-50" (assert= (tw-resolve-layout "z-50") "z-index:50")) (deftest "z-auto" (assert= (tw-resolve-layout "z-auto") "z-index:auto"))) (defsuite "tw-dimensions" (deftest "w-full" (assert= (tw-resolve-layout "w-full") "width:100%")) (deftest "w-screen" (assert= (tw-resolve-layout "w-screen") "width:100vw")) (deftest "w-auto" (assert= (tw-resolve-layout "w-auto") "width:auto")) (deftest "w-min" (assert= (tw-resolve-layout "w-min") "width:min-content")) (deftest "w-max" (assert= (tw-resolve-layout "w-max") "width:max-content")) (deftest "w-fit" (assert= (tw-resolve-layout "w-fit") "width:fit-content")) (deftest "w-4" (assert= (tw-resolve-layout "w-4") "width:1rem")) (deftest "w-12" (assert= (tw-resolve-layout "w-12") "width:3rem")) (deftest "w-1/2" (assert= (tw-resolve-layout "w-1/2") "width:50%")) (deftest "w-1/3" (assert= (tw-resolve-layout "w-1/3") "width:33.3333%")) (deftest "w-2/3" (assert= (tw-resolve-layout "w-2/3") "width:66.6667%")) (deftest "h-full" (assert= (tw-resolve-layout "h-full") "height:100%")) (deftest "h-screen" (assert= (tw-resolve-layout "h-screen") "height:100vh")) (deftest "h-auto" (assert= (tw-resolve-layout "h-auto") "height:auto")) (deftest "h-16" (assert= (tw-resolve-layout "h-16") "height:4rem"))) (defsuite "tw-max-min" (deftest "max-w-xs" (assert= (tw-resolve-layout "max-w-xs") "max-width:20rem")) (deftest "max-w-md" (assert= (tw-resolve-layout "max-w-md") "max-width:28rem")) (deftest "max-w-xl" (assert= (tw-resolve-layout "max-w-xl") "max-width:36rem")) (deftest "max-w-2xl" (assert= (tw-resolve-layout "max-w-2xl") "max-width:42rem")) (deftest "max-w-7xl" (assert= (tw-resolve-layout "max-w-7xl") "max-width:80rem")) (deftest "max-w-prose" (assert= (tw-resolve-layout "max-w-prose") "max-width:65ch")) (deftest "max-w-none" (assert= (tw-resolve-layout "max-w-none") "max-width:none")) (deftest "max-w-full" (assert= (tw-resolve-layout "max-w-full") "max-width:100%")) (deftest "max-h-full" (assert= (tw-resolve-layout "max-h-full") "max-height:100%")) (deftest "max-h-screen" (assert= (tw-resolve-layout "max-h-screen") "max-height:100vh")) (deftest "min-w-0" (assert= (tw-resolve-layout "min-w-0") "min-width:0px")) (deftest "min-w-full" (assert= (tw-resolve-layout "min-w-full") "min-width:100%")) (deftest "min-h-0" (assert= (tw-resolve-layout "min-h-0") "min-height:0px")) (deftest "min-h-full" (assert= (tw-resolve-layout "min-h-full") "min-height:100%")) (deftest "min-h-screen" (assert= (tw-resolve-layout "min-h-screen") "min-height:100vh"))) (defsuite "tw-overflow" (deftest "overflow-auto" (assert= (tw-resolve-layout "overflow-auto") "overflow:auto")) (deftest "overflow-hidden" (assert= (tw-resolve-layout "overflow-hidden") "overflow:hidden")) (deftest "overflow-visible" (assert= (tw-resolve-layout "overflow-visible") "overflow:visible")) (deftest "overflow-scroll" (assert= (tw-resolve-layout "overflow-scroll") "overflow:scroll")) (deftest "overflow-x-auto" (assert= (tw-resolve-layout "overflow-x-auto") "overflow-x:auto")) (deftest "overflow-x-hidden" (assert= (tw-resolve-layout "overflow-x-hidden") "overflow-x:hidden")) (deftest "overflow-y-auto" (assert= (tw-resolve-layout "overflow-y-auto") "overflow-y:auto")) (deftest "overflow-y-scroll" (assert= (tw-resolve-layout "overflow-y-scroll") "overflow-y:scroll"))) (defsuite "tw-layout-misc" (deftest "aspect-auto" (assert= (tw-resolve-layout "aspect-auto") "aspect-ratio:auto")) (deftest "aspect-square" (assert= (tw-resolve-layout "aspect-square") "aspect-ratio:1 / 1")) (deftest "aspect-video" (assert= (tw-resolve-layout "aspect-video") "aspect-ratio:16 / 9")) (deftest "object-cover" (assert= (tw-resolve-layout "object-cover") "object-fit:cover")) (deftest "object-contain" (assert= (tw-resolve-layout "object-contain") "object-fit:contain")) (deftest "object-fill" (assert= (tw-resolve-layout "object-fill") "object-fit:fill")) (deftest "visible" (assert= (tw-resolve-layout "visible") "visibility:visible")) (deftest "invisible" (assert= (tw-resolve-layout "invisible") "visibility:hidden")) (deftest "collapse" (assert= (tw-resolve-layout "collapse") "visibility:collapse")) (deftest "container" (assert= (tw-resolve-layout "container") "width:100%;max-width:100%")) (deftest "isolate" (assert= (tw-resolve-layout "isolate") "isolation:isolate"))) (defsuite "tw-text-sizes" (deftest "text-xs" (assert= (tw-resolve-type "text-xs") "font-size:0.75rem;line-height:1rem")) (deftest "text-sm" (assert= (tw-resolve-type "text-sm") "font-size:0.875rem;line-height:1.25rem")) (deftest "text-base" (assert= (tw-resolve-type "text-base") "font-size:1rem;line-height:1.5rem")) (deftest "text-lg" (assert= (tw-resolve-type "text-lg") "font-size:1.125rem;line-height:1.75rem")) (deftest "text-xl" (assert= (tw-resolve-type "text-xl") "font-size:1.25rem;line-height:1.75rem")) (deftest "text-2xl" (assert= (tw-resolve-type "text-2xl") "font-size:1.5rem;line-height:2rem")) (deftest "text-3xl" (assert= (tw-resolve-type "text-3xl") "font-size:1.875rem;line-height:2.25rem")) (deftest "text-4xl" (assert= (tw-resolve-type "text-4xl") "font-size:2.25rem;line-height:2.5rem")) (deftest "text-5xl" (assert= (tw-resolve-type "text-5xl") "font-size:3rem;line-height:1")) (deftest "text-6xl" (assert= (tw-resolve-type "text-6xl") "font-size:3.75rem;line-height:1")) (deftest "text-7xl" (assert= (tw-resolve-type "text-7xl") "font-size:4.5rem;line-height:1")) (deftest "text-8xl" (assert= (tw-resolve-type "text-8xl") "font-size:6rem;line-height:1")) (deftest "text-9xl" (assert= (tw-resolve-type "text-9xl") "font-size:8rem;line-height:1"))) (defsuite "tw-text-align" (deftest "text-left" (assert= (tw-resolve-type "text-left") "text-align:left")) (deftest "text-center" (assert= (tw-resolve-type "text-center") "text-align:center")) (deftest "text-right" (assert= (tw-resolve-type "text-right") "text-align:right")) (deftest "text-justify" (assert= (tw-resolve-type "text-justify") "text-align:justify")) (deftest "text-start" (assert= (tw-resolve-type "text-start") "text-align:start")) (deftest "text-end" (assert= (tw-resolve-type "text-end") "text-align:end"))) (defsuite "tw-font-weight" (deftest "font-thin" (assert= (tw-resolve-type "font-thin") "font-weight:100")) (deftest "font-extralight" (assert= (tw-resolve-type "font-extralight") "font-weight:200")) (deftest "font-light" (assert= (tw-resolve-type "font-light") "font-weight:300")) (deftest "font-normal" (assert= (tw-resolve-type "font-normal") "font-weight:400")) (deftest "font-medium" (assert= (tw-resolve-type "font-medium") "font-weight:500")) (deftest "font-semibold" (assert= (tw-resolve-type "font-semibold") "font-weight:600")) (deftest "font-bold" (assert= (tw-resolve-type "font-bold") "font-weight:700")) (deftest "font-extrabold" (assert= (tw-resolve-type "font-extrabold") "font-weight:800")) (deftest "font-black" (assert= (tw-resolve-type "font-black") "font-weight:900"))) (defsuite "tw-font-family" (deftest "font-sans" (assert= (tw-resolve-type "font-sans") "font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,\"Noto Sans\",sans-serif")) (deftest "font-serif" (assert= (tw-resolve-type "font-serif") "font-family:ui-serif,Georgia,Cambria,\"Times New Roman\",Times,serif")) (deftest "font-mono" (assert= (tw-resolve-type "font-mono") "font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"))) (defsuite "tw-font-style" (deftest "italic" (assert= (tw-resolve-type "italic") "font-style:italic")) (deftest "not-italic" (assert= (tw-resolve-type "not-italic") "font-style:normal"))) (defsuite "tw-text-transform" (deftest "uppercase" (assert= (tw-resolve-type "uppercase") "text-transform:uppercase")) (deftest "lowercase" (assert= (tw-resolve-type "lowercase") "text-transform:lowercase")) (deftest "capitalize" (assert= (tw-resolve-type "capitalize") "text-transform:capitalize")) (deftest "normal-case" (assert= (tw-resolve-type "normal-case") "text-transform:none"))) (defsuite "tw-leading" (deftest "leading-none" (assert= (tw-resolve-type "leading-none") "line-height:1")) (deftest "leading-tight" (assert= (tw-resolve-type "leading-tight") "line-height:1.25")) (deftest "leading-snug" (assert= (tw-resolve-type "leading-snug") "line-height:1.375")) (deftest "leading-normal" (assert= (tw-resolve-type "leading-normal") "line-height:1.5")) (deftest "leading-relaxed" (assert= (tw-resolve-type "leading-relaxed") "line-height:1.625")) (deftest "leading-loose" (assert= (tw-resolve-type "leading-loose") "line-height:2")) (deftest "leading-6" (assert= (tw-resolve-type "leading-6") "line-height:1.5rem")) (deftest "leading-8" (assert= (tw-resolve-type "leading-8") "line-height:2rem"))) (defsuite "tw-tracking" (deftest "tracking-tighter" (assert= (tw-resolve-type "tracking-tighter") "letter-spacing:-0.05em")) (deftest "tracking-tight" (assert= (tw-resolve-type "tracking-tight") "letter-spacing:-0.025em")) (deftest "tracking-normal" (assert= (tw-resolve-type "tracking-normal") "letter-spacing:0em")) (deftest "tracking-wide" (assert= (tw-resolve-type "tracking-wide") "letter-spacing:0.025em")) (deftest "tracking-wider" (assert= (tw-resolve-type "tracking-wider") "letter-spacing:0.05em")) (deftest "tracking-widest" (assert= (tw-resolve-type "tracking-widest") "letter-spacing:0.1em"))) (defsuite "tw-whitespace" (deftest "whitespace-normal" (assert= (tw-resolve-type "whitespace-normal") "white-space:normal")) (deftest "whitespace-nowrap" (assert= (tw-resolve-type "whitespace-nowrap") "white-space:nowrap")) (deftest "whitespace-pre" (assert= (tw-resolve-type "whitespace-pre") "white-space:pre")) (deftest "whitespace-pre-line" (assert= (tw-resolve-type "whitespace-pre-line") "white-space:pre-line")) (deftest "whitespace-pre-wrap" (assert= (tw-resolve-type "whitespace-pre-wrap") "white-space:pre-wrap")) (deftest "break-normal" (assert= (tw-resolve-type "break-normal") "overflow-wrap:normal;word-break:normal")) (deftest "break-words" (assert= (tw-resolve-type "break-words") "overflow-wrap:break-word")) (deftest "break-all" (assert= (tw-resolve-type "break-all") "word-break:break-all")) (deftest "break-keep" (assert= (tw-resolve-type "break-keep") "word-break:keep-all"))) (defsuite "tw-truncate" (deftest "truncate" (assert= (tw-resolve-type "truncate") "overflow:hidden;text-overflow:ellipsis;white-space:nowrap")) (deftest "text-ellipsis" (assert= (tw-resolve-type "text-ellipsis") nil)) (deftest "line-clamp-3" (assert= (tw-resolve-type "line-clamp-3") "overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3"))) (defsuite "tw-vertical-align" (deftest "align-baseline" (assert= (tw-resolve-type "align-baseline") "vertical-align:baseline")) (deftest "align-top" (assert= (tw-resolve-type "align-top") "vertical-align:top")) (deftest "align-middle" (assert= (tw-resolve-type "align-middle") "vertical-align:middle")) (deftest "align-bottom" (assert= (tw-resolve-type "align-bottom") "vertical-align:bottom")) (deftest "align-text-top" (assert= (tw-resolve-type "align-text-top") "vertical-align:text-top")) (deftest "align-text-bottom" (assert= (tw-resolve-type "align-text-bottom") "vertical-align:text-bottom")) (deftest "align-sub" (assert= (tw-resolve-type "align-sub") "vertical-align:sub")) (deftest "align-super" (assert= (tw-resolve-type "align-super") "vertical-align:super"))) (defsuite "tw-list" (deftest "list-none" (assert= (tw-resolve-type "list-none") "list-style-type:none")) (deftest "list-disc" (assert= (tw-resolve-type "list-disc") "list-style-type:disc")) (deftest "list-decimal" (assert= (tw-resolve-type "list-decimal") "list-style-type:decimal")) (deftest "list-inside" (assert= (tw-resolve-type "list-inside") "list-style-position:inside")) (deftest "list-outside" (assert= (tw-resolve-type "list-outside") "list-style-position:outside"))) (defsuite "tw-type-misc" (deftest "text-wrap" (assert= (tw-resolve-type "text-wrap") "text-wrap:wrap")) (deftest "text-nowrap" (assert= (tw-resolve-type "text-nowrap") "text-wrap:nowrap")) (deftest "text-balance" (assert= (tw-resolve-type "text-balance") "text-wrap:balance")) (deftest "text-pretty" (assert= (tw-resolve-type "text-pretty") "text-wrap:pretty")) (deftest "indent-4" (assert= (tw-resolve-type "indent-4") "text-indent:1rem")) (deftest "indent-8" (assert= (tw-resolve-type "indent-8") "text-indent:2rem")) (deftest "hyphens-auto" (assert= (tw-resolve-type "hyphens-auto") "hyphens:auto")) (deftest "hyphens-none" (assert= (tw-resolve-type "hyphens-none") "hyphens:none")) (deftest "content-none" (assert= (tw-resolve-type "content-none") "content:none")) (deftest "antialiased" (assert= (tw-resolve-type "antialiased") "-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale")) (deftest "tabular-nums" (assert= (tw-resolve-type "tabular-nums") "font-variant-numeric:tabular-nums")) (deftest "ordinal" (assert= (tw-resolve-type "ordinal") "font-variant-numeric:ordinal")) (deftest "slashed-zero" (assert= (tw-resolve-type "slashed-zero") "font-variant-numeric:slashed-zero"))) (defsuite "tw-arb-colour" (deftest "bg-[#ff0000]" (assert= (tw-resolve-arbitrary "bg-[#ff0000]") "background-color:#ff0000")) (deftest "bg-[rgb(255,0,0)]" (assert= (tw-resolve-arbitrary "bg-[rgb(255,0,0)]") "background-color:rgb(255,0,0)")) (deftest "bg-[hsl(200,50%,50%)]" (assert= (tw-resolve-arbitrary "bg-[hsl(200,50%,50%)]") "background-color:hsl(200,50%,50%)")) (deftest "text-[#333]" (assert= (tw-resolve-arbitrary "text-[#333]") "color:#333")) (deftest "text-[red]" (assert= (tw-resolve-arbitrary "text-[red]") "color:red")) (deftest "border-color-[#ccc]" (assert= (tw-resolve-arbitrary "border-color-[#ccc]") "border-color:#ccc")) (deftest "fill-[currentColor]" (assert= (tw-resolve-arbitrary "fill-[currentColor]") "fill:currentColor")) (deftest "accent-[#0ea5e9]" (assert= (tw-resolve-arbitrary "accent-[#0ea5e9]") "accent-color:#0ea5e9"))) (defsuite "tw-arb-spacing" (deftest "p-[10px]" (assert= (tw-resolve-arbitrary "p-[10px]") "padding:10px")) (deftest "p-[1.5rem]" (assert= (tw-resolve-arbitrary "p-[1.5rem]") "padding:1.5rem")) (deftest "pt-[20px]" (assert= (tw-resolve-arbitrary "pt-[20px]") "padding-top:20px")) (deftest "m-[auto]" (assert= (tw-resolve-arbitrary "m-[auto]") "margin:auto")) (deftest "mt-[-1rem]" (assert= (tw-resolve-arbitrary "mt-[-1rem]") "margin-top:-1rem")) (deftest "gap-[20px]" (assert= (tw-resolve-arbitrary "gap-[20px]") "gap:20px")) (deftest "gap-x-[1.5rem]" (assert= (tw-resolve-arbitrary "gap-x-[1.5rem]") "column-gap:1.5rem")) (deftest "gap-y-[2rem]" (assert= (tw-resolve-arbitrary "gap-y-[2rem]") "row-gap:2rem"))) (defsuite "tw-arb-dimensions" (deftest "w-[300px]" (assert= (tw-resolve-arbitrary "w-[300px]") "width:300px")) (deftest "w-[50%]" (assert= (tw-resolve-arbitrary "w-[50%]") "width:50%")) (deftest "w-[calc(100%-2rem)]" (assert= (tw-resolve-arbitrary "w-[calc(100%-2rem)]") "width:calc(100%-2rem)")) (deftest "h-[100vh]" (assert= (tw-resolve-arbitrary "h-[100vh]") "height:100vh")) (deftest "h-[500px]" (assert= (tw-resolve-arbitrary "h-[500px]") "height:500px")) (deftest "min-w-[320px]" (assert= (tw-resolve-arbitrary "min-w-[320px]") "min-width:320px")) (deftest "max-w-[800px]" (assert= (tw-resolve-arbitrary "max-w-[800px]") "max-width:800px")) (deftest "max-h-[90vh]" (assert= (tw-resolve-arbitrary "max-h-[90vh]") "max-height:90vh"))) (defsuite "tw-arb-position" (deftest "top-[50%]" (assert= (tw-resolve-arbitrary "top-[50%]") "top:50%")) (deftest "right-[1rem]" (assert= (tw-resolve-arbitrary "right-[1rem]") "right:1rem")) (deftest "bottom-[0]" (assert= (tw-resolve-arbitrary "bottom-[0]") "bottom:0")) (deftest "left-[auto]" (assert= (tw-resolve-arbitrary "left-[auto]") "left:auto")) (deftest "inset-[0]" (assert= (tw-resolve-arbitrary "inset-[0]") "inset:0")) (deftest "z-[999]" (assert= (tw-resolve-arbitrary "z-[999]") "z-index:999")) (deftest "z-[-1]" (assert= (tw-resolve-arbitrary "z-[-1]") "z-index:-1"))) (defsuite "tw-arb-typography" (deftest "font-size-[20px]" (assert= (tw-resolve-arbitrary "font-size-[20px]") "font-size:20px")) (deftest "leading-[1.6]" (assert= (tw-resolve-arbitrary "leading-[1.6]") "line-height:1.6")) (deftest "leading-[2rem]" (assert= (tw-resolve-arbitrary "leading-[2rem]") "line-height:2rem")) (deftest "tracking-[0.05em]" (assert= (tw-resolve-arbitrary "tracking-[0.05em]") "letter-spacing:0.05em")) (deftest "indent-[2em]" (assert= (tw-resolve-arbitrary "indent-[2em]") "text-indent:2em"))) (defsuite "tw-arb-borders" (deftest "border-[3px]" (assert= (tw-resolve-arbitrary "border-[3px]") "border-width:3px")) (deftest "rounded-[12px]" (assert= (tw-resolve-arbitrary "rounded-[12px]") "border-radius:12px")) (deftest "rounded-[50%]" (assert= (tw-resolve-arbitrary "rounded-[50%]") "border-radius:50%")) (deftest "opacity-[0.8]" (assert= (tw-resolve-arbitrary "opacity-[0.8]") "opacity:0.8")) (deftest "shadow-[0_4px_8px_rgba(0,0,0,0.1)]" (assert= (tw-resolve-arbitrary "shadow-[0_4px_8px_rgba(0,0,0,0.1)]") "box-shadow:0 4px 8px rgba(0,0,0,0.1)"))) (defsuite "tw-arb-grid" (deftest "grid-cols-[1fr_2fr]" (assert= (tw-resolve-arbitrary "grid-cols-[1fr_2fr]") "grid-template-columns:1fr 2fr")) (deftest "grid-cols-[200px_1fr_200px]" (assert= (tw-resolve-arbitrary "grid-cols-[200px_1fr_200px]") "grid-template-columns:200px 1fr 200px")) (deftest "grid-rows-[auto_1fr_auto]" (assert= (tw-resolve-arbitrary "grid-rows-[auto_1fr_auto]") "grid-template-rows:auto 1fr auto")) (deftest "basis-[200px]" (assert= (tw-resolve-arbitrary "basis-[200px]") "flex-basis:200px")) (deftest "order-[99]" (assert= (tw-resolve-arbitrary "order-[99]") "order:99")) (deftest "order-[-1]" (assert= (tw-resolve-arbitrary "order-[-1]") "order:-1"))) (defsuite "tw-arb-misc" (deftest "duration-[250ms]" (assert= (tw-resolve-arbitrary "duration-[250ms]") "transition-duration:250ms")) (deftest "delay-[100ms]" (assert= (tw-resolve-arbitrary "delay-[100ms]") "transition-delay:100ms")) (deftest "aspect-[4/3]" (assert= (tw-resolve-arbitrary "aspect-[4/3]") "aspect-ratio:4/3")) (deftest "columns-[3]" (assert= (tw-resolve-arbitrary "columns-[3]") "columns:3"))) (defsuite "tw-arb-edge" (deftest "no bracket → nil" (assert-nil (tw-resolve-arbitrary "flex"))) (deftest "unknown prefix → nil" (assert-nil (tw-resolve-arbitrary "banana-[42px]"))) (deftest "underscore → space" (assert= (tw-resolve-arbitrary "shadow-[0_1px_2px_black]") "box-shadow:0 1px 2px black")) (deftest "multiple underscores" (assert= (tw-resolve-arbitrary "grid-cols-[1fr_2fr_1fr_2fr]") "grid-template-columns:1fr 2fr 1fr 2fr"))) (defsuite "tw-arb-pipeline" (deftest "plain arbitrary" (let ((r (tw-process-token "w-[300px]"))) (assert (contains? (get r "rule") "width:300px")))) (deftest "hover: arbitrary" (let ((r (tw-process-token "hover:bg-[#ff0000]"))) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "background-color:#ff0000")))) (deftest "sm: arbitrary" (let ((r (tw-process-token "sm:w-[50%]"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "width:50%")))) (deftest "lg: arbitrary grid" (let ((r (tw-process-token "lg:grid-cols-[1fr_2fr_1fr]"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "grid-template-columns:1fr 2fr 1fr")))) (deftest "focus: arbitrary border" (let ((r (tw-process-token "focus:border-[2px]"))) (assert (contains? (get r "rule") ":focus")) (assert (contains? (get r "rule") "border-width:2px")))) (deftest "arbitrary class name" (assert= (get (tw-process-token "w-[300px]") "cls") "sx-w-[300px]")) (deftest "real component with arbitrary values" (let ((tokens (list "flex" "gap-4" "w-[calc(100%-2rem)]" "max-w-[800px]" "p-[1.5rem]" "rounded-[12px]" "bg-[#f5f5f4]" "shadow-[0_2px_4px_rgba(0,0,0,0.1)]" "sm:p-[2rem]" "lg:max-w-[1200px]"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens))))) (defsuite "tw-class-names" (deftest "simple token → sx-{token}" (assert= (get (tw-process-token "flex") "cls") "sx-flex")) (deftest "hyphenated → sx-{token}" (assert= (get (tw-process-token "flex-col") "cls") "sx-flex-col")) (deftest "colon variant → colons become hyphens" (assert= (get (tw-process-token "hover:bg-sky-200") "cls") "sx-hover-bg-sky-200")) (deftest "breakpoint variant" (assert= (get (tw-process-token "sm:flex") "cls") "sx-sm-flex")) (deftest "dot in token → becomes d" (assert= (get (tw-process-token "p-0.5") "cls") "sx-p-0d5")) (deftest "combined bp+state" (assert= (get (tw-process-token "sm:hover:bg-sky-200") "cls") "sx-sm-hover-bg-sky-200")) (deftest "negative prefix preserved" (assert= (get (tw-process-token "-mt-4") "cls") "sx--mt-4")) (deftest "spacing token" (assert= (get (tw-process-token "p-4") "cls") "sx-p-4")) (deftest "colour token" (assert= (get (tw-process-token "bg-sky-500") "cls") "sx-bg-sky-500")) (deftest "compound layout token" (assert= (get (tw-process-token "grid-cols-3") "cls") "sx-grid-cols-3")) (deftest "fraction token → slash stays" (assert= (get (tw-process-token "w-1/2") "cls") "sx-w-1/2"))) (defsuite "tw-token-plain" (deftest "flex → display:flex rule" (let ((r (tw-process-token "flex"))) (assert (contains? (get r "rule") "display:flex")))) (deftest "p-4 → padding:1rem rule" (let ((r (tw-process-token "p-4"))) (assert (contains? (get r "rule") "padding:1rem")))) (deftest "bg-sky-500 → background-color rule" (let ((r (tw-process-token "bg-sky-500"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%)")))) (deftest "text-lg → font-size rule" (let ((r (tw-process-token "text-lg"))) (assert (contains? (get r "rule") "font-size:1.125rem")))) (deftest "font-bold → font-weight rule" (let ((r (tw-process-token "font-bold"))) (assert (contains? (get r "rule") "font-weight:700")))) (deftest "flex-col → flex-direction rule" (let ((r (tw-process-token "flex-col"))) (assert (contains? (get r "rule") "flex-direction:column")))) (deftest "justify-between → justify-content rule" (let ((r (tw-process-token "justify-between"))) (assert (contains? (get r "rule") "justify-content:space-between")))) (deftest "items-center → align-items rule" (let ((r (tw-process-token "items-center"))) (assert (contains? (get r "rule") "align-items:center")))) (deftest "grid-cols-3 → grid-template-columns rule" (let ((r (tw-process-token "grid-cols-3"))) (assert (contains? (get r "rule") "grid-template-columns:repeat(3,minmax(0,1fr))")))) (deftest "relative → position:relative rule" (let ((r (tw-process-token "relative"))) (assert (contains? (get r "rule") "position:relative")))) (deftest "z-10 → z-index:10 rule" (let ((r (tw-process-token "z-10"))) (assert (contains? (get r "rule") "z-index:10")))) (deftest "unresolvable → nil" (assert-nil (tw-process-token "bogus-token-xyz")))) (defsuite "tw-token-states" (deftest "hover: adds :hover pseudo" (let ((r (tw-process-token "hover:bg-sky-200"))) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "background-color:hsl(199,89%,87%)")))) (deftest "focus: adds :focus pseudo" (let ((r (tw-process-token "focus:border-blue-500"))) (assert (contains? (get r "rule") ":focus")) (assert (contains? (get r "rule") "border-color:hsl(217,91%,53%)")))) (deftest "active: adds :active pseudo" (let ((r (tw-process-token "active:bg-sky-300"))) (assert (contains? (get r "rule") ":active")))) (deftest "disabled: adds :disabled pseudo" (let ((r (tw-process-token "disabled:opacity-50"))) (assert (contains? (get r "rule") ":disabled")) (assert (contains? (get r "rule") "opacity:0.5")))) (deftest "focus-visible: pseudo" (let ((r (tw-process-token "focus-visible:ring-2"))) (assert (contains? (get r "rule") ":focus-visible")))) (deftest "first: → :first-child" (let ((r (tw-process-token "first:mt-0"))) (assert (contains? (get r "rule") ":first-child")))) (deftest "last: → :last-child" (let ((r (tw-process-token "last:mb-0"))) (assert (contains? (get r "rule") ":last-child")))) (deftest "placeholder: → ::placeholder" (let ((r (tw-process-token "placeholder:text-stone-400"))) (assert (contains? (get r "rule") "::placeholder")))) (deftest "checked: → :checked" (let ((r (tw-process-token "checked:bg-sky-500"))) (assert (contains? (get r "rule") ":checked")))) (deftest "even: → :nth-child(even)" (let ((r (tw-process-token "even:bg-stone-100"))) (assert (contains? (get r "rule") ":nth-child(even)")))) (deftest "odd: → :nth-child(odd)" (let ((r (tw-process-token "odd:bg-stone-200"))) (assert (contains? (get r "rule") ":nth-child(odd)"))))) (defsuite "tw-token-breakpoints" (deftest "sm: → 640px media query" (let ((r (tw-process-token "sm:flex"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "display:flex")))) (deftest "md: → 768px" (let ((r (tw-process-token "md:block"))) (assert (contains? (get r "rule") "@media(min-width:768px)")))) (deftest "lg: → 1024px" (let ((r (tw-process-token "lg:grid-cols-3"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(3,minmax(0,1fr))")))) (deftest "xl: → 1280px" (let ((r (tw-process-token "xl:hidden"))) (assert (contains? (get r "rule") "@media(min-width:1280px)")) (assert (contains? (get r "rule") "display:none")))) (deftest "2xl: → 1536px" (let ((r (tw-process-token "2xl:max-w-7xl"))) (assert (contains? (get r "rule") "@media(min-width:1536px)")) (assert (contains? (get r "rule") "max-width:80rem"))))) (defsuite "tw-token-combined" (deftest "sm:hover:bg-sky-200 → media + pseudo" (let ((r (tw-process-token "sm:hover:bg-sky-200"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "background-color:hsl(199,89%,87%)")))) (deftest "lg:focus:border-blue-500" (let ((r (tw-process-token "lg:focus:border-blue-500"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") ":focus")) (assert (contains? (get r "rule") "border-color:hsl(217,91%,53%)"))))) (defsuite "tw-media-sm" (deftest "sm:flex" (let ((r (tw-process-token "sm:flex"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "display:flex")))) (deftest "sm:hidden" (let ((r (tw-process-token "sm:hidden"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "display:none")))) (deftest "sm:block" (let ((r (tw-process-token "sm:block"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "display:block")))) (deftest "sm:flex-col" (let ((r (tw-process-token "sm:flex-col"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "flex-direction:column")))) (deftest "sm:flex-row" (let ((r (tw-process-token "sm:flex-row"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "flex-direction:row")))) (deftest "sm:grid-cols-2" (let ((r (tw-process-token "sm:grid-cols-2"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(2,minmax(0,1fr))")))) (deftest "sm:p-4" (let ((r (tw-process-token "sm:p-4"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "padding:1rem")))) (deftest "sm:px-6" (let ((r (tw-process-token "sm:px-6"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "padding-left:1.5rem;padding-right:1.5rem")))) (deftest "sm:gap-4" (let ((r (tw-process-token "sm:gap-4"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "gap:1rem")))) (deftest "sm:text-lg" (let ((r (tw-process-token "sm:text-lg"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "font-size:1.125rem")))) (deftest "sm:font-bold" (let ((r (tw-process-token "sm:font-bold"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "font-weight:700")))) (deftest "sm:text-center" (let ((r (tw-process-token "sm:text-center"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "text-align:center")))) (deftest "sm:w-1/2" (let ((r (tw-process-token "sm:w-1/2"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "width:50%")))) (deftest "sm:max-w-xl" (let ((r (tw-process-token "sm:max-w-xl"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "max-width:36rem")))) (deftest "sm:items-center" (let ((r (tw-process-token "sm:items-center"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "align-items:center")))) (deftest "sm:justify-between" (let ((r (tw-process-token "sm:justify-between"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "justify-content:space-between")))) (deftest "sm:bg-sky-100" (let ((r (tw-process-token "sm:bg-sky-100"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "background-color:hsl(199,89%,93%)")))) (deftest "sm:rounded-lg" (let ((r (tw-process-token "sm:rounded-lg"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "border-radius:0.5rem")))) (deftest "sm:shadow-md" (let ((r (tw-process-token "sm:shadow-md"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "box-shadow:")))) (deftest "sm:relative" (let ((r (tw-process-token "sm:relative"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") "position:relative"))))) (defsuite "tw-media-md" (deftest "md:flex" (let ((r (tw-process-token "md:flex"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "display:flex")))) (deftest "md:flex-row" (let ((r (tw-process-token "md:flex-row"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "flex-direction:row")))) (deftest "md:grid-cols-2" (let ((r (tw-process-token "md:grid-cols-2"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(2,minmax(0,1fr))")))) (deftest "md:px-8" (let ((r (tw-process-token "md:px-8"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "padding-left:2rem;padding-right:2rem")))) (deftest "md:text-xl" (let ((r (tw-process-token "md:text-xl"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "font-size:1.25rem")))) (deftest "md:hidden" (let ((r (tw-process-token "md:hidden"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "display:none")))) (deftest "md:absolute" (let ((r (tw-process-token "md:absolute"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "position:absolute")))) (deftest "md:top-0" (let ((r (tw-process-token "md:top-0"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") "top:0px"))))) (defsuite "tw-media-lg" (deftest "lg:grid-cols-3" (let ((r (tw-process-token "lg:grid-cols-3"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(3,minmax(0,1fr))")))) (deftest "lg:max-w-4xl" (let ((r (tw-process-token "lg:max-w-4xl"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "max-width:56rem")))) (deftest "lg:px-12" (let ((r (tw-process-token "lg:px-12"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "padding-left:3rem;padding-right:3rem")))) (deftest "lg:text-2xl" (let ((r (tw-process-token "lg:text-2xl"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "font-size:1.5rem")))) (deftest "lg:col-span-2" (let ((r (tw-process-token "lg:col-span-2"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "grid-column:span 2 / span 2")))) (deftest "lg:sticky" (let ((r (tw-process-token "lg:sticky"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") "position:sticky"))))) (defsuite "tw-media-xl" (deftest "xl:grid-cols-4" (let ((r (tw-process-token "xl:grid-cols-4"))) (assert (contains? (get r "rule") "@media(min-width:1280px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(4,minmax(0,1fr))")))) (deftest "xl:max-w-7xl" (let ((r (tw-process-token "xl:max-w-7xl"))) (assert (contains? (get r "rule") "@media(min-width:1280px)")) (assert (contains? (get r "rule") "max-width:80rem")))) (deftest "xl:hidden" (let ((r (tw-process-token "xl:hidden"))) (assert (contains? (get r "rule") "@media(min-width:1280px)")) (assert (contains? (get r "rule") "display:none")))) (deftest "xl:gap-8" (let ((r (tw-process-token "xl:gap-8"))) (assert (contains? (get r "rule") "@media(min-width:1280px)")) (assert (contains? (get r "rule") "gap:2rem"))))) (defsuite "tw-media-2xl" (deftest "2xl:max-w-screen" (let ((r (tw-process-token "2xl:max-w-screen"))) (assert (contains? (get r "rule") "@media(min-width:1536px)")) (assert (contains? (get r "rule") "max-width:100vw")))) (deftest "2xl:block" (let ((r (tw-process-token "2xl:block"))) (assert (contains? (get r "rule") "@media(min-width:1536px)")) (assert (contains? (get r "rule") "display:block")))) (deftest "2xl:text-4xl" (let ((r (tw-process-token "2xl:text-4xl"))) (assert (contains? (get r "rule") "@media(min-width:1536px)")) (assert (contains? (get r "rule") "font-size:2.25rem"))))) (defsuite "tw-media-state-combined" (deftest "sm:hover:bg-sky-200" (let ((r (tw-process-token "sm:hover:bg-sky-200"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "background-color:hsl(199,89%,87%)")))) (deftest "md:hover:bg-stone-200" (let ((r (tw-process-token "md:hover:bg-stone-200"))) (assert (contains? (get r "rule") "@media(min-width:768px)")) (assert (contains? (get r "rule") ":hover")))) (deftest "lg:focus:border-blue-500" (let ((r (tw-process-token "lg:focus:border-blue-500"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") ":focus")) (assert (contains? (get r "rule") "border-color:hsl(217,91%,53%)")))) (deftest "sm:disabled:opacity-50" (let ((r (tw-process-token "sm:disabled:opacity-50"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") ":disabled")) (assert (contains? (get r "rule") "opacity:0.5")))) (deftest "lg:hover:scale-105" (let ((r (tw-process-token "lg:hover:scale-105"))) (assert (contains? (get r "rule") "@media(min-width:1024px)")) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "transform:scale(1.05)"))))) (defsuite "tw-media-integration" (deftest "responsive grid: mobile-first" (let ((tokens (list "grid" "grid-cols-1" "sm:grid-cols-2" "md:grid-cols-3" "lg:grid-cols-4" "gap-4"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive flex: column→row" (let ((tokens (list "flex" "flex-col" "sm:flex-row" "gap-4" "items-start" "sm:items-center"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive spacing" (let ((tokens (list "p-4" "sm:p-6" "md:p-8" "lg:p-12" "xl:p-16"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive typography" (let ((tokens (list "text-base" "sm:text-lg" "md:text-xl" "lg:text-2xl" "xl:text-3xl"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive visibility" (let ((tokens (list "hidden" "sm:block" "md:hidden" "lg:block"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive button with hover states" (let ((tokens (list "px-4" "py-2" "text-sm" "bg-sky-500" "text-white" "rounded-md" "hover:bg-sky-600" "sm:px-6" "sm:text-base" "md:px-8"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens))))) (defsuite "tw-token-negative" (begin (deftest "-mt-4 negates value" (let ((r (tw-process-token "-mt-4"))) (assert (contains? (get r "rule") "margin-top:-1rem")))) (deftest "-ml-2 negates value" (let ((r (tw-process-token "-ml-2"))) (assert (contains? (get r "rule") "margin-left:-0.5rem")))) (deftest "-mx-4 negates both sides" (let ((r (tw-process-token "-mx-4"))) (assert (contains? (get r "rule") "margin-left:-1rem")) (assert (contains? (get r "rule") "margin-right:-1rem")))) (deftest "positive mt-4 unaffected" (let ((r (tw-process-token "mt-4"))) (assert (contains? (get r "rule") "margin-top:1rem")))))) (defsuite "tw-important" (deftest "!p-4 → padding with !important" (let ((r (tw-process-token "!p-4"))) (assert (contains? (get r "rule") "padding:1rem !important")))) (deftest "!font-bold" (let ((r (tw-process-token "!font-bold"))) (assert (contains? (get r "rule") "font-weight:700 !important")))) (deftest "!hidden" (let ((r (tw-process-token "!hidden"))) (assert (contains? (get r "rule") "display:none !important")))) (deftest "!bg-sky-500" (let ((r (tw-process-token "!bg-sky-500"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%) !important")))) (deftest "! strips bang from class name" (assert= (get (tw-process-token "!p-4") "cls") "sx-p-4"))) (defsuite "tw-integration" (deftest "card: resolves all tokens" (let ((tokens (list "bg-white" "p-6" "rounded-xl" "shadow-md"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "nav: resolves all tokens" (let ((tokens (list "flex" "items-center" "justify-between" "px-4" "py-2" "bg-stone-100"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "button: resolves all tokens" (let ((tokens (list "inline-flex" "items-center" "px-4" "py-2" "text-sm" "font-medium" "rounded-md" "bg-sky-500" "text-white" "transition-colors" "hover:bg-sky-600" "focus:outline-none" "focus-visible:ring-2" "disabled:opacity-50" "cursor-pointer"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "grid layout: resolves all tokens" (let ((tokens (list "grid" "grid-cols-3" "gap-4" "lg:grid-cols-4" "sm:grid-cols-2"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "positioned overlay: resolves all tokens" (let ((tokens (list "fixed" "inset-0" "z-50" "bg-black" "opacity-50"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "form input: resolves all tokens" (let ((tokens (list "block" "w-full" "rounded-md" "border" "border-stone-300" "px-3" "py-2" "text-sm" "placeholder:text-stone-400" "focus:border-sky-500" "focus:ring-2"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "responsive layout: resolves all tokens" (let ((tokens (list "flex" "flex-col" "sm:flex-row" "gap-4" "items-start" "sm:items-center" "justify-between" "p-4" "md:p-8"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "typography: resolves all tokens" (let ((tokens (list "text-lg" "font-semibold" "leading-tight" "tracking-wide" "text-stone-900" "antialiased"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens))))) (defsuite "tw-dark" (deftest "dark:bg-stone-900" (let ((r (tw-process-token "dark:bg-stone-900"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "background-color:hsl(25,6%,21%)")))) (deftest "dark:text-white" (let ((r (tw-process-token "dark:text-white"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "color:#ffffff")))) (deftest "dark:text-stone-100" (let ((r (tw-process-token "dark:text-stone-100"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "color:hsl(25,6%,93%)")))) (deftest "dark:border-stone-700" (let ((r (tw-process-token "dark:border-stone-700"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "border-color:hsl(25,6%,38%)")))) (deftest "dark: class name" (assert= (get (tw-process-token "dark:bg-stone-900") "cls") "sx-dark-bg-stone-900")) (deftest "dark:hover: combined" (let ((r (tw-process-token "dark:hover:bg-stone-800"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "background-color:hsl(25,6%,30%)")))) (deftest "dark:hidden" (let ((r (tw-process-token "dark:hidden"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "display:none"))))) (defsuite "tw-group" (deftest "group-hover:text-sky-500" (let ((r (tw-process-token "group-hover:text-sky-500"))) (assert (contains? (get r "rule") ".group:hover ")) (assert (contains? (get r "rule") "color:hsl(199,89%,53%)")))) (deftest "group-focus:border-blue-500" (let ((r (tw-process-token "group-focus:border-blue-500"))) (assert (contains? (get r "rule") ".group:focus ")) (assert (contains? (get r "rule") "border-color:hsl(217,91%,53%)")))) (deftest "group-active:scale-95" (let ((r (tw-process-token "group-active:scale-95"))) (assert (contains? (get r "rule") ".group:active ")) (assert (contains? (get r "rule") "transform:scale(0.95)")))) (deftest "group-hover: class name" (assert= (get (tw-process-token "group-hover:text-sky-500") "cls") "sx-group-hover-text-sky-500")) (deftest "sm:group-hover: — breakpoint + group" (let ((r (tw-process-token "sm:group-hover:text-sky-500"))) (assert (contains? (get r "rule") "@media(min-width:640px)")) (assert (contains? (get r "rule") ".group:hover ")))) (deftest "group-hover:opacity-100" (let ((r (tw-process-token "group-hover:opacity-100"))) (assert (contains? (get r "rule") ".group:hover ")) (assert (contains? (get r "rule") "opacity:1"))))) (defsuite "tw-peer" (deftest "peer-focus:border-sky-500" (let ((r (tw-process-token "peer-focus:border-sky-500"))) (assert (contains? (get r "rule") ".peer:focus~")) (assert (contains? (get r "rule") "border-color:hsl(199,89%,53%)")))) (deftest "peer-hover:text-sky-600" (let ((r (tw-process-token "peer-hover:text-sky-600"))) (assert (contains? (get r "rule") ".peer:hover~")) (assert (contains? (get r "rule") "color:hsl(199,89%,45%)")))) (deftest "peer-checked:bg-sky-100" (let ((r (tw-process-token "peer-checked:bg-sky-100"))) (assert (contains? (get r "rule") ".peer:checked~")) (assert (contains? (get r "rule") "background-color:hsl(199,89%,93%)")))) (deftest "peer-disabled:opacity-50" (let ((r (tw-process-token "peer-disabled:opacity-50"))) (assert (contains? (get r "rule") ".peer:disabled~")) (assert (contains? (get r "rule") "opacity:0.5")))) (deftest "peer-invalid:border-red-500" (let ((r (tw-process-token "peer-invalid:border-red-500"))) (assert (contains? (get r "rule") ".peer:invalid~")) (assert (contains? (get r "rule") "border-color:hsl(0,72%,53%)")))) (deftest "peer-focus: class name" (assert= (get (tw-process-token "peer-focus:border-sky-500") "cls") "sx-peer-focus-border-sky-500"))) (defsuite "tw-container-query" (deftest "@md:flex → 448px" (let ((r (tw-process-token "@md:flex"))) (assert (contains? (get r "rule") "@container(min-width:448px)")) (assert (contains? (get r "rule") "display:flex")))) (deftest "@lg:grid-cols-3 → 512px" (let ((r (tw-process-token "@lg:grid-cols-3"))) (assert (contains? (get r "rule") "@container(min-width:512px)")) (assert (contains? (get r "rule") "grid-template-columns:repeat(3,minmax(0,1fr))")))) (deftest "@sm:hidden → 384px" (let ((r (tw-process-token "@sm:hidden"))) (assert (contains? (get r "rule") "@container(min-width:384px)")) (assert (contains? (get r "rule") "display:none")))) (deftest "@xl:text-lg → 576px" (let ((r (tw-process-token "@xl:text-lg"))) (assert (contains? (get r "rule") "@container(min-width:576px)")) (assert (contains? (get r "rule") "font-size:1.125rem")))) (deftest "@xs:p-2 → 320px" (let ((r (tw-process-token "@xs:p-2"))) (assert (contains? (get r "rule") "@container(min-width:320px)")) (assert (contains? (get r "rule") "padding:0.5rem")))) (deftest "@container class name" (assert= (get (tw-process-token "@md:flex") "cls") "sx-@md-flex"))) (defsuite "tw-colour-opacity" (deftest "bg-sky-500/50 → alpha 0.5" (let ((r (tw-process-token "bg-sky-500/50"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%,0.5)")))) (deftest "bg-sky-500/75 → alpha 0.75" (let ((r (tw-process-token "bg-sky-500/75"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%,0.75)")))) (deftest "bg-sky-500/25 → alpha 0.25" (let ((r (tw-process-token "bg-sky-500/25"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%,0.25)")))) (deftest "text-red-600/75" (let ((r (tw-process-token "text-red-600/75"))) (assert (contains? (get r "rule") "color:hsl(0,72%,45%,0.75)")))) (deftest "border-blue-500/50" (let ((r (tw-process-token "border-blue-500/50"))) (assert (contains? (get r "rule") "border-color:hsl(217,91%,53%,0.5)")))) (deftest "without /alpha unchanged" (let ((r (tw-process-token "bg-sky-500"))) (assert (contains? (get r "rule") "background-color:hsl(199,89%,53%)")))) (deftest "hover: with opacity" (let ((r (tw-process-token "hover:bg-sky-500/50"))) (assert (contains? (get r "rule") ":hover")) (assert (contains? (get r "rule") "hsl(199,89%,53%,0.5)")))) (deftest "dark: with opacity" (let ((r (tw-process-token "dark:bg-stone-900/80"))) (assert (contains? (get r "rule") ".dark ")) (assert (contains? (get r "rule") "hsl(25,6%,21%,0.8)"))))) (defsuite "tw-ring-colour" (deftest "ring-sky-500" (let ((r (tw-process-token "ring-sky-500"))) (assert (contains? (get r "rule") "--tw-ring-color:hsl(199,89%,53%)")))) (deftest "ring-blue-600" (let ((r (tw-process-token "ring-blue-600"))) (assert (contains? (get r "rule") "--tw-ring-color:hsl(217,91%,45%)")))) (deftest "ring-red-500" (let ((r (tw-process-token "ring-red-500"))) (assert (contains? (get r "rule") "--tw-ring-color:hsl(0,72%,53%)")))) (deftest "ring-2 still works (width)" (let ((r (tw-process-token "ring-2"))) (assert (contains? (get r "rule") "box-shadow:0 0 0 2px")))) (deftest "ring default width" (let ((r (tw-process-token "ring"))) (assert (contains? (get r "rule") "box-shadow:0 0 0 3px")))) (deftest "focus:ring-sky-500" (let ((r (tw-process-token "focus:ring-sky-500"))) (assert (contains? (get r "rule") ":focus")) (assert (contains? (get r "rule") "--tw-ring-color:hsl(199,89%,53%)"))))) (defsuite "tw-new-features-integration" (deftest "dark mode card" (let ((tokens (list "bg-white" "dark:bg-stone-900" "text-stone-900" "dark:text-stone-100" "border" "dark:border-stone-700" "rounded-xl" "shadow-md" "p-6"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "form with peer validation" (let ((tokens (list "border" "rounded-md" "px-3" "py-2" "text-sm" "peer-focus:border-sky-500" "peer-focus:ring-2" "peer-invalid:border-red-500" "peer-disabled:opacity-50"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "card with group hover" (let ((tokens (list "bg-white" "rounded-xl" "p-4" "transition-all" "group-hover:shadow-lg" "group-hover:scale-105"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "important overrides" (let ((tokens (list "!p-0" "!m-0" "!hidden" "!text-center"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "container responsive" (let ((tokens (list "flex" "flex-col" "@sm:flex-row" "@md:grid" "@md:grid-cols-2"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "dark responsive button" (let ((tokens (list "px-4" "py-2" "bg-sky-500" "text-white" "rounded-md" "hover:bg-sky-600" "dark:bg-sky-600" "dark:hover:bg-sky-700" "focus:ring-2" "focus:ring-sky-500" "sm:px-6"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))) (deftest "opacity modifiers" (let ((tokens (list "bg-sky-500/90" "hover:bg-sky-600/90" "text-stone-900/80" "border-stone-300/50" "dark:bg-stone-900/95"))) (assert (every? (fn (t) (not (nil? (tw-process-token t)))) tokens)))))