git.iko.soy/typeable/elm-ui
on master help sign in
virtualCSS benchmarking
commit103299f7cec4ac0cf373d7f5cf4308d1a7404838 authorMatthew Griffith <mdg.griffith@gmail.com> dateSun 7 Jul 2019, 10:28 (7 years ago) parentae18607
3 files changed+630−481
benchmarks/runtime/index.js+9 benchmarks/src/ManyElements.elm+107−11 src/Internal/Model.elm+514−470
benchmarks/runtime/index.js+9
@@ -85,6 +85,15 @@ async function write_results(allResults) {
8585 , { module: "ManyElements", group: "elmUI", count: 512, value: "elmUI512" }
8686 , { module: "ManyElements", group: "elmUI", count: 64, value: "elmUI64" }
8787 , { module: "ManyElements", group: "elmUI", count: 8192, value: "elmUI8192" }
88+ , { module: "ManyElements", group: "elmUIVCSS", count: 1024, value: "elmUIVCSS1024" }
89+ , { module: "ManyElements", group: "elmUIVCSS", count: 128, value: "elmUIVCSS128" }
90+ , { module: "ManyElements", group: "elmUIVCSS", count: 2048, value: "elmUIVCSS2048" }
91+ , { module: "ManyElements", group: "elmUIVCSS", count: 24, value: "elmUIVCSS24" }
92+ , { module: "ManyElements", group: "elmUIVCSS", count: 256, value: "elmUIVCSS256" }
93+ , { module: "ManyElements", group: "elmUIVCSS", count: 4096, value: "elmUIVCSS4096" }
94+ , { module: "ManyElements", group: "elmUIVCSS", count: 512, value: "elmUIVCSS512" }
95+ , { module: "ManyElements", group: "elmUIVCSS", count: 64, value: "elmUIVCSS64" }
96+ , { module: "ManyElements", group: "elmUIVCSS", count: 8192, value: "elmUIVCSS8192" }
8897 , { module: "ManyElements", group: "viewHtml", count: 1024, value: "viewHtml1024" }
8998 , { module: "ManyElements", group: "viewHtml", count: 128, value: "viewHtml128" }
9099 , { module: "ManyElements", group: "viewHtml", count: 2048, value: "viewHtml2048" }
benchmarks/src/ManyElements.elm+107−11
@@ -8,6 +8,15 @@ module ManyElements exposing
88 , elmUI512
99 , elmUI64
1010 , elmUI8192
11+ , elmUIVCSS1024
12+ , elmUIVCSS128
13+ , elmUIVCSS2048
14+ , elmUIVCSS24
15+ , elmUIVCSS256
16+ , elmUIVCSS4096
17+ , elmUIVCSS512
18+ , elmUIVCSS64
19+ , elmUIVCSS8192
1120 , viewHtml1024
1221 , viewHtml128
1322 , viewHtml2048
@@ -37,6 +46,7 @@ import Element.Font as Font
3746import Element.Keyed
3847import Html
3948import Html.Attributes
49+import Internal.Model as Internal
4050
4151
4252
@@ -89,6 +99,55 @@ elmUI8192 =
8999
90100
91101
102+{- Elm UI VirtualCSS -}
103+
104+
105+elmUIVCSS24 : Benchmark.Render.Benchmark Model Msg
106+elmUIVCSS24 =
107+ elmUIVCSS "elmUIVCSS24" 24
108+
109+
110+elmUIVCSS64 : Benchmark.Render.Benchmark Model Msg
111+elmUIVCSS64 =
112+ elmUIVCSS "elmUIVCSS64" 64
113+
114+
115+elmUIVCSS128 : Benchmark.Render.Benchmark Model Msg
116+elmUIVCSS128 =
117+ elmUIVCSS "elmUIVCSS128" 128
118+
119+
120+elmUIVCSS256 : Benchmark.Render.Benchmark Model Msg
121+elmUIVCSS256 =
122+ elmUIVCSS "elmUIVCSS256" 256
123+
124+
125+elmUIVCSS512 : Benchmark.Render.Benchmark Model Msg
126+elmUIVCSS512 =
127+ elmUIVCSS "elmUIVCSS512" 512
128+
129+
130+elmUIVCSS1024 : Benchmark.Render.Benchmark Model Msg
131+elmUIVCSS1024 =
132+ elmUIVCSS "elmUIVCSS1024" 1024
133+
134+
135+elmUIVCSS2048 : Benchmark.Render.Benchmark Model Msg
136+elmUIVCSS2048 =
137+ elmUIVCSS "elmUIVCSS2048" 2048
138+
139+
140+elmUIVCSS4096 : Benchmark.Render.Benchmark Model Msg
141+elmUIVCSS4096 =
142+ elmUIVCSS "elmUIVCSS4096" 4096
143+
144+
145+elmUIVCSS8192 : Benchmark.Render.Benchmark Model Msg
146+elmUIVCSS8192 =
147+ elmUIVCSS "elmUIVCSS8192" 8192
148+
149+
150+
92151{- Normal Html -}
93152
94153
@@ -203,8 +262,8 @@ type Msg
203262
204263
205264{-| -}
206−elmUI : String -> Int -> Benchmark.Render.Benchmark Model Msg
207−elmUI name count =
265+elmUIVCSS : String -> Int -> Benchmark.Render.Benchmark Model Msg
266+elmUIVCSS name count =
208267 { name = name
209268 , init =
210269 { index = 0
@@ -212,7 +271,17 @@ elmUI name count =
212271 , elements = List.range 0 (count - 1)
213272 }
214273 , view =
215− view
274+ \model ->
275+ Element.layoutWith
276+ { options =
277+ [ Internal.RenderModeOption
278+ Internal.WithVirtualCss
279+ ]
280+ }
281+ []
282+ (Element.column [ spacing 8, centerX ]
283+ (List.map (viewEl model.index) model.elements)
284+ )
216285 , update =
217286 \msg model ->
218287 case msg of
@@ -234,16 +303,44 @@ elmUI name count =
234303 }
235304
236305
237−view model =
238− Element.layout []
239− (Element.Keyed.column [ spacing 8, centerX ]
240− (List.map (viewEl model.index) model.elements)
241− )
306+{-| -}
307+elmUI : String -> Int -> Benchmark.Render.Benchmark Model Msg
308+elmUI name count =
309+ { name = name
310+ , init =
311+ { index = 0
312+ , numberOfElements = count
313+ , elements = List.range 0 (count - 1)
314+ }
315+ , view =
316+ \model ->
317+ Element.layout []
318+ (Element.column [ spacing 8, centerX ]
319+ (List.map (viewEl model.index) model.elements)
320+ )
321+ , update =
322+ \msg model ->
323+ case msg of
324+ Refresh ->
325+ if model.index > model.numberOfElements then
326+ { model | index = 0 }
327+
328+ else
329+ { model | index = model.index + 1 }
330+
331+ Tick i ->
332+ if model.index > model.numberOfElements then
333+ { model | index = 0 }
334+
335+ else
336+ { model | index = model.index + 1 }
337+ , tick = Tick
338+ , refresh = Refresh
339+ }
242340
243341
244342viewEl selectedIndex index =
245− ( String.fromInt index
246− , el
343+ el
247344 [ Background.color
248345 (if selectedIndex == index then
249346 pink
@@ -268,7 +365,6 @@ viewEl selectedIndex index =
268365 else
269366 text "Hello!"
270367 )
271− )
272368
273369
274370white =
src/Internal/Model.elm+514−470
@@ -83,9 +83,7 @@ module Internal.Model exposing
8383 , reduceRecursive
8484 , reduceStyles
8585 , reduceStylesRecursive
86− , removeNever
87− -- , renderFont
88−
86+ , removeNever
8987 , renderFontClassName
9088 , renderHeight
9189 , renderRoot
@@ -95,7 +93,6 @@ module Internal.Model exposing
9593 , rowClass
9694 , singleClass
9795 , spacingName
98− , staticRoot
9996 , tag
10097 , textShadowClass
10198 , toHtml
@@ -113,7 +110,7 @@ import Html.Attributes
113110import Html.Keyed
114111import Internal.Flag as Flag exposing (Flag)
115112import Internal.Style exposing (classes, dot)
116−import Json.Encode as Json
113+import Json.Encode as Encode
117114import Set exposing (Set)
118115import VirtualDom
119116
@@ -534,7 +531,7 @@ finalizeNode has node attributes children embedMode parentContext =
534531
535532embedWith static opts styles children =
536533 if static then
537− staticRoot
534+ staticRoot opts
538535 :: (styles
539536 |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
540537 |> Tuple.second
@@ -557,7 +554,7 @@ embedWith static opts styles children =
557554
558555embedKeyed static opts styles children =
559556 if static then
560− ( "static-stylesheet", staticRoot )
557+ ( "static-stylesheet", staticRoot opts )
561558 :: ( "dynamic-stylesheet"
562559 , styles
563560 |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
@@ -1822,8 +1819,17 @@ defaultOptions =
18221819 }
18231820
18241821
1825−staticRoot =
1826− VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ]
1822+staticRoot : OptionRecord -> VirtualDom.Node msg
1823+staticRoot opts =
1824+ case opts.mode of
1825+ Layout ->
1826+ VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ]
1827+
1828+ NoStaticStyleSheet ->
1829+ VirtualDom.text ""
1830+
1831+ WithVirtualCss ->
1832+ VirtualDom.node "elm-ui-static-rules" [ VirtualDom.property "rules" (Encode.string Internal.Style.rules) ] []
18271833
18281834
18291835addWhen ifThis x to =
@@ -2072,10 +2078,6 @@ type Children x
20722078 | Keyed (List ( String, x ))
20732079
20742080
2075−
2076−-- toHtml : OptionRecord -> Element msg -> VirtualDom.Node msg
2077−
2078−
20792081toHtml mode el =
20802082 case el of
20812083 Unstyled html ->
@@ -2111,8 +2113,7 @@ renderRoot optionList attributes child =
21112113
21122114
21132115type RenderMode
2114− = Viewport
2115− | Layout
2116+ = Layout
21162117 | NoStaticStyleSheet
21172118 | WithVirtualCss
21182119
@@ -2337,7 +2338,20 @@ optionsToRecord options =
23372338
23382339toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
23392340toStyleSheet options styleSheet =
2340− VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2341+ case options.mode of
2342+ Layout ->
2343+ VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2344+
2345+ NoStaticStyleSheet ->
2346+ VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2347+
2348+ WithVirtualCss ->
2349+ VirtualDom.node "elm-ui-rules"
2350+ [ VirtualDom.property "rulesPayload"
2351+ (encodeStyles options styleSheet)
2352+ , VirtualDom.attribute "rules" "hello"
2353+ ]
2354+ []
23412355
23422356
23432357renderTopLevelValues rules =
@@ -2553,508 +2567,538 @@ renderProps force (Property key val) existing =
25532567 existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
25542568
25552569
2570+encodeStyles options stylesheet =
2571+ let
2572+ combine style rendered =
2573+ let
2574+ renderedStyle =
2575+ renderStyleRule options style Nothing
2576+ in
2577+ { rules = renderedStyle ++ rendered.rules
2578+ , topLevel =
2579+ case topLevelValue style of
2580+ Nothing ->
2581+ rendered.topLevel
2582+
2583+ Just topLevel ->
2584+ topLevel :: rendered.topLevel
2585+ }
2586+ in
2587+ case List.foldl combine { topLevel = [], rules = [] } stylesheet of
2588+ { topLevel, rules } ->
2589+ -- TODO: top level values are still required
2590+ rules
2591+ |> List.map (\r -> ( r, Encode.string r ))
2592+ |> Encode.object
2593+
2594+
25562595toStyleSheetString : OptionRecord -> List Style -> String
25572596toStyleSheetString options stylesheet =
25582597 let
2559− renderStyle maybePseudo selector props =
2560− case maybePseudo of
2561− Nothing ->
2562− selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}"
2563−
2564− Just pseudo ->
2565− case pseudo of
2566− Hover ->
2567− case options.hover of
2568− NoHover ->
2569− ""
2598+ combine style rendered =
2599+ { rules = rendered.rules ++ renderStyleRule options style Nothing
2600+ , topLevel =
2601+ case topLevelValue style of
2602+ Nothing ->
2603+ rendered.topLevel
25702604
2571− ForceHover ->
2572− selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}"
2605+ Just topLevel ->
2606+ topLevel :: rendered.topLevel
2607+ }
2608+ in
2609+ case List.foldl combine { topLevel = [], rules = [] } stylesheet of
2610+ { topLevel, rules } ->
2611+ renderTopLevelValues topLevel ++ String.concat rules
25732612
2574− AllowHover ->
2575− selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}"
25762613
2577− Focus ->
2578− let
2579− renderedProps =
2580− List.foldl (renderProps False) "" props
2581− in
2582− String.join "\n"
2583− [ selector
2584− ++ "-fs:focus {"
2585− ++ renderedProps
2586− ++ "\n}"
2587− , "."
2588− ++ classes.any
2589− ++ ":focus ~ "
2590− ++ selector
2591− ++ "-fs:not(.focus) {"
2592− ++ renderedProps
2593− ++ "\n}"
2594− , "."
2595− ++ classes.any
2596− ++ ":focus "
2597− ++ selector
2598− ++ "-fs {"
2599− ++ renderedProps
2600− ++ "\n}"
2601− , ".focusable-parent:focus ~ "
2602− ++ "."
2603− ++ classes.any
2604− ++ " "
2605− ++ selector
2606− ++ "-fs {"
2607− ++ renderedProps
2608− ++ "\n}"
2609− ]
2614+renderStyle : OptionRecord -> Maybe PseudoClass -> String -> List Property -> List String
2615+renderStyle options maybePseudo selector props =
2616+ case maybePseudo of
2617+ Nothing ->
2618+ [ selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
26102619
2611− Active ->
2612− selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2620+ Just pseudo ->
2621+ case pseudo of
2622+ Hover ->
2623+ case options.hover of
2624+ NoHover ->
2625+ []
26132626
2614− renderStyleRule rule maybePseudo =
2615− case rule of
2616− Style selector props ->
2617− renderStyle maybePseudo selector props
2627+ ForceHover ->
2628+ [ selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}" ]
26182629
2619− Shadows name prop ->
2620− renderStyle
2621− maybePseudo
2622− ("." ++ name)
2623− [ Property "box-shadow" prop
2624− ]
2630+ AllowHover ->
2631+ [ selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
26252632
2626− Transparency name transparency ->
2633+ Focus ->
26272634 let
2628− opacity =
2629− (1 - transparency)
2630− |> min 1
2631− |> max 0
2635+ renderedProps =
2636+ List.foldl (renderProps False) "" props
26322637 in
2633− renderStyle
2634− maybePseudo
2635− ("." ++ name)
2636− [ Property "opacity" (String.fromFloat opacity)
2637− ]
2638+ [ selector
2639+ ++ "-fs:focus {"
2640+ ++ renderedProps
2641+ ++ "\n}"
2642+ , "."
2643+ ++ classes.any
2644+ ++ ":focus ~ "
2645+ ++ selector
2646+ ++ "-fs:not(.focus) {"
2647+ ++ renderedProps
2648+ ++ "\n}"
2649+ , "."
2650+ ++ classes.any
2651+ ++ ":focus "
2652+ ++ selector
2653+ ++ "-fs {"
2654+ ++ renderedProps
2655+ ++ "\n}"
2656+ , ".focusable-parent:focus ~ "
2657+ ++ "."
2658+ ++ classes.any
2659+ ++ " "
2660+ ++ selector
2661+ ++ "-fs {"
2662+ ++ renderedProps
2663+ ++ "\n}"
2664+ ]
26382665
2639− FontSize i ->
2640− renderStyle
2641− maybePseudo
2642− (".font-size-" ++ String.fromInt i)
2643− [ Property "font-size" (String.fromInt i ++ "px")
2644− ]
2666+ Active ->
2667+ [ selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
26452668
2646− FontFamily name typefaces ->
2647− let
2648− features =
2649− typefaces
2650− |> List.filterMap renderVariants
2651− |> String.join ", "
2652−
2653− families =
2654− [ Property "font-family"
2655− (typefaces
2656− |> List.map fontName
2657− |> String.join ", "
2658− )
2659− , Property "font-feature-settings" features
2660− , Property "font-variant"
2661− (if List.any hasSmallCaps typefaces then
2662− "small-caps"
26632669
2664− else
2665− "normal"
2666− )
2667− ]
2668− in
2669− String.join " "
2670− [ renderStyle
2671− maybePseudo
2672− ("." ++ name)
2673− families
2674− ]
2670+renderStyleRule : OptionRecord -> Style -> Maybe PseudoClass -> List String
2671+renderStyleRule options rule maybePseudo =
2672+ case rule of
2673+ Style selector props ->
2674+ renderStyle options maybePseudo selector props
2675+
2676+ Shadows name prop ->
2677+ renderStyle options
2678+ maybePseudo
2679+ ("." ++ name)
2680+ [ Property "box-shadow" prop
2681+ ]
2682+
2683+ Transparency name transparency ->
2684+ let
2685+ opacity =
2686+ (1 - transparency)
2687+ |> min 1
2688+ |> max 0
2689+ in
2690+ renderStyle options
2691+ maybePseudo
2692+ ("." ++ name)
2693+ [ Property "opacity" (String.fromFloat opacity)
2694+ ]
2695+
2696+ FontSize i ->
2697+ renderStyle options
2698+ maybePseudo
2699+ (".font-size-" ++ String.fromInt i)
2700+ [ Property "font-size" (String.fromInt i ++ "px")
2701+ ]
2702+
2703+ FontFamily name typefaces ->
2704+ let
2705+ features =
2706+ typefaces
2707+ |> List.filterMap renderVariants
2708+ |> String.join ", "
2709+
2710+ families =
2711+ [ Property "font-family"
2712+ (typefaces
2713+ |> List.map fontName
2714+ |> String.join ", "
2715+ )
2716+ , Property "font-feature-settings" features
2717+ , Property "font-variant"
2718+ (if List.any hasSmallCaps typefaces then
2719+ "small-caps"
26752720
2676− Single class prop val ->
2677− renderStyle
2721+ else
2722+ "normal"
2723+ )
2724+ ]
2725+ in
2726+ renderStyle options
2727+ maybePseudo
2728+ ("." ++ name)
2729+ families
2730+
2731+ Single class prop val ->
2732+ renderStyle options
2733+ maybePseudo
2734+ ("." ++ class)
2735+ [ Property prop val
2736+ ]
2737+
2738+ Colored class prop color ->
2739+ -- This is because the trick we're using to make a txtarea be height:content
2740+ -- stops the inheritance chain for font color.
2741+ -- So we need to pack our bags, hike up our socks and jump over the break.
2742+ if prop == "color" then
2743+ List.concat
2744+ [ renderStyle options
26782745 maybePseudo
26792746 ("." ++ class)
2680− [ Property prop val
2747+ [ Property prop (formatColor color)
26812748 ]
2749+ , renderStyle options
2750+ maybePseudo
2751+ ("." ++ class ++ " ." ++ classes.inputMultilineParent ++ " ." ++ classes.inputMultiline)
2752+ [ Property prop (formatColor color)
2753+ ]
2754+ ]
26822755
2683− Colored class prop color ->
2684− -- This is because the trick we're using to make a txtarea be height:content
2685− -- stops the inheritance chain for font color.
2686− -- So we need to pack our bags, hike up our socks and jump over the break.
2687− if prop == "color" then
2688− String.concat
2689− [ renderStyle
2690− maybePseudo
2691− ("." ++ class)
2692− [ Property prop (formatColor color)
2693− ]
2694− , renderStyle
2695− maybePseudo
2696− ("." ++ class ++ " ." ++ classes.inputMultilineParent ++ " ." ++ classes.inputMultiline)
2697− [ Property prop (formatColor color)
2698− ]
2699− ]
2756+ else
2757+ renderStyle options
2758+ maybePseudo
2759+ ("." ++ class)
2760+ [ Property prop (formatColor color)
2761+ ]
27002762
2701− else
2702− renderStyle
2703− maybePseudo
2704− ("." ++ class)
2705− [ Property prop (formatColor color)
2706− ]
2763+ SpacingStyle cls x y ->
2764+ let
2765+ class =
2766+ "." ++ cls
27072767
2708− SpacingStyle cls x y ->
2709− let
2710− class =
2711− "." ++ cls
2768+ halfX =
2769+ String.fromFloat (toFloat x / 2) ++ "px"
27122770
2713− halfX =
2714− String.fromFloat (toFloat x / 2) ++ "px"
2771+ halfY =
2772+ String.fromFloat (toFloat y / 2) ++ "px"
27152773
2716− halfY =
2717− String.fromFloat (toFloat y / 2) ++ "px"
2774+ xPx =
2775+ String.fromInt x ++ "px"
27182776
2719− xPx =
2720− String.fromInt x ++ "px"
2777+ yPx =
2778+ String.fromInt y ++ "px"
27212779
2722− yPx =
2723− String.fromInt y ++ "px"
2780+ row =
2781+ "." ++ Internal.Style.classes.row
27242782
2725− row =
2726− "." ++ Internal.Style.classes.row
2783+ wrappedRow =
2784+ "." ++ Internal.Style.classes.wrapped ++ row
27272785
2728− wrappedRow =
2729− "." ++ Internal.Style.classes.wrapped ++ row
2786+ column =
2787+ "." ++ Internal.Style.classes.column
27302788
2731− column =
2732− "." ++ Internal.Style.classes.column
2789+ page =
2790+ "." ++ Internal.Style.classes.page
27332791
2734− page =
2735− "." ++ Internal.Style.classes.page
2792+ paragraph =
2793+ "." ++ Internal.Style.classes.paragraph
27362794
2737− paragraph =
2738− "." ++ Internal.Style.classes.paragraph
2795+ left =
2796+ "." ++ Internal.Style.classes.alignLeft
27392797
2740− left =
2741− "." ++ Internal.Style.classes.alignLeft
2798+ right =
2799+ "." ++ Internal.Style.classes.alignRight
27422800
2743− right =
2744− "." ++ Internal.Style.classes.alignRight
2801+ any =
2802+ "." ++ Internal.Style.classes.any
27452803
2746− any =
2747− "." ++ Internal.Style.classes.any
2804+ single =
2805+ "." ++ Internal.Style.classes.single
2806+ in
2807+ List.concat
2808+ [ renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ " + " ++ any) [ Property "margin-left" xPx ]
2809+
2810+ -- margins don't apply to last element of normal, unwrapped rows
2811+ -- , renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ ":first-child") [ Property "margin" "0" ]
2812+ -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2813+ , renderStyle options
2814+ maybePseudo
2815+ (class ++ wrappedRow ++ " > " ++ any)
2816+ [ Property "margin" (halfY ++ " " ++ halfX)
2817+ ]
27482818
2749− single =
2750− "." ++ Internal.Style.classes.single
2751− in
2752− String.concat
2753− [ renderStyle maybePseudo (class ++ row ++ " > " ++ any ++ " + " ++ any) [ Property "margin-left" xPx ]
2754−
2755− -- margins don't apply to last element of normal, unwrapped rows
2756− -- , renderStyle maybePseudo (class ++ row ++ " > " ++ any ++ ":first-child") [ Property "margin" "0" ]
2757− -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2758− , renderStyle maybePseudo
2759− (class ++ wrappedRow ++ " > " ++ any)
2760− [ Property "margin" (halfY ++ " " ++ halfX)
2761− ]
2819+ -- , renderStyle options maybePseudo
2820+ -- (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2821+ -- [ Property "margin-right" "0"
2822+ -- ]
2823+ -- columns
2824+ , renderStyle options maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2825+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2826+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2827+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2828+ , renderStyle options
2829+ maybePseudo
2830+ (class ++ paragraph)
2831+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2832+ ]
2833+ , renderStyle options
2834+ maybePseudo
2835+ ("textarea" ++ any ++ class)
2836+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2837+ , Property "height" ("calc(100% + " ++ String.fromInt y ++ "px)")
2838+ ]
27622839
2763− -- , renderStyle maybePseudo
2764− -- (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2765− -- [ Property "margin-right" "0"
2766− -- ]
2767− -- columns
2768− , renderStyle maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2769− , renderStyle maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2770− , renderStyle maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2771− , renderStyle maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2772− , renderStyle
2773− maybePseudo
2774− (class ++ paragraph)
2775− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2776− ]
2777− , renderStyle
2778− maybePseudo
2779− ("textarea" ++ any ++ class)
2780− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2781− , Property "height" ("calc(100% + " ++ String.fromInt y ++ "px)")
2782− ]
2840+ -- , renderStyle options
2841+ -- maybePseudo
2842+ -- (class ++ paragraph ++ " > " ++ any)
2843+ -- [ Property "margin-right" xPx
2844+ -- , Property "margin-bottom" yPx
2845+ -- ]
2846+ , renderStyle options
2847+ maybePseudo
2848+ (class ++ paragraph ++ " > " ++ left)
2849+ [ Property "margin-right" xPx
2850+ ]
2851+ , renderStyle options
2852+ maybePseudo
2853+ (class ++ paragraph ++ " > " ++ right)
2854+ [ Property "margin-left" xPx
2855+ ]
2856+ , renderStyle options
2857+ maybePseudo
2858+ (class ++ paragraph ++ "::after")
2859+ [ Property "content" "''"
2860+ , Property "display" "block"
2861+ , Property "height" "0"
2862+ , Property "width" "0"
2863+ , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2864+ ]
2865+ , renderStyle options
2866+ maybePseudo
2867+ (class ++ paragraph ++ "::before")
2868+ [ Property "content" "''"
2869+ , Property "display" "block"
2870+ , Property "height" "0"
2871+ , Property "width" "0"
2872+ , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2873+ ]
2874+ ]
27832875
2784− -- , renderStyle
2785− -- maybePseudo
2786− -- (class ++ paragraph ++ " > " ++ any)
2787− -- [ Property "margin-right" xPx
2788− -- , Property "margin-bottom" yPx
2789− -- ]
2790− , renderStyle
2791− maybePseudo
2792− (class ++ paragraph ++ " > " ++ left)
2793− [ Property "margin-right" xPx
2794− ]
2795− , renderStyle
2796− maybePseudo
2797− (class ++ paragraph ++ " > " ++ right)
2798− [ Property "margin-left" xPx
2799− ]
2800− , renderStyle
2801− maybePseudo
2802− (class ++ paragraph ++ "::after")
2803− [ Property "content" "''"
2804− , Property "display" "block"
2805− , Property "height" "0"
2806− , Property "width" "0"
2807− , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2808− ]
2809− , renderStyle
2810− maybePseudo
2811− (class ++ paragraph ++ "::before")
2812− [ Property "content" "''"
2813− , Property "display" "block"
2814− , Property "height" "0"
2815− , Property "width" "0"
2816− , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2817− ]
2818− ]
2876+ PaddingStyle cls top right bottom left ->
2877+ let
2878+ class =
2879+ "."
2880+ ++ cls
2881+ in
2882+ renderStyle options
2883+ maybePseudo
2884+ class
2885+ [ Property "padding"
2886+ (String.fromInt top
2887+ ++ "px "
2888+ ++ String.fromInt right
2889+ ++ "px "
2890+ ++ String.fromInt bottom
2891+ ++ "px "
2892+ ++ String.fromInt left
2893+ ++ "px"
2894+ )
2895+ ]
28192896
2820− PaddingStyle cls top right bottom left ->
2821− let
2822− class =
2823− "."
2824− ++ cls
2825− in
2826− renderStyle
2827− maybePseudo
2828− class
2829− [ Property "padding"
2830− (String.fromInt top
2831− ++ "px "
2832− ++ String.fromInt right
2833− ++ "px "
2834− ++ String.fromInt bottom
2835− ++ "px "
2836− ++ String.fromInt left
2837− ++ "px"
2838− )
2839− ]
2897+ BorderWidth cls top right bottom left ->
2898+ let
2899+ class =
2900+ "."
2901+ ++ cls
2902+ in
2903+ renderStyle options
2904+ maybePseudo
2905+ class
2906+ [ Property "border-width"
2907+ (String.fromInt top
2908+ ++ "px "
2909+ ++ String.fromInt right
2910+ ++ "px "
2911+ ++ String.fromInt bottom
2912+ ++ "px "
2913+ ++ String.fromInt left
2914+ ++ "px"
2915+ )
2916+ ]
28402917
2841− BorderWidth cls top right bottom left ->
2842− let
2843− class =
2844− "."
2845− ++ cls
2846− in
2847− renderStyle
2848− maybePseudo
2849− class
2850− [ Property "border-width"
2851− (String.fromInt top
2852− ++ "px "
2853− ++ String.fromInt right
2854− ++ "px "
2855− ++ String.fromInt bottom
2856− ++ "px "
2857− ++ String.fromInt left
2858− ++ "px"
2859− )
2918+ GridTemplateStyle template ->
2919+ let
2920+ class =
2921+ ".grid-rows-"
2922+ ++ String.join "-" (List.map lengthClassName template.rows)
2923+ ++ "-cols-"
2924+ ++ String.join "-" (List.map lengthClassName template.columns)
2925+ ++ "-space-x-"
2926+ ++ lengthClassName (Tuple.first template.spacing)
2927+ ++ "-space-y-"
2928+ ++ lengthClassName (Tuple.second template.spacing)
2929+
2930+ ySpacing =
2931+ toGridLength (Tuple.second template.spacing)
2932+
2933+ xSpacing =
2934+ toGridLength (Tuple.first template.spacing)
2935+
2936+ toGridLength x =
2937+ toGridLengthHelper Nothing Nothing x
2938+
2939+ toGridLengthHelper minimum maximum x =
2940+ case x of
2941+ Px px ->
2942+ String.fromInt px ++ "px"
2943+
2944+ Content ->
2945+ case ( minimum, maximum ) of
2946+ ( Nothing, Nothing ) ->
2947+ "max-content"
2948+
2949+ ( Just minSize, Nothing ) ->
2950+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2951+
2952+ ( Nothing, Just maxSize ) ->
2953+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2954+
2955+ ( Just minSize, Just maxSize ) ->
2956+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2957+
2958+ Fill i ->
2959+ case ( minimum, maximum ) of
2960+ ( Nothing, Nothing ) ->
2961+ String.fromInt i ++ "fr"
2962+
2963+ ( Just minSize, Nothing ) ->
2964+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2965+
2966+ ( Nothing, Just maxSize ) ->
2967+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2968+
2969+ ( Just minSize, Just maxSize ) ->
2970+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2971+
2972+ Min m len ->
2973+ toGridLengthHelper (Just m) maximum len
2974+
2975+ Max m len ->
2976+ toGridLengthHelper minimum (Just m) len
2977+
2978+ msColumns =
2979+ template.columns
2980+ |> List.map toGridLength
2981+ |> String.join ySpacing
2982+ |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2983+
2984+ msRows =
2985+ template.columns
2986+ |> List.map toGridLength
2987+ |> String.join ySpacing
2988+ |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2989+
2990+ base =
2991+ class ++ "{" ++ msColumns ++ msRows ++ "}"
2992+
2993+ columns =
2994+ template.columns
2995+ |> List.map toGridLength
2996+ |> String.join " "
2997+ |> (\x -> "grid-template-columns: " ++ x ++ ";")
2998+
2999+ rows =
3000+ template.rows
3001+ |> List.map toGridLength
3002+ |> String.join " "
3003+ |> (\x -> "grid-template-rows: " ++ x ++ ";")
3004+
3005+ gapX =
3006+ "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
3007+
3008+ gapY =
3009+ "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
3010+
3011+ modernGrid =
3012+ class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
3013+
3014+ supports =
3015+ "@supports (display:grid) {" ++ modernGrid ++ "}"
3016+ in
3017+ [ base
3018+ , supports
3019+ ]
3020+
3021+ GridPosition position ->
3022+ let
3023+ class =
3024+ ".grid-pos-"
3025+ ++ String.fromInt position.row
3026+ ++ "-"
3027+ ++ String.fromInt position.col
3028+ ++ "-"
3029+ ++ String.fromInt position.width
3030+ ++ "-"
3031+ ++ String.fromInt position.height
3032+
3033+ msPosition =
3034+ String.join " "
3035+ [ "-ms-grid-row: "
3036+ ++ String.fromInt position.row
3037+ ++ ";"
3038+ , "-ms-grid-row-span: "
3039+ ++ String.fromInt position.height
3040+ ++ ";"
3041+ , "-ms-grid-column: "
3042+ ++ String.fromInt position.col
3043+ ++ ";"
3044+ , "-ms-grid-column-span: "
3045+ ++ String.fromInt position.width
3046+ ++ ";"
28603047 ]
28613048
2862− GridTemplateStyle template ->
2863− let
2864− class =
2865− ".grid-rows-"
2866− ++ String.join "-" (List.map lengthClassName template.rows)
2867− ++ "-cols-"
2868− ++ String.join "-" (List.map lengthClassName template.columns)
2869− ++ "-space-x-"
2870− ++ lengthClassName (Tuple.first template.spacing)
2871− ++ "-space-y-"
2872− ++ lengthClassName (Tuple.second template.spacing)
2873−
2874− ySpacing =
2875− toGridLength (Tuple.second template.spacing)
2876−
2877− xSpacing =
2878− toGridLength (Tuple.first template.spacing)
2879−
2880− toGridLength x =
2881− toGridLengthHelper Nothing Nothing x
2882−
2883− toGridLengthHelper minimum maximum x =
2884− case x of
2885− Px px ->
2886− String.fromInt px ++ "px"
2887−
2888− Content ->
2889− case ( minimum, maximum ) of
2890− ( Nothing, Nothing ) ->
2891− "max-content"
2892−
2893− ( Just minSize, Nothing ) ->
2894− "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2895−
2896− ( Nothing, Just maxSize ) ->
2897− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2898−
2899− ( Just minSize, Just maxSize ) ->
2900− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2901−
2902− Fill i ->
2903− case ( minimum, maximum ) of
2904− ( Nothing, Nothing ) ->
2905− String.fromInt i ++ "fr"
2906−
2907− ( Just minSize, Nothing ) ->
2908− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2909−
2910− ( Nothing, Just maxSize ) ->
2911− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2912−
2913− ( Just minSize, Just maxSize ) ->
2914− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2915−
2916− Min m len ->
2917− toGridLengthHelper (Just m) maximum len
2918−
2919− Max m len ->
2920− toGridLengthHelper minimum (Just m) len
2921−
2922− msColumns =
2923− template.columns
2924− |> List.map toGridLength
2925− |> String.join ySpacing
2926− |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2927−
2928− msRows =
2929− template.columns
2930− |> List.map toGridLength
2931− |> String.join ySpacing
2932− |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2933−
2934− base =
2935− class ++ "{" ++ msColumns ++ msRows ++ "}"
2936−
2937− columns =
2938− template.columns
2939− |> List.map toGridLength
2940− |> String.join " "
2941− |> (\x -> "grid-template-columns: " ++ x ++ ";")
2942−
2943− rows =
2944− template.rows
2945− |> List.map toGridLength
2946− |> String.join " "
2947− |> (\x -> "grid-template-rows: " ++ x ++ ";")
2948−
2949− gapX =
2950− "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
2951−
2952− gapY =
2953− "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
2954−
2955− modernGrid =
2956− class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
2957−
2958− supports =
2959− "@supports (display:grid) {" ++ modernGrid ++ "}"
2960− in
2961− base ++ supports
3049+ base =
3050+ class ++ "{" ++ msPosition ++ "}"
29623051
2963− GridPosition position ->
2964− let
2965− class =
2966− ".grid-pos-"
2967− ++ String.fromInt position.row
2968− ++ "-"
2969− ++ String.fromInt position.col
2970− ++ "-"
2971− ++ String.fromInt position.width
2972− ++ "-"
2973− ++ String.fromInt position.height
2974−
2975− msPosition =
2976− String.join " "
2977− [ "-ms-grid-row: "
2978− ++ String.fromInt position.row
2979− ++ ";"
2980− , "-ms-grid-row-span: "
2981− ++ String.fromInt position.height
2982− ++ ";"
2983− , "-ms-grid-column: "
2984− ++ String.fromInt position.col
2985− ++ ";"
2986− , "-ms-grid-column-span: "
2987− ++ String.fromInt position.width
2988− ++ ";"
2989− ]
2990−
2991− base =
2992− class ++ "{" ++ msPosition ++ "}"
2993−
2994− modernPosition =
2995− String.join " "
2996− [ "grid-row: "
2997− ++ String.fromInt position.row
2998− ++ " / "
2999− ++ String.fromInt (position.row + position.height)
3000− ++ ";"
3001− , "grid-column: "
3002− ++ String.fromInt position.col
3003− ++ " / "
3004− ++ String.fromInt (position.col + position.width)
3005− ++ ";"
3006− ]
3007−
3008− modernGrid =
3009− class ++ "{" ++ modernPosition ++ "}"
3010−
3011− supports =
3012− "@supports (display:grid) {" ++ modernGrid ++ "}"
3013− in
3014− base ++ supports
3052+ modernPosition =
3053+ String.join " "
3054+ [ "grid-row: "
3055+ ++ String.fromInt position.row
3056+ ++ " / "
3057+ ++ String.fromInt (position.row + position.height)
3058+ ++ ";"
3059+ , "grid-column: "
3060+ ++ String.fromInt position.col
3061+ ++ " / "
3062+ ++ String.fromInt (position.col + position.width)
3063+ ++ ";"
3064+ ]
30153065
3016− PseudoSelector class styles ->
3017− let
3018− renderPseudoRule style =
3019− renderStyleRule style (Just class)
3020− in
3021− List.map renderPseudoRule styles
3022− |> String.join " "
3066+ modernGrid =
3067+ class ++ "{" ++ modernPosition ++ "}"
30233068
3024− Transform transform ->
3025− let
3026− val =
3027− transformValue transform
3069+ supports =
3070+ "@supports (display:grid) {" ++ modernGrid ++ "}"
3071+ in
3072+ [ base
3073+ , supports
3074+ ]
30283075
3029− class =
3030− transformClass transform
3031− in
3032− case ( class, val ) of
3033− ( Just cls, Just v ) ->
3034− renderStyle
3035− maybePseudo
3036− ("." ++ cls)
3037− [ Property "transform"
3038− v
3039− ]
3076+ PseudoSelector class styles ->
3077+ let
3078+ renderPseudoRule style =
3079+ renderStyleRule options style (Just class)
3080+ in
3081+ List.concatMap renderPseudoRule styles
30403082
3041− _ ->
3042− ""
3083+ Transform transform ->
3084+ let
3085+ val =
3086+ transformValue transform
30433087
3044− combine style rendered =
3045− { rules = rendered.rules ++ renderStyleRule style Nothing
3046− , topLevel =
3047− case topLevelValue style of
3048− Nothing ->
3049− rendered.topLevel
3088+ class =
3089+ transformClass transform
3090+ in
3091+ case ( class, val ) of
3092+ ( Just cls, Just v ) ->
3093+ renderStyle options
3094+ maybePseudo
3095+ ("." ++ cls)
3096+ [ Property "transform"
3097+ v
3098+ ]
30503099
3051− Just topLevel ->
3052− topLevel :: rendered.topLevel
3053− }
3054− in
3055− case List.foldl combine { topLevel = [], rules = "" } stylesheet of
3056− { topLevel, rules } ->
3057− renderTopLevelValues topLevel ++ rules
3100+ _ ->
3101+ []
30583102
30593103
30603104lengthClassName : Length -> String