(.using [library [lux (.except and) [control ["[0]" maybe]] [data ["[0]" text ["%" format (.only format)] ["[0]" encoding (.only Encoding)]] [collection ["[0]" list ("[1]#[0]" functor)]]] [math [number ["[0]" nat]]] [type [primitive (.except Frame pattern)]] [world [net (.only URL)]]]] ["[0]" / "_" ["[1][0]" selector (.only Selector Combinator Specializer Generic)] ["[1][0]" value (.only Value Animation Percentage)] ["[1][0]" property (.only Property)] ["[1][0]" font (.only Font)] ["[1][0]" style] ["[1][0]" query (.only Query)]]) (primitive: .public Common Any) (primitive: .public Special Any) (primitive: .public (CSS brand) Text (def: .public css (-> (CSS Any) Text) (|>> representation)) (def: .public empty (CSS Any) (abstraction "")) (type: .public Style (List (Ex (_ brand) [(Property brand) (Value brand)]))) (def: .public (rule selector style) (-> (Selector Any) Style (CSS Common)) (abstraction (format (/selector.selector selector) "{" (/style.inline (/style.style style)) "}"))) (def: .public char_set (-> Encoding (CSS Special)) (|>> encoding.name %.text (text.enclosed ["@charset " ";"]) abstraction)) (def: .public (font font) (-> Font (CSS Special)) (let [with_unicode (case (the /font.#unicode_range font) {.#Some unicode_range} (let [unicode_range' (format "U+" (# nat.hex encoded (the /font.#start unicode_range)) "-" (# nat.hex encoded (the /font.#end unicode_range)))] (list ["unicode-range" unicode_range'])) {.#None} (list))] (|> (partial_list ["font-family" (the /font.#family font)] ["src" (format "url(" (the /font.#source font) ")")] ["font-stretch" (|> font (the /font.#stretch) (maybe.else /value.normal_stretch) /value.value)] ["font-style" (|> font (the /font.#style) (maybe.else /value.normal_style) /value.value)] ["font-weight" (|> font (the /font.#weight) (maybe.else /value.normal_weight) /value.value)] with_unicode) (list#each (function (_ [property value]) (format property ": " value ";"))) text.together (text.enclosed ["{" "}"]) (format "@font-face") abstraction))) (def: .public (import url query) (-> URL (Maybe Query) (CSS Special)) (abstraction (format (format "@import url(" (%.text url) ")") (case query {.#Some query} (format " " (/query.query query)) {.#None} "") ";"))) (def: separator text.new_line) (type: .public Frame (Record [#when (Value Percentage) #what Style])) (def: .public (key_frames animation frames) (-> (Value Animation) (List Frame) (CSS Special)) (abstraction (format "@keyframes " (/value.value animation) " {" (|> frames (list#each (function (_ frame) (format (/value.value (the #when frame)) " {" (/style.inline (/style.style (the #what frame))) "}"))) (text.interposed ..separator)) "}"))) (template: (!composite
) [(abstraction (format (representation ) ..separator (representation)))]) (def: .public (and pre post) (All (_ kind) (-> (CSS kind) (CSS kind) (CSS kind))) (!composite pre post)) (def: .public (in_context combinator selector css) (-> Combinator (Selector Any) (CSS Common) (CSS Common)) (|> css representation (text.all_split_by ..separator) (list#each (let [prefix (|> selector (combinator (/selector.tag "")) /selector.selector)] (|>> (format prefix)))) (text.interposed ..separator) abstraction)) (def: .public (dependent combinator selector style inner) (-> Combinator (Selector Any) Style (CSS Common) (CSS Common)) (!composite (..rule selector style) (..in_context combinator selector inner))) (template [ ] [(def: .public (-> (Selector Any) Style (CSS Common) (CSS Common)) (..dependent ))] [with_descendants /selector.in] [with_children /selector.sub] ) (def: .public (in_case specializer selector css) (All (_ kind) (-> (Specializer kind) (Selector (Generic Any)) (CSS Common) (CSS Common))) (|> css representation (text.all_split_by ..separator) (list#each (let [prefix (|> selector (specializer (as_expected (/selector.tag ""))) /selector.selector)] (|>> (format prefix)))) (text.interposed ..separator) abstraction)) (def: .public (specialized combinator selector style inner) (All (_ kind) (-> (Specializer kind) (Selector (Generic Any)) Style (CSS Common) (CSS Common))) (!composite (..rule selector style) (..in_case combinator selector inner))) (template [ ] [(def: .public (-> (Selector (Generic Any)) Style (CSS Common) (CSS Common)) (..specialized ))] [with_case /selector.and] [with_part /selector.at] [with_element /selector.for] ) )