@@ -16,6 +16,7 @@ module Internal.Model exposing
1616 , LayoutContext(..)
1717 , Length(..)
1818 , Location(..)
19+ , NearbyChildren(..)
1920 , NodeName(..)
2021 , Option(..)
2122 , OptionRecord
@@ -29,6 +30,7 @@ module Internal.Model exposing
2930 , TransformComponent(..)
3031 , Transformation(..)
3132 , VAlign(..)
33+ , Variant(..)
3234 , XYZ
3335 , addNodeName
3436 , addWhen
@@ -40,7 +42,7 @@ module Internal.Model exposing
4042 , asParagraph
4143 , asRow
4244 , asTextColumn
43− , boxShadowName
45+ , boxShadowClass
4446 , columnClass
4547 , composeTransformation
4648 , contextClasses
@@ -77,40 +79,30 @@ module Internal.Model exposing
7779 , onlyStyles
7880 , optionsToRecord
7981 , paddingName
82+ , paddingNameFloat
8083 , pageClass
8184 , paragraphClass
8285 , reduceRecursive
83− , reduceRecursiveCalcName
8486 , reduceStyles
8587 , reduceStylesRecursive
8688 , removeNever
87− , renderFocusStyle
88− , renderFont
8989 , renderFontClassName
9090 , renderHeight
9191 , renderRoot
92+ , renderVariant
9293 , renderWidth
9394 , rootStyle
9495 , rowClass
9596 , singleClass
96− , skippable
97− , sortedReduce
9897 , spacingName
99− , staticRoot
10098 , tag
101− , textElement
102− , textElementFill
103− , textShadowName
99+ , textShadowClass
104100 , toHtml
105101 , toStyleSheet
106− , toStyleSheetString
107102 , transformClass
108− , transformValue
109− , unit
110103 , unstyled
111− , untransformed
112104 , unwrapDecorations
113− , unwrapDecsHelper
105+ , variantName
114106 )
115107
116108{-| -}
@@ -120,7 +112,7 @@ import Html.Attributes
120112import Html.Keyed
121113import Internal.Flag as Flag exposing (Flag)
122114import Internal.Style exposing (classes, dot)
123−import Json.Encode as Json
115+import Json.Encode as Encode
124116import Set exposing (Set)
125117import VirtualDom
126118
@@ -182,7 +174,7 @@ type Style
182174 | Colored String String Color
183175 | SpacingStyle String Int Int
184176 | BorderWidth String Int Int Int Int
185− | PaddingStyle String Int Int Int Int
177+ | PaddingStyle String Float Float Float Float
186178 | GridTemplateStyle
187179 { spacing : ( Length, Length )
188180 , columns : List Length
@@ -213,12 +205,86 @@ type PseudoClass
213205 | Active
214206
215207
208+{-| -}
209+type alias Adjustment =
210+ { capital : Float
211+ , lowercase : Float
212+ , baseline : Float
213+ , descender : Float
214+ }
215+
216+
216217type Font
217218 = Serif
218219 | SansSerif
219220 | Monospace
220221 | Typeface String
221222 | ImportFont String String
223+ | FontWith
224+ { name : String
225+ , adjustment : Maybe Adjustment
226+ , variants : List Variant
227+ }
228+
229+
230+type Variant
231+ = VariantActive String
232+ | VariantOff String
233+ | VariantIndexed String Int
234+
235+
236+renderVariant var =
237+ case var of
238+ VariantActive name ->
239+ "\"" ++ name ++ "\""
240+
241+ VariantOff name ->
242+ "\"" ++ name ++ "\" 0"
243+
244+ VariantIndexed name index ->
245+ "\"" ++ name ++ "\" " ++ String.fromInt index
246+
247+
248+variantName var =
249+ case var of
250+ VariantActive name ->
251+ name
252+
253+ VariantOff name ->
254+ name ++ "-0"
255+
256+ VariantIndexed name index ->
257+ name ++ "-" ++ String.fromInt index
258+
259+
260+renderVariants typeface =
261+ case typeface of
262+ FontWith font ->
263+ Just (String.join ", " (List.map renderVariant font.variants))
264+
265+ _ ->
266+ Nothing
267+
268+
269+isSmallCaps var =
270+ case var of
271+ VariantActive name ->
272+ name == "smcp"
273+
274+ VariantOff name ->
275+ False
276+
277+ VariantIndexed name index ->
278+ name == "smcp" && index == 1
279+
280+
281+hasSmallCaps typeface =
282+ case typeface of
283+ FontWith font ->
284+ List.any isSmallCaps font.variants
285+
286+ _ ->
287+ False
222288
223289
224290type Property
@@ -306,6 +372,13 @@ type NodeName
306372 | Embedded String String
307373
308374
375+type NearbyChildren msg
376+ = NoNearbyChildren
377+ | ChildrenBehind (List (Html.Html msg))
378+ | ChildrenInFront (List (Html.Html msg))
379+ | ChildrenBehindAndInFront (List (Html.Html msg)) (List (Html.Html msg))
380+
381+
309382div =
310383 Generic
311384
@@ -314,7 +387,7 @@ type alias Gathered msg =
314387 { node : NodeName
315388 , attributes : List (VirtualDom.Attribute msg)
316389 , styles : List Style
317− , children : List (VirtualDom.Node msg)
390+ , children : NearbyChildren msg
318391 , has : Flag.Field
319392 }
320393
@@ -382,7 +455,10 @@ finalizeNode has node attributes children embedMode parentContext =
382455 Embedded nodeName internal ->
383456 VirtualDom.node nodeName
384457 attributes
385− [ createNode internal [ Html.Attributes.class (classes.any ++ " " ++ classes.single) ]
458+ [ createNode internal
459+ [ Html.Attributes.class
460+ (classes.any ++ " " ++ classes.single)
461+ ]
386462 ]
387463 in
388464 case parentContext of
@@ -459,49 +535,45 @@ finalizeNode has node attributes children embedMode parentContext =
459535
460536
461537embedWith static opts styles children =
538+ let
539+ dynamicStyleSheet =
540+ styles
541+ |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
542+ |> Tuple.second
543+ -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
544+ -- |> sortedReduce
545+ |> toStyleSheet opts
546+ in
462547 if static then
463− staticRoot
464− :: (styles
465− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
466− |> Tuple.second
467− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
468− -- |> sortedReduce
469− |> toStyleSheet opts
470− )
548+ staticRoot opts
549+ :: dynamicStyleSheet
471550 :: children
472551
473552 else
474− (styles
475− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
476− |> Tuple.second
477− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
478− -- |> sortedReduce
479− |> toStyleSheet opts
480− )
553+ dynamicStyleSheet
481554 :: children
482555
483556
484557embedKeyed static opts styles children =
558+ let
559+ dynamicStyleSheet =
560+ styles
561+ |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
562+ |> Tuple.second
563+ -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
564+ -- |> sortedReduce
565+ |> toStyleSheet opts
566+ in
485567 if static then
486− ( "static-stylesheet", staticRoot )
568+ ( "static-stylesheet", staticRoot opts )
487569 :: ( "dynamic-stylesheet"
488− , styles
489− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
490− |> Tuple.second
491− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
492− -- |> sortedReduce
493− |> toStyleSheet opts
570+ , dynamicStyleSheet
494571 )
495572 :: children
496573
497574 else
498575 ( "dynamic-stylesheet"
499− , styles
500− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
501− |> Tuple.second
502− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
503− -- |> sortedReduce
504− |> toStyleSheet opts
576+ , dynamicStyleSheet
505577 )
506578 :: children
507579
@@ -817,7 +889,16 @@ skippable flag style =
817889 False
818890
819891
820−gatherAttrRecursive : String -> NodeName -> Flag.Field -> Transformation -> List Style -> List (VirtualDom.Attribute msg) -> List (VirtualDom.Node msg) -> List (Attribute aligned msg) -> Gathered msg
892+gatherAttrRecursive :
893+ String
894+ -> NodeName
895+ -> Flag.Field
896+ -> Transformation
897+ -> List Style
898+ -> List (VirtualDom.Attribute msg)
899+ -> NearbyChildren msg
900+ -> List (Attribute aligned msg)
901+ -> Gathered msg
821902gatherAttrRecursive classes node has transform styles attrs children elementAttrs =
822903 case elementAttrs of
823904 [] ->
@@ -951,7 +1032,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9511032 in
9521033 gatherAttrRecursive (classes ++ " " ++ newClass)
9531034 node
954− (Flag.merge addToFlags has)
1035+ (Flag.merge addToFlags (Flag.add Flag.width has))
9551036 transform
9561037 (newStyles ++ styles)
9571038 attrs
@@ -972,7 +1053,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9721053 name =
9731054 "height-px-" ++ val
9741055 in
975− gatherAttrRecursive (name ++ " " ++ classes)
1056+ gatherAttrRecursive (Internal.Style.classes.heightExact ++ " " ++ name ++ " " ++ classes)
9761057 node
9771058 (Flag.add Flag.height has)
9781059 transform
@@ -1029,7 +1110,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
10291110 in
10301111 gatherAttrRecursive (classes ++ " " ++ newClass)
10311112 node
1032− (Flag.merge addToFlags has)
1113+ (Flag.merge addToFlags (Flag.add Flag.height has))
10331114 transform
10341115 (newStyles ++ styles)
10351116 attrs
@@ -1061,20 +1142,15 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
10611142 gatherAttrRecursive classes (addNodeName "h6" node) has transform styles attrs children remaining
10621143
10631144 Paragraph ->
1064− let
1065− newNode =
1066− case node of
1067− Generic ->
1068− NodeName "p"
1069−
1070− NodeName name ->
1071− NodeName name
1072−
1073− Embedded x y ->
1074− Embedded x y
1075− in
1076− gatherAttrRecursive classes
1077− newNode
1145+ -- previously we rendered a <p> tag, though apparently this invalidates the html if it has <div>s inside.
1146+ -- Since we can't guaranteee that there are no divs, we need another strategy.
1147+ -- While it's not documented in many places, there apparently is a paragraph aria role
1148+ -- https://github.com/w3c/aria/blob/11f85f41a5b621fdbe85fc9bcdcd270e653a48ba/common/script/roleInfo.js
1149+ -- Though we'll need to wait till it gets released in an official wai-aria spec to use it.
1150+ -- If it's used at the moment, then Lighthouse complains (likely rightfully) that role paragraph is not recognized.
1151+ gatherAttrRecursive
1152+ classes
1153+ node
10781154 has
10791155 transform
10801156 styles
@@ -1109,75 +1185,16 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
11091185
11101186 Styled styled ->
11111187 styles ++ styled.styles
1112−
1113− nearbyElement =
1114− Html.div
1115− [ Html.Attributes.class <|
1116− case location of
1117− Above ->
1118− String.join " "
1119− [ Internal.Style.classes.nearby
1120− , Internal.Style.classes.single
1121− , Internal.Style.classes.above
1122− ]
1123−
1124− Below ->
1125− String.join " "
1126− [ Internal.Style.classes.nearby
1127− , Internal.Style.classes.single
1128− , Internal.Style.classes.below
1129− ]
1130−
1131− OnRight ->
1132− String.join " "
1133− [ Internal.Style.classes.nearby
1134− , Internal.Style.classes.single
1135− , Internal.Style.classes.onRight
1136− ]
1137−
1138− OnLeft ->
1139− String.join " "
1140− [ Internal.Style.classes.nearby
1141− , Internal.Style.classes.single
1142− , Internal.Style.classes.onLeft
1143− ]
1144−
1145− InFront ->
1146− String.join " "
1147− [ Internal.Style.classes.nearby
1148− , Internal.Style.classes.single
1149− , Internal.Style.classes.inFront
1150− ]
1151−
1152− Behind ->
1153− String.join " "
1154− [ Internal.Style.classes.nearby
1155− , Internal.Style.classes.single
1156− , Internal.Style.classes.behind
1157− ]
1158− ]
1159− [ case elem of
1160− Empty ->
1161− VirtualDom.text ""
1162−
1163− Text str ->
1164− textElement str
1165−
1166− Unstyled html ->
1167− html asEl
1168−
1169− Styled styled ->
1170− styled.html NoStyleSheet asEl
1171− ]
1172−
1173− newClasses =
1174− if location == Behind then
1175− Internal.Style.classes.hasBehind ++ " " ++ classes
1176−
1177− else
1178− classes
11791188 in
1180− gatherAttrRecursive newClasses node has transform newStyles attrs (nearbyElement :: children) remaining
1189+ gatherAttrRecursive
1190+ classes
1191+ node
1192+ has
1193+ transform
1194+ newStyles
1195+ attrs
1196+ (addNearbyElement location elem children)
1197+ remaining
11811198
11821199 AlignX x ->
11831200 if Flag.present Flag.xAlign has then
@@ -1233,6 +1250,106 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
12331250 remaining
12341251
12351252
1253+addNearbyElement location elem existing =
1254+ let
1255+ nearby =
1256+ nearbyElement location elem
1257+ in
1258+ case existing of
1259+ NoNearbyChildren ->
1260+ case location of
1261+ Behind ->
1262+ ChildrenBehind [ nearby ]
1263+
1264+ _ ->
1265+ ChildrenInFront [ nearby ]
1266+
1267+ ChildrenBehind existingBehind ->
1268+ case location of
1269+ Behind ->
1270+ ChildrenBehind (nearby :: existingBehind)
1271+
1272+ _ ->
1273+ ChildrenBehindAndInFront existingBehind [ nearby ]
1274+
1275+ ChildrenInFront existingInFront ->
1276+ case location of
1277+ Behind ->
1278+ ChildrenBehindAndInFront [ nearby ] existingInFront
1279+
1280+ _ ->
1281+ ChildrenInFront (nearby :: existingInFront)
1282+
1283+ ChildrenBehindAndInFront existingBehind existingInFront ->
1284+ case location of
1285+ Behind ->
1286+ ChildrenBehindAndInFront (nearby :: existingBehind) existingInFront
1287+
1288+ _ ->
1289+ ChildrenBehindAndInFront existingBehind (nearby :: existingInFront)
1290+
1291+
1292+nearbyElement location elem =
1293+ Html.div
1294+ [ Html.Attributes.class <|
1295+ case location of
1296+ Above ->
1297+ String.join " "
1298+ [ Internal.Style.classes.nearby
1299+ , Internal.Style.classes.single
1300+ , Internal.Style.classes.above
1301+ ]
1302+
1303+ Below ->
1304+ String.join " "
1305+ [ Internal.Style.classes.nearby
1306+ , Internal.Style.classes.single
1307+ , Internal.Style.classes.below
1308+ ]
1309+
1310+ OnRight ->
1311+ String.join " "
1312+ [ Internal.Style.classes.nearby
1313+ , Internal.Style.classes.single
1314+ , Internal.Style.classes.onRight
1315+ ]
1316+
1317+ OnLeft ->
1318+ String.join " "
1319+ [ Internal.Style.classes.nearby
1320+ , Internal.Style.classes.single
1321+ , Internal.Style.classes.onLeft
1322+ ]
1323+
1324+ InFront ->
1325+ String.join " "
1326+ [ Internal.Style.classes.nearby
1327+ , Internal.Style.classes.single
1328+ , Internal.Style.classes.inFront
1329+ ]
1330+
1331+ Behind ->
1332+ String.join " "
1333+ [ Internal.Style.classes.nearby
1334+ , Internal.Style.classes.single
1335+ , Internal.Style.classes.behind
1336+ ]
1337+ ]
1338+ [ case elem of
1339+ Empty ->
1340+ VirtualDom.text ""
1341+
1342+ Text str ->
1343+ textElement str
1344+
1345+ Unstyled html ->
1346+ html asEl
1347+
1348+ Styled styled ->
1349+ styled.html NoStyleSheet asEl
1350+ ]
1351+
1352+
12361353renderWidth w =
12371354 case w of
12381355 Px px ->
@@ -1319,7 +1436,7 @@ renderHeight h =
13191436 "height-px-" ++ val
13201437 in
13211438 ( Flag.none
1322− , name
1439+ , Internal.Style.classes.heightExact ++ " " ++ name
13231440 , [ Single name "height" (val ++ "px") ]
13241441 )
13251442
@@ -1342,7 +1459,7 @@ renderHeight h =
13421459 , [ Single
13431460 (Internal.Style.classes.any
13441461 ++ "."
1345− ++ Internal.Style.classes.row
1462+ ++ Internal.Style.classes.column
13461463 ++ " > "
13471464 ++ (Internal.Style.dot <| "height-fill-" ++ String.fromInt portion)
13481465 )
@@ -1361,7 +1478,9 @@ renderHeight h =
13611478 Single
13621479 cls
13631480 "min-height"
1364− (String.fromInt minSize ++ "px")
1481+ -- This needs to be !important because we're using `min-height: min-content`
1482+ -- to correct for safari's incorrect implementation of flexbox.
1483+ (String.fromInt minSize ++ "px !important")
13651484
13661485 ( newFlag, newAttrs, newStyle ) =
13671486 renderHeight len
@@ -1439,7 +1558,7 @@ element : LayoutContext -> NodeName -> List (Attribute aligned msg) -> Children
14391558element context node attributes children =
14401559 attributes
14411560 |> List.reverse
1442− |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] []
1561+ |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] NoNearbyChildren
14431562 |> createElement context children
14441563
14451564
@@ -1490,34 +1609,31 @@ createElement context children rendered =
14901609 -- Maybe we could unpack text elements in a paragraph as well,
14911610 -- however, embedded elements that are larger than the line height will overlap with exisitng text.
14921611 -- I don't think that's what we want.
1493− if
1494− context
1495− == asEl
1496− || context
1497− == asParagraph
1498− then
1499− ( VirtualDom.text
1500− (if context == asParagraph then
1501− str
1502−
1503− else
1504− str
1505− )
1506− :: htmls
1507− , existingStyles
1508− )
1509−
1510− else
1511− ( textElement
1512− (if context == asParagraph then
1513− str
1514−
1515− else
1516− str
1517− )
1518− :: htmls
1519− , existingStyles
1520− )
1612+ -- if
1613+ -- context
1614+ -- == asEl
1615+ -- || context
1616+ -- == asParagraph
1617+ -- then
1618+ -- ( VirtualDom.text
1619+ -- (if context == asParagraph then
1620+ -- str
1621+ -- else
1622+ -- str
1623+ -- )
1624+ -- :: htmls
1625+ -- , existingStyles
1626+ -- )
1627+ -- else
1628+ ( (if context == asEl then
1629+ textElementFill str
1630+
1631+ else
1632+ textElement str
1633+ )
1634+ :: htmls
1635+ , existingStyles
1636+ )
15211637
15221638 Empty ->
15231639 ( htmls, existingStyles )
@@ -1559,28 +1675,30 @@ createElement context children rendered =
15591675 -- TEXT OPTIMIZATION
15601676 -- You can have raw text if the element is an el, and has `width-content` and `height-content`
15611677 -- Same if it's a column or row with one child and width-content, height-content
1562− if
1563− context
1564− == asEl
1565− || context
1566− == asParagraph
1567− then
1568− ( ( key
1569− , VirtualDom.text
1570− str
1571− )
1572− :: htmls
1573− , existingStyles
1574− )
1678+ -- if
1679+ -- context
1680+ -- == asEl
1681+ -- || context
1682+ -- == asParagraph
1683+ -- then
1684+ -- ( ( key
1685+ -- , VirtualDom.text
1686+ -- str
1687+ -- )
1688+ -- :: htmls
1689+ -- , existingStyles
1690+ -- )
1691+ -- else
1692+ ( ( key
1693+ , if context == asEl then
1694+ textElementFill str
15751695
1576− else
1577− ( ( key
1578− , textElement
1579− str
1580− )
1581− :: htmls
1582− , existingStyles
1583− )
1696+ else
1697+ textElement str
1698+ )
1699+ :: htmls
1700+ , existingStyles
1701+ )
15841702
15851703 Empty ->
15861704 ( htmls, existingStyles )
@@ -1603,13 +1721,8 @@ createElement context children rendered =
16031721 (finalizeNode rendered.has
16041722 rendered.node
16051723 rendered.attributes
1606− (Keyed <|
1607− keyed
1608− ++ List.map
1609− (\x ->
1610− ( "nearby-elements-pls", x )
1611− )
1612− rendered.children
1724+ (Keyed
1725+ (addKeyedChildren "nearby-element-pls" keyed rendered.children)
16131726 )
16141727 NoStyleSheet
16151728 )
@@ -1623,13 +1736,7 @@ createElement context children rendered =
16231736 rendered.node
16241737 rendered.attributes
16251738 (Keyed
1626− (keyed
1627− ++ List.map
1628− (\x ->
1629− ( "nearby-elements-pls", x )
1630− )
1631− rendered.children
1632− )
1739+ (addKeyedChildren "nearby-element-pls" keyed rendered.children)
16331740 )
16341741 }
16351742
@@ -1651,7 +1758,7 @@ createElement context children rendered =
16511758 rendered.has
16521759 rendered.node
16531760 rendered.attributes
1654− (Unkeyed <| unkeyed ++ rendered.children)
1761+ (Unkeyed (addChildren unkeyed rendered.children))
16551762 NoStyleSheet
16561763 )
16571764
@@ -1663,10 +1770,42 @@ createElement context children rendered =
16631770 rendered.has
16641771 rendered.node
16651772 rendered.attributes
1666− (Unkeyed (unkeyed ++ rendered.children))
1773+ (Unkeyed (addChildren unkeyed rendered.children))
16671774 }
16681775
16691776
1777+addChildren existing nearbyChildren =
1778+ case nearbyChildren of
1779+ NoNearbyChildren ->
1780+ existing
1781+
1782+ ChildrenBehind behind ->
1783+ behind ++ existing
1784+
1785+ ChildrenInFront inFront ->
1786+ existing ++ inFront
1787+
1788+ ChildrenBehindAndInFront behind inFront ->
1789+ behind ++ existing ++ inFront
1790+
1791+
1792+addKeyedChildren key existing nearbyChildren =
1793+ case nearbyChildren of
1794+ NoNearbyChildren ->
1795+ existing
1796+
1797+ ChildrenBehind behind ->
1798+ List.map (\x -> ( key, x )) behind ++ existing
1799+
1800+ ChildrenInFront inFront ->
1801+ existing ++ List.map (\x -> ( key, x )) inFront
1802+
1803+ ChildrenBehindAndInFront behind inFront ->
1804+ List.map (\x -> ( key, x )) behind
1805+ ++ existing
1806+ ++ List.map (\x -> ( key, x )) inFront
1807+
1808+
16701809unit =
16711810 0
16721811
@@ -1678,8 +1817,20 @@ defaultOptions =
16781817 }
16791818
16801819
1681−staticRoot =
1682− VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ]
1820+staticRoot : OptionRecord -> VirtualDom.Node msg
1821+staticRoot opts =
1822+ case opts.mode of
1823+ Layout ->
1824+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
1825+ VirtualDom.node "div"
1826+ []
1827+ [ VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ] ]
1828+
1829+ NoStaticStyleSheet ->
1830+ VirtualDom.text ""
1831+
1832+ WithVirtualCss ->
1833+ VirtualDom.node "elm-ui-static-rules" [ VirtualDom.property "rules" (Encode.string Internal.Style.rules) ] []
16831834
16841835
16851836addWhen ifThis x to =
@@ -1797,7 +1948,7 @@ type Spacing
17971948
17981949
17991950type Padding
1800− = Padding String Int Int Int Int
1951+ = Padding String Float Float Float Float
18011952
18021953
18031954extractSpacingAndPadding : List (Attribute aligned msg) -> ( Maybe Padding, Maybe Spacing )
@@ -1893,35 +2044,44 @@ getHeight attrs =
18932044 Nothing
18942045
18952046
2047+textElementClasses : String
2048+textElementClasses =
2049+ classes.any
2050+ ++ " "
2051+ ++ classes.text
2052+ ++ " "
2053+ ++ classes.widthContent
2054+ ++ " "
2055+ ++ classes.heightContent
2056+
2057+
18962058textElement : String -> VirtualDom.Node msg
18972059textElement str =
18982060 Html.div
18992061 [ Html.Attributes.class
1900− (String.join " "
1901− [ classes.any
1902− , classes.text
1903− , classes.widthContent
1904− , classes.heightContent
1905− ]
1906− )
2062+ textElementClasses
19072063 ]
19082064 [ Html.text str ]
19092065
19102066
2067+textElementFillClasses : String
2068+textElementFillClasses =
2069+ classes.any
2070+ ++ " "
2071+ ++ classes.text
2072+ ++ " "
2073+ ++ classes.widthFill
2074+ ++ " "
2075+ ++ classes.heightFill
2076+
2077+
19112078textElementFill : String -> VirtualDom.Node msg
19122079textElementFill str =
1913− VirtualDom.node "div"
1914− [ VirtualDom.property "className"
1915− (Json.string <|
1916− String.join " "
1917− [ classes.any
1918− , classes.text
1919− , classes.widthFill
1920− , classes.heightFill
1921− ]
1922− )
2080+ Html.div
2081+ [ Html.Attributes.class
2082+ textElementFillClasses
19232083 ]
1924− [ VirtualDom.text str ]
2084+ [ Html.text str ]
19252085
19262086
19272087type Children x
@@ -1929,10 +2089,6 @@ type Children x
19292089 | Keyed (List ( String, x ))
19302090
19312091
1932−
1933−-- toHtml : OptionRecord -> Element msg -> VirtualDom.Node msg
1934−
1935−
19362092toHtml mode el =
19372093 case el of
19382094 Unstyled html ->
@@ -1968,8 +2124,7 @@ renderRoot optionList attributes child =
19682124
19692125
19702126type RenderMode
1971− = Viewport
1972− | Layout
2127+ = Layout
19732128 | NoStaticStyleSheet
19742129 | WithVirtualCss
19752130
@@ -2018,8 +2173,8 @@ rootStyle =
20182173 , SansSerif
20192174 ]
20202175 in
2021− [ StyleClass Flag.bgColor (Colored ("bg-color-" ++ formatColorClass (Rgba 1 1 1 0)) "background-color" (Rgba 1 1 1 0))
2022− , StyleClass Flag.fontColor (Colored ("font-color-" ++ formatColorClass (Rgba 0 0 0 1)) "color" (Rgba 0 0 0 1))
2176+ [ StyleClass Flag.bgColor (Colored ("bg-" ++ formatColorClass (Rgba 1 1 1 0)) "background-color" (Rgba 1 1 1 0))
2177+ , StyleClass Flag.fontColor (Colored ("fc-" ++ formatColorClass (Rgba 0 0 0 1)) "color" (Rgba 0 0 0 1))
20232178 , StyleClass Flag.fontSize (FontSize 20)
20242179 , StyleClass Flag.fontFamily <|
20252180 FontFamily (List.foldl renderFontClassName "font-" families)
@@ -2051,14 +2206,49 @@ renderFontClassName font current =
20512206 |> String.toLower
20522207 |> String.words
20532208 |> String.join "-"
2209+
2210+ FontWith { name } ->
2211+ name
2212+ |> String.toLower
2213+ |> String.words
2214+ |> String.join "-"
20542215 )
20552216
20562217
20572218renderFocusStyle :
20582219 FocusStyle
2059− -> Style
2220+ -> List Style
20602221renderFocusStyle focus =
2061− Style (Internal.Style.dot classes.any ++ ":focus .focusable, " ++ Internal.Style.dot classes.any ++ ".focusable:focus")
2222+ [ Style (Internal.Style.dot classes.focusedWithin ++ ":focus-within")
2223+ (List.filterMap identity
2224+ [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
2225+ , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
2226+ , Maybe.map
2227+ (\shadow ->
2228+ Property "box-shadow"
2229+ (formatBoxShadow
2230+ { color = shadow.color
2231+ , offset =
2232+ shadow.offset
2233+ |> Tuple.mapFirst toFloat
2234+ |> Tuple.mapSecond toFloat
2235+ , inset = False
2236+ , blur =
2237+ toFloat shadow.blur
2238+ , size =
2239+ toFloat shadow.size
2240+ }
2241+ )
2242+ )
2243+ focus.shadow
2244+ , Just <| Property "outline" "none"
2245+ ]
2246+ )
2247+ , Style
2248+ ((Internal.Style.dot classes.any ++ ":focus .focusable, ")
2249+ ++ (Internal.Style.dot classes.any ++ ".focusable:focus, ")
2250+ ++ (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb")
2251+ )
20622252 (List.filterMap identity
20632253 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
20642254 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
@@ -2081,6 +2271,7 @@ renderFocusStyle focus =
20812271 , Just <| Property "outline" "none"
20822272 ]
20832273 )
2274+ ]
20842275
20852276
20862277focusDefaultStyle : { backgroundColor : Maybe Color, borderColor : Maybe Color, shadow : Maybe Shadow }
@@ -2092,7 +2283,7 @@ focusDefaultStyle =
20922283 { color =
20932284 Rgba (155 / 255) (203 / 255) 1 1
20942285 , offset = ( 0, 0 )
2095− , blur = 3
2286+ , blur = 0
20962287 , size = 3
20972288 }
20982289 }
@@ -2160,519 +2351,734 @@ optionsToRecord options =
21602351 options
21612352
21622353
2163−renderFont : List Font -> String
2164−renderFont families =
2354+toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2355+toStyleSheet options styleSheet =
2356+ case options.mode of
2357+ Layout ->
2358+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2359+ VirtualDom.node "div"
2360+ []
2361+ [ VirtualDom.node "style"
2362+ []
2363+ [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2364+ ]
2365+
2366+ NoStaticStyleSheet ->
2367+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2368+ VirtualDom.node "div"
2369+ []
2370+ [ VirtualDom.node "style"
2371+ []
2372+ [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2373+ ]
2374+
2375+ WithVirtualCss ->
2376+ VirtualDom.node "elm-ui-rules"
2377+ [ VirtualDom.property "rules"
2378+ (encodeStyles options styleSheet)
2379+ ]
2380+ []
2381+
2382+
2383+renderTopLevelValues rules =
21652384 let
2166− fontName font =
2385+ withImport font =
21672386 case font of
2168− Serif ->
2169− "serif"
2387+ ImportFont _ url ->
2388+ Just ("@import url('" ++ url ++ "');")
2389+
2390+ -- FontWith with ->
2391+ -- case with.url of
2392+ -- Just x ->
2393+ -- Just ("@import url('" ++ x ++ "');")
2394+ -- Nothing ->
2395+ -- Nothing
2396+ _ ->
2397+ Nothing
21702398
2171− SansSerif ->
2172− "sans-serif"
2399+ allNames =
2400+ List.map Tuple.first rules
21732401
2174− Monospace ->
2175− "monospace"
2402+ fontImports ( name, typefaces ) =
2403+ let
2404+ imports =
2405+ String.join "\n" (List.filterMap withImport typefaces)
2406+ in
2407+ imports
21762408
2177− Typeface name ->
2178− "\"" ++ name ++ "\""
2409+ fontAdjustments ( name, typefaces ) =
2410+ case typefaceAdjustment typefaces of
2411+ Nothing ->
2412+ String.join ""
2413+ (List.map (renderNullAdjustmentRule name) allNames)
21792414
2180− ImportFont name url ->
2181− "\"" ++ name ++ "\""
2415+ Just adjustment ->
2416+ String.join ""
2417+ (List.map (renderFontAdjustmentRule name adjustment) allNames)
21822418 in
2183− families
2184− |> List.map fontName
2185− |> String.join ", "
2419+ String.join "\n" (List.map fontImports rules)
2420+ ++ String.join "\n" (List.map fontAdjustments rules)
21862421
21872422
2188−toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2189−toStyleSheet options styleSheet =
2190− VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2423+renderNullAdjustmentRule fontToAdjust otherFontName =
2424+ let
2425+ name =
2426+ if fontToAdjust == otherFontName then
2427+ fontToAdjust
21912428
2429+ else
2430+ otherFontName ++ " ." ++ fontToAdjust
2431+ in
2432+ String.join " "
2433+ [ bracket
2434+ ("."
2435+ ++ name
2436+ ++ "."
2437+ ++ classes.sizeByCapital
2438+ ++ ", "
2439+ ++ "."
2440+ ++ name
2441+ ++ " ."
2442+ ++ classes.sizeByCapital
2443+ )
2444+ [ ( "line-height", "1" )
2445+ ]
2446+ , bracket
2447+ ("."
2448+ ++ name
2449+ ++ "."
2450+ ++ classes.sizeByCapital
2451+ ++ "> ."
2452+ ++ Internal.Style.classes.text
2453+ ++ ", ."
2454+ ++ name
2455+ ++ " ."
2456+ ++ classes.sizeByCapital
2457+ ++ " > ."
2458+ ++ Internal.Style.classes.text
2459+ )
2460+ [ ( "vertical-align", "0" )
2461+ , ( "line-height", "1" )
2462+ ]
2463+ ]
21922464
2193−toStyleSheetString : OptionRecord -> List Style -> String
2194−toStyleSheetString options stylesheet =
2195− let
2196− renderTopLevels rule =
2197− case rule of
2198− FontFamily name typefaces ->
2199− let
2200− getImports font =
2201− case font of
2202− ImportFont _ url ->
2203− Just ("@import url('" ++ url ++ "');")
22042465
2205− _ ->
2206− Nothing
2207− in
2208− typefaces
2209− |> List.filterMap getImports
2210− |> String.join "\n"
2211− |> Just
2466+fontRule name modifier ( parentAdj, textAdjustment ) =
2467+ [ bracket
2468+ ("."
2469+ ++ name
2470+ ++ "."
2471+ ++ modifier
2472+ ++ ", "
2473+ ++ "."
2474+ ++ name
2475+ ++ " ."
2476+ ++ modifier
2477+ )
2478+ parentAdj
2479+ , bracket
2480+ ("."
2481+ ++ name
2482+ ++ "."
2483+ ++ modifier
2484+ ++ "> ."
2485+ ++ Internal.Style.classes.text
2486+ ++ ", ."
2487+ ++ name
2488+ ++ " ."
2489+ ++ modifier
2490+ ++ " > ."
2491+ ++ Internal.Style.classes.text
2492+ )
2493+ textAdjustment
2494+ ]
22122495
2213− _ ->
2214− Nothing
22152496
2216− renderProps force (Property key val) existing =
2217− if force then
2218− existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2497+renderFontAdjustmentRule fontToAdjust ( full, capital ) otherFontName =
2498+ let
2499+ name =
2500+ if fontToAdjust == otherFontName then
2501+ fontToAdjust
22192502
22202503 else
2221− existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2504+ otherFontName ++ " ." ++ fontToAdjust
2505+ in
2506+ String.join " "
2507+ (fontRule name classes.sizeByCapital capital ++ fontRule name classes.fullSize full)
2508+
2509+
2510+bracket selector rules =
2511+ let
2512+ renderPair ( name, val ) =
2513+ name ++ ": " ++ val ++ ";"
2514+ in
2515+ selector ++ " {" ++ String.join "" (List.map renderPair rules) ++ "}"
2516+
2517+
2518+fontAdjustmentRules converted =
2519+ ( [ ( "display", "block" )
2520+ ]
2521+ , [ ( "display", "inline-block" )
2522+ , ( "line-height", String.fromFloat converted.height )
2523+ , ( "vertical-align", String.fromFloat converted.vertical ++ "em" )
2524+ , ( "font-size", String.fromFloat converted.size ++ "em" )
2525+ ]
2526+ )
22222527
2223− renderStyle maybePseudo selector props =
2224− case maybePseudo of
2528+
2529+typefaceAdjustment typefaces =
2530+ List.foldl
2531+ (\face found ->
2532+ case found of
22252533 Nothing ->
2226− selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}"
2534+ case face of
2535+ FontWith with ->
2536+ case with.adjustment of
2537+ Nothing ->
2538+ found
2539+
2540+ Just adjustment ->
2541+ Just
2542+ ( fontAdjustmentRules
2543+ (.full (convertAdjustment adjustment))
2544+ , fontAdjustmentRules
2545+ (.capital (convertAdjustment adjustment))
2546+ )
22272547
2228− Just pseudo ->
2229− case pseudo of
2230− Hover ->
2231− case options.hover of
2232− NoHover ->
2233− ""
2548+ _ ->
2549+ found
2550+
2551+ Just _ ->
2552+ found
2553+ )
2554+ Nothing
2555+ typefaces
22342556
2235− ForceHover ->
2236− selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}"
22372557
2238− AllowHover ->
2239− selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2558+fontName font =
2559+ case font of
2560+ Serif ->
2561+ "serif"
22402562
2241− Focus ->
2242− let
2243− renderedProps =
2244− List.foldl (renderProps False) "" props
2245− in
2246− String.join "\n"
2247− [ selector
2248− ++ "-fs:focus {"
2249− ++ renderedProps
2250− ++ "\n}"
2251− , "."
2252− ++ classes.any
2253− ++ ":focus ~ "
2254− ++ selector
2255− ++ "-fs:not(.focus) {"
2256− ++ renderedProps
2257− ++ "\n}"
2258− , "."
2259− ++ classes.any
2260− ++ ":focus "
2261− ++ selector
2262− ++ "-fs {"
2263− ++ renderedProps
2264− ++ "\n}"
2265− , ".focusable-parent:focus ~ "
2266− ++ "."
2267− ++ classes.any
2268− ++ " "
2269− ++ selector
2270− ++ "-fs {"
2271− ++ renderedProps
2272− ++ "\n}"
2273− ]
2563+ SansSerif ->
2564+ "sans-serif"
22742565
2275− Active ->
2276− selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2566+ Monospace ->
2567+ "monospace"
22772568
2278− renderStyleRule rule maybePseudo =
2279− case rule of
2280− Style selector props ->
2281− renderStyle maybePseudo selector props
2569+ Typeface name ->
2570+ "\"" ++ name ++ "\""
22822571
2283− Shadows name prop ->
2284− renderStyle
2285− maybePseudo
2286− ("." ++ name)
2287− [ Property "box-shadow" prop
2288− ]
2572+ ImportFont name url ->
2573+ "\"" ++ name ++ "\""
2574+
2575+ FontWith { name } ->
2576+ "\"" ++ name ++ "\""
2577+
2578+
2579+topLevelValue rule =
2580+ case rule of
2581+ FontFamily name typefaces ->
2582+ Just ( name, typefaces )
2583+
2584+ _ ->
2585+ Nothing
2586+
2587+
2588+renderProps force (Property key val) existing =
2589+ if force then
2590+ existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2591+
2592+ else
2593+ existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2594+
2595+
2596+encodeStyles options stylesheet =
2597+ stylesheet
2598+ |> List.map
2599+ (\style ->
2600+ let
2601+ styled =
2602+ renderStyleRule options style Nothing
2603+ in
2604+ ( getStyleName style, Encode.list Encode.string styled )
2605+ )
2606+ |> Encode.object
2607+
2608+
2609+toStyleSheetString : OptionRecord -> List Style -> String
2610+toStyleSheetString options stylesheet =
2611+ let
2612+ combine style rendered =
2613+ { rules = rendered.rules ++ renderStyleRule options style Nothing
2614+ , topLevel =
2615+ case topLevelValue style of
2616+ Nothing ->
2617+ rendered.topLevel
2618+
2619+ Just topLevel ->
2620+ topLevel :: rendered.topLevel
2621+ }
2622+ in
2623+ case List.foldl combine { topLevel = [], rules = [] } stylesheet of
2624+ { topLevel, rules } ->
2625+ renderTopLevelValues topLevel ++ String.concat rules
2626+
2627+
2628+renderStyle : OptionRecord -> Maybe PseudoClass -> String -> List Property -> List String
2629+renderStyle options maybePseudo selector props =
2630+ case maybePseudo of
2631+ Nothing ->
2632+ [ selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2633+
2634+ Just pseudo ->
2635+ case pseudo of
2636+ Hover ->
2637+ case options.hover of
2638+ NoHover ->
2639+ []
2640+
2641+ ForceHover ->
2642+ [ selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}" ]
22892643
2290− Transparency name transparency ->
2644+ AllowHover ->
2645+ [ selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2646+
2647+ Focus ->
22912648 let
2292− opacity =
2293− (1 - transparency)
2294− |> min 1
2295− |> max 0
2649+ renderedProps =
2650+ List.foldl (renderProps False) "" props
22962651 in
2297− renderStyle
2298− maybePseudo
2299− ("." ++ name)
2300− [ Property "opacity" (String.fromFloat opacity)
2301− ]
2652+ [ selector ++ "-fs:focus {" ++ renderedProps ++ "\n}"
2653+ , ("." ++ classes.any ++ ":focus " ++ selector ++ "-fs {")
2654+ ++ renderedProps
2655+ ++ "\n}"
2656+ , (selector ++ "-fs:focus-within {")
2657+ ++ renderedProps
2658+ ++ "\n}"
2659+ , (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb" ++ selector ++ "-fs {")
2660+ ++ renderedProps
2661+ ++ "\n}"
2662+ ]
23022663
2303− FontSize i ->
2304− renderStyle
2305− maybePseudo
2306− (".font-size-" ++ String.fromInt i)
2307− [ Property "font-size" (String.fromInt i ++ "px")
2308− ]
2664+ Active ->
2665+ [ selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
23092666
2310− FontFamily name typefaces ->
2311− renderStyle
2312− maybePseudo
2313− ("." ++ name)
2314− [ Property "font-family" (renderFont typefaces)
2315− ]
23162667
2317− Single class prop val ->
2318− renderStyle
2319− maybePseudo
2320− ("." ++ class)
2321− [ Property prop val
2322− ]
2668+renderStyleRule : OptionRecord -> Style -> Maybe PseudoClass -> List String
2669+renderStyleRule options rule maybePseudo =
2670+ case rule of
2671+ Style selector props ->
2672+ renderStyle options maybePseudo selector props
23232673
2324− Colored class prop color ->
2325− renderStyle
2326− maybePseudo
2327− ("." ++ class)
2328− [ Property prop (formatColor color)
2329− ]
2674+ Shadows name prop ->
2675+ renderStyle options
2676+ maybePseudo
2677+ ("." ++ name)
2678+ [ Property "box-shadow" prop
2679+ ]
23302680
2331− SpacingStyle cls x y ->
2332− let
2333− class =
2334− "." ++ cls
2681+ Transparency name transparency ->
2682+ let
2683+ opacity =
2684+ (1 - transparency)
2685+ |> min 1
2686+ |> max 0
2687+ in
2688+ renderStyle options
2689+ maybePseudo
2690+ ("." ++ name)
2691+ [ Property "opacity" (String.fromFloat opacity)
2692+ ]
23352693
2336− xPx =
2337− String.fromInt x ++ "px"
2694+ FontSize i ->
2695+ renderStyle options
2696+ maybePseudo
2697+ (".font-size-" ++ String.fromInt i)
2698+ [ Property "font-size" (String.fromInt i ++ "px")
2699+ ]
23382700
2339− yPx =
2340− String.fromInt y ++ "px"
2701+ FontFamily name typefaces ->
2702+ let
2703+ features =
2704+ typefaces
2705+ |> List.filterMap renderVariants
2706+ |> String.join ", "
2707+
2708+ families =
2709+ [ Property "font-family"
2710+ (typefaces
2711+ |> List.map fontName
2712+ |> String.join ", "
2713+ )
2714+ , Property "font-feature-settings" features
2715+ , Property "font-variant"
2716+ (if List.any hasSmallCaps typefaces then
2717+ "small-caps"
23412718
2342− row =
2343− "." ++ Internal.Style.classes.row
2719+ else
2720+ "normal"
2721+ )
2722+ ]
2723+ in
2724+ renderStyle options
2725+ maybePseudo
2726+ ("." ++ name)
2727+ families
23442728
2345− wrappedRow =
2346− "." ++ Internal.Style.classes.wrapped ++ row
2729+ Single class prop val ->
2730+ renderStyle options
2731+ maybePseudo
2732+ ("." ++ class)
2733+ [ Property prop val
2734+ ]
23472735
2348− column =
2349− "." ++ Internal.Style.classes.column
2736+ Colored class prop color ->
2737+ renderStyle options
2738+ maybePseudo
2739+ ("." ++ class)
2740+ [ Property prop (formatColor color)
2741+ ]
23502742
2351− page =
2352− "." ++ Internal.Style.classes.page
2743+ SpacingStyle cls x y ->
2744+ let
2745+ class =
2746+ "." ++ cls
23532747
2354− paragraph =
2355− "." ++ Internal.Style.classes.paragraph
2748+ halfX =
2749+ String.fromFloat (toFloat x / 2) ++ "px"
23562750
2357− left =
2358− "." ++ Internal.Style.classes.alignLeft
2751+ halfY =
2752+ String.fromFloat (toFloat y / 2) ++ "px"
23592753
2360− right =
2361− "." ++ Internal.Style.classes.alignRight
2754+ xPx =
2755+ String.fromInt x ++ "px"
23622756
2363− any =
2364− "." ++ Internal.Style.classes.any
2757+ yPx =
2758+ String.fromInt y ++ "px"
23652759
2366− single =
2367− "." ++ Internal.Style.classes.single
2368− in
2369− String.concat
2370− [ renderStyle maybePseudo (class ++ row ++ " > " ++ any) [ Property "margin-right" xPx ]
2760+ row =
2761+ "." ++ Internal.Style.classes.row
23712762
2372− -- margins don't apply to last element of normal, unwrapped rows
2373− , renderStyle maybePseudo (class ++ row ++ " > " ++ any ++ ":last-child") [ Property "margin" "0" ]
2763+ wrappedRow =
2764+ "." ++ Internal.Style.classes.wrapped ++ row
23742765
2375− -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2376− , renderStyle maybePseudo
2377− (class ++ wrappedRow ++ " > " ++ any)
2378− [ Property "margin" ("0 " ++ xPx ++ " " ++ yPx ++ " 0")
2379− ]
2380− , renderStyle maybePseudo
2381− (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2382− [ Property "margin-right" "0"
2383− ]
2766+ column =
2767+ "." ++ Internal.Style.classes.column
23842768
2385− -- columns
2386− , renderStyle maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2387− , renderStyle maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2388− , renderStyle maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2389− , renderStyle maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2390− , renderStyle
2391− maybePseudo
2392− (class ++ paragraph)
2393− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2394− ]
2395− , renderStyle
2396− maybePseudo
2397− ("textarea" ++ class)
2398− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2399− ]
2769+ page =
2770+ "." ++ Internal.Style.classes.page
24002771
2401− -- , renderStyle
2402− -- maybePseudo
2403− -- (class ++ paragraph ++ " > " ++ any)
2404− -- [ Property "margin-right" xPx
2405− -- , Property "margin-bottom" yPx
2406− -- ]
2407− , renderStyle
2408− maybePseudo
2409− (class ++ paragraph ++ " > " ++ left)
2410− [ Property "margin-right" xPx
2411− ]
2412− , renderStyle
2413− maybePseudo
2414− (class ++ paragraph ++ " > " ++ right)
2415− [ Property "margin-left" xPx
2416− ]
2417− , renderStyle
2418− maybePseudo
2419− (class ++ paragraph ++ "::after")
2420− [ Property "content" "''"
2421− , Property "display" "block"
2422− , Property "height" "0"
2423− , Property "width" "0"
2424− , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2425− ]
2426− , renderStyle
2427− maybePseudo
2428− (class ++ paragraph ++ "::before")
2429− [ Property "content" "''"
2430− , Property "display" "block"
2431− , Property "height" "0"
2432− , Property "width" "0"
2433− , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2434− ]
2435− ]
2772+ paragraph =
2773+ "." ++ Internal.Style.classes.paragraph
24362774
2437− PaddingStyle cls top right bottom left ->
2438− let
2439− class =
2440− "."
2441− ++ cls
2442− in
2443− renderStyle
2444− maybePseudo
2445− class
2446− [ Property "padding"
2447− (String.fromInt top
2448− ++ "px "
2449− ++ String.fromInt right
2450− ++ "px "
2451− ++ String.fromInt bottom
2452− ++ "px "
2453− ++ String.fromInt left
2454− ++ "px"
2455− )
2456− ]
2775+ left =
2776+ "." ++ Internal.Style.classes.alignLeft
24572777
2458− BorderWidth cls top right bottom left ->
2459− let
2460− class =
2461− "."
2462− ++ cls
2463− in
2464− renderStyle
2465− maybePseudo
2466− class
2467− [ Property "border-width"
2468− (String.fromInt top
2469− ++ "px "
2470− ++ String.fromInt right
2471− ++ "px "
2472− ++ String.fromInt bottom
2473− ++ "px "
2474− ++ String.fromInt left
2475− ++ "px"
2476− )
2477− ]
2778+ right =
2779+ "." ++ Internal.Style.classes.alignRight
24782780
2479− GridTemplateStyle template ->
2480− let
2481− class =
2482− ".grid-rows-"
2483− ++ String.join "-" (List.map lengthClassName template.rows)
2484− ++ "-cols-"
2485− ++ String.join "-" (List.map lengthClassName template.columns)
2486− ++ "-space-x-"
2487− ++ lengthClassName (Tuple.first template.spacing)
2488− ++ "-space-y-"
2489− ++ lengthClassName (Tuple.second template.spacing)
2490−
2491− ySpacing =
2492− toGridLength (Tuple.second template.spacing)
2493−
2494− xSpacing =
2495− toGridLength (Tuple.first template.spacing)
2496−
2497− toGridLength x =
2498− toGridLengthHelper Nothing Nothing x
2499−
2500− toGridLengthHelper minimum maximum x =
2501− case x of
2502− Px px ->
2503− String.fromInt px ++ "px"
2504−
2505− Content ->
2506− case ( minimum, maximum ) of
2507− ( Nothing, Nothing ) ->
2508− "max-content"
2509−
2510− ( Just minSize, Nothing ) ->
2511− "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2512−
2513− ( Nothing, Just maxSize ) ->
2514− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2515−
2516− ( Just minSize, Just maxSize ) ->
2517− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2518−
2519− Fill i ->
2520− case ( minimum, maximum ) of
2521− ( Nothing, Nothing ) ->
2522− String.fromInt i ++ "fr"
2523−
2524− ( Just minSize, Nothing ) ->
2525− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2526−
2527− ( Nothing, Just maxSize ) ->
2528− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2529−
2530− ( Just minSize, Just maxSize ) ->
2531− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2532−
2533− Min m len ->
2534− toGridLengthHelper (Just m) maximum len
2535−
2536− Max m len ->
2537− toGridLengthHelper minimum (Just m) len
2538−
2539− msColumns =
2540− template.columns
2541− |> List.map toGridLength
2542− |> String.join ySpacing
2543− |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2544−
2545− msRows =
2546− template.columns
2547− |> List.map toGridLength
2548− |> String.join ySpacing
2549− |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2550−
2551− base =
2552− class ++ "{" ++ msColumns ++ msRows ++ "}"
2553−
2554− columns =
2555− template.columns
2556− |> List.map toGridLength
2557− |> String.join " "
2558− |> (\x -> "grid-template-columns: " ++ x ++ ";")
2559−
2560− rows =
2561− template.rows
2562− |> List.map toGridLength
2563− |> String.join " "
2564− |> (\x -> "grid-template-rows: " ++ x ++ ";")
2565−
2566− gapX =
2567− "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
2568−
2569− gapY =
2570− "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
2571−
2572− modernGrid =
2573− class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
2574−
2575− supports =
2576− "@supports (display:grid) {" ++ modernGrid ++ "}"
2577− in
2578− base ++ supports
2781+ any =
2782+ "." ++ Internal.Style.classes.any
25792783
2580− GridPosition position ->
2581− let
2582− class =
2583− ".grid-pos-"
2584− ++ String.fromInt position.row
2585− ++ "-"
2586− ++ String.fromInt position.col
2587− ++ "-"
2588− ++ String.fromInt position.width
2589− ++ "-"
2590− ++ String.fromInt position.height
2591−
2592− msPosition =
2593− String.join " "
2594− [ "-ms-grid-row: "
2595− ++ String.fromInt position.row
2596− ++ ";"
2597− , "-ms-grid-row-span: "
2598− ++ String.fromInt position.height
2599− ++ ";"
2600− , "-ms-grid-column: "
2601− ++ String.fromInt position.col
2602− ++ ";"
2603− , "-ms-grid-column-span: "
2604− ++ String.fromInt position.width
2605− ++ ";"
2606− ]
2607−
2608− base =
2609− class ++ "{" ++ msPosition ++ "}"
2610−
2611− modernPosition =
2612− String.join " "
2613− [ "grid-row: "
2614− ++ String.fromInt position.row
2615− ++ " / "
2616− ++ String.fromInt (position.row + position.height)
2617− ++ ";"
2618− , "grid-column: "
2619− ++ String.fromInt position.col
2620− ++ " / "
2621− ++ String.fromInt (position.col + position.width)
2622− ++ ";"
2623− ]
2624−
2625− modernGrid =
2626− class ++ "{" ++ modernPosition ++ "}"
2627−
2628− supports =
2629− "@supports (display:grid) {" ++ modernGrid ++ "}"
2630− in
2631− base ++ supports
2784+ single =
2785+ "." ++ Internal.Style.classes.single
2786+ in
2787+ List.concat
2788+ [ renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ " + " ++ any) [ Property "margin-left" xPx ]
2789+
2790+ -- margins don't apply to last element of normal, unwrapped rows
2791+ -- , renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ ":first-child") [ Property "margin" "0" ]
2792+ -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2793+ , renderStyle options
2794+ maybePseudo
2795+ (class ++ wrappedRow ++ " > " ++ any)
2796+ [ Property "margin" (halfY ++ " " ++ halfX)
2797+ ]
26322798
2633− PseudoSelector class styles ->
2634− let
2635− renderPseudoRule style =
2636− renderStyleRule style (Just class)
2637− in
2638− List.map renderPseudoRule styles
2799+ -- , renderStyle options maybePseudo
2800+ -- (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2801+ -- [ Property "margin-right" "0"
2802+ -- ]
2803+ -- columns
2804+ , renderStyle options maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2805+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2806+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2807+ , renderStyle options maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2808+ , renderStyle options
2809+ maybePseudo
2810+ (class ++ paragraph)
2811+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2812+ ]
2813+ , renderStyle options
2814+ maybePseudo
2815+ ("textarea" ++ any ++ class)
2816+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2817+ , Property "height" ("calc(100% + " ++ String.fromInt y ++ "px)")
2818+ ]
2819+
2820+ -- , renderStyle options
2821+ -- maybePseudo
2822+ -- (class ++ paragraph ++ " > " ++ any)
2823+ -- [ Property "margin-right" xPx
2824+ -- , Property "margin-bottom" yPx
2825+ -- ]
2826+ , renderStyle options
2827+ maybePseudo
2828+ (class ++ paragraph ++ " > " ++ left)
2829+ [ Property "margin-right" xPx
2830+ ]
2831+ , renderStyle options
2832+ maybePseudo
2833+ (class ++ paragraph ++ " > " ++ right)
2834+ [ Property "margin-left" xPx
2835+ ]
2836+ , renderStyle options
2837+ maybePseudo
2838+ (class ++ paragraph ++ "::after")
2839+ [ Property "content" "''"
2840+ , Property "display" "block"
2841+ , Property "height" "0"
2842+ , Property "width" "0"
2843+ , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2844+ ]
2845+ , renderStyle options
2846+ maybePseudo
2847+ (class ++ paragraph ++ "::before")
2848+ [ Property "content" "''"
2849+ , Property "display" "block"
2850+ , Property "height" "0"
2851+ , Property "width" "0"
2852+ , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2853+ ]
2854+ ]
2855+
2856+ PaddingStyle cls top right bottom left ->
2857+ let
2858+ class =
2859+ "."
2860+ ++ cls
2861+ in
2862+ renderStyle options
2863+ maybePseudo
2864+ class
2865+ [ Property "padding"
2866+ (String.fromFloat top
2867+ ++ "px "
2868+ ++ String.fromFloat right
2869+ ++ "px "
2870+ ++ String.fromFloat bottom
2871+ ++ "px "
2872+ ++ String.fromFloat left
2873+ ++ "px"
2874+ )
2875+ ]
2876+
2877+ BorderWidth cls top right bottom left ->
2878+ let
2879+ class =
2880+ "."
2881+ ++ cls
2882+ in
2883+ renderStyle options
2884+ maybePseudo
2885+ class
2886+ [ Property "border-width"
2887+ (String.fromInt top
2888+ ++ "px "
2889+ ++ String.fromInt right
2890+ ++ "px "
2891+ ++ String.fromInt bottom
2892+ ++ "px "
2893+ ++ String.fromInt left
2894+ ++ "px"
2895+ )
2896+ ]
2897+
2898+ GridTemplateStyle template ->
2899+ let
2900+ class =
2901+ ".grid-rows-"
2902+ ++ String.join "-" (List.map lengthClassName template.rows)
2903+ ++ "-cols-"
2904+ ++ String.join "-" (List.map lengthClassName template.columns)
2905+ ++ "-space-x-"
2906+ ++ lengthClassName (Tuple.first template.spacing)
2907+ ++ "-space-y-"
2908+ ++ lengthClassName (Tuple.second template.spacing)
2909+
2910+ ySpacing =
2911+ toGridLength (Tuple.second template.spacing)
2912+
2913+ xSpacing =
2914+ toGridLength (Tuple.first template.spacing)
2915+
2916+ toGridLength x =
2917+ toGridLengthHelper Nothing Nothing x
2918+
2919+ toGridLengthHelper minimum maximum x =
2920+ case x of
2921+ Px px ->
2922+ String.fromInt px ++ "px"
2923+
2924+ Content ->
2925+ case ( minimum, maximum ) of
2926+ ( Nothing, Nothing ) ->
2927+ "max-content"
2928+
2929+ ( Just minSize, Nothing ) ->
2930+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2931+
2932+ ( Nothing, Just maxSize ) ->
2933+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2934+
2935+ ( Just minSize, Just maxSize ) ->
2936+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2937+
2938+ Fill i ->
2939+ case ( minimum, maximum ) of
2940+ ( Nothing, Nothing ) ->
2941+ String.fromInt i ++ "fr"
2942+
2943+ ( Just minSize, Nothing ) ->
2944+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2945+
2946+ ( Nothing, Just maxSize ) ->
2947+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2948+
2949+ ( Just minSize, Just maxSize ) ->
2950+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2951+
2952+ Min m len ->
2953+ toGridLengthHelper (Just m) maximum len
2954+
2955+ Max m len ->
2956+ toGridLengthHelper minimum (Just m) len
2957+
2958+ msColumns =
2959+ template.columns
2960+ |> List.map toGridLength
2961+ |> String.join ySpacing
2962+ |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2963+
2964+ msRows =
2965+ template.columns
2966+ |> List.map toGridLength
2967+ |> String.join ySpacing
2968+ |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2969+
2970+ base =
2971+ class ++ "{" ++ msColumns ++ msRows ++ "}"
2972+
2973+ columns =
2974+ template.columns
2975+ |> List.map toGridLength
26392976 |> String.join " "
2977+ |> (\x -> "grid-template-columns: " ++ x ++ ";")
26402978
2641− Transform transform ->
2642− let
2643− val =
2644− transformValue transform
2979+ rows =
2980+ template.rows
2981+ |> List.map toGridLength
2982+ |> String.join " "
2983+ |> (\x -> "grid-template-rows: " ++ x ++ ";")
26452984
2646− class =
2647− transformClass transform
2648− in
2649− case ( class, val ) of
2650− ( Just cls, Just v ) ->
2651− renderStyle
2652− maybePseudo
2653− ("." ++ cls)
2654− [ Property "transform"
2655− v
2656− ]
2985+ gapX =
2986+ "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
26572987
2658− _ ->
2659− ""
2988+ gapY =
2989+ "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
26602990
2661− combine style rendered =
2662− { rendered
2663− | rules = rendered.rules ++ renderStyleRule style Nothing
2664− , topLevel =
2665− case renderTopLevels style of
2666− Nothing ->
2667− rendered.topLevel
2991+ modernGrid =
2992+ class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
26682993
2669− Just topLevel ->
2670− rendered.topLevel ++ topLevel
2671− }
2672− in
2673− case List.foldl combine { rules = "", topLevel = "" } stylesheet of
2674− { topLevel, rules } ->
2675− topLevel ++ rules
2994+ supports =
2995+ "@supports (display:grid) {" ++ modernGrid ++ "}"
2996+ in
2997+ [ base
2998+ , supports
2999+ ]
3000+
3001+ GridPosition position ->
3002+ let
3003+ class =
3004+ ".grid-pos-"
3005+ ++ String.fromInt position.row
3006+ ++ "-"
3007+ ++ String.fromInt position.col
3008+ ++ "-"
3009+ ++ String.fromInt position.width
3010+ ++ "-"
3011+ ++ String.fromInt position.height
3012+
3013+ msPosition =
3014+ String.join " "
3015+ [ "-ms-grid-row: "
3016+ ++ String.fromInt position.row
3017+ ++ ";"
3018+ , "-ms-grid-row-span: "
3019+ ++ String.fromInt position.height
3020+ ++ ";"
3021+ , "-ms-grid-column: "
3022+ ++ String.fromInt position.col
3023+ ++ ";"
3024+ , "-ms-grid-column-span: "
3025+ ++ String.fromInt position.width
3026+ ++ ";"
3027+ ]
3028+
3029+ base =
3030+ class ++ "{" ++ msPosition ++ "}"
3031+
3032+ modernPosition =
3033+ String.join " "
3034+ [ "grid-row: "
3035+ ++ String.fromInt position.row
3036+ ++ " / "
3037+ ++ String.fromInt (position.row + position.height)
3038+ ++ ";"
3039+ , "grid-column: "
3040+ ++ String.fromInt position.col
3041+ ++ " / "
3042+ ++ String.fromInt (position.col + position.width)
3043+ ++ ";"
3044+ ]
3045+
3046+ modernGrid =
3047+ class ++ "{" ++ modernPosition ++ "}"
3048+
3049+ supports =
3050+ "@supports (display:grid) {" ++ modernGrid ++ "}"
3051+ in
3052+ [ base
3053+ , supports
3054+ ]
3055+
3056+ PseudoSelector class styles ->
3057+ let
3058+ renderPseudoRule style =
3059+ renderStyleRule options style (Just class)
3060+ in
3061+ List.concatMap renderPseudoRule styles
3062+
3063+ Transform transform ->
3064+ let
3065+ val =
3066+ transformValue transform
3067+
3068+ class =
3069+ transformClass transform
3070+ in
3071+ case ( class, val ) of
3072+ ( Just cls, Just v ) ->
3073+ renderStyle options
3074+ maybePseudo
3075+ ("." ++ cls)
3076+ [ Property "transform"
3077+ v
3078+ ]
3079+
3080+ _ ->
3081+ []
26763082
26773083
26783084lengthClassName : Length -> String
@@ -2712,12 +3118,12 @@ formatTextShadow shadow =
27123118 ]
27133119
27143120
2715−textShadowName shadow =
3121+textShadowClass shadow =
27163122 String.concat
27173123 [ "txt"
2718− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2719− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2720− , String.fromFloat shadow.blur ++ "px"
3124+ , floatClass (Tuple.first shadow.offset) ++ "px"
3125+ , floatClass (Tuple.second shadow.offset) ++ "px"
3126+ , floatClass shadow.blur ++ "px"
27213127 , formatColorClass shadow.color
27223128 ]
27233129
@@ -2738,17 +3144,17 @@ formatBoxShadow shadow =
27383144 ]
27393145
27403146
2741−boxShadowName shadow =
3147+boxShadowClass shadow =
27423148 String.concat <|
27433149 [ if shadow.inset then
27443150 "box-inset"
27453151
27463152 else
27473153 "box-"
2748− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2749− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2750− , String.fromFloat shadow.blur ++ "px"
2751− , String.fromFloat shadow.size ++ "px"
3154+ , floatClass (Tuple.first shadow.offset) ++ "px"
3155+ , floatClass (Tuple.second shadow.offset) ++ "px"
3156+ , floatClass shadow.blur ++ "px"
3157+ , floatClass shadow.size ++ "px"
27523158 , formatColorClass shadow.color
27533159 ]
27543160
@@ -2793,6 +3199,17 @@ paddingName top right bottom left =
27933199 ++ String.fromInt left
27943200
27953201
3202+paddingNameFloat top right bottom left =
3203+ "pad-"
3204+ ++ floatClass top
3205+ ++ "-"
3206+ ++ floatClass right
3207+ ++ "-"
3208+ ++ floatClass bottom
3209+ ++ "-"
3210+ ++ floatClass left
3211+
3212+
27963213getStyleName : Style -> String
27973214getStyleName style =
27983215 case style of
@@ -3058,3 +3475,76 @@ onlyStyles attr =
30583475
30593476 _ ->
30603477 Nothing
3478+
3479+
3480+
3481+{- Font Adjustments -}
3482+
3483+
3484+convertAdjustment adjustment =
3485+ let
3486+ lineHeight =
3487+ 1.5
3488+
3489+ base =
3490+ lineHeight
3491+
3492+ normalDescender =
3493+ (lineHeight - 1)
3494+ / 2
3495+
3496+ oldMiddle =
3497+ lineHeight / 2
3498+
3499+ newCapitalMiddle =
3500+ ((ascender - newBaseline) / 2) + newBaseline
3501+
3502+ newFullMiddle =
3503+ ((ascender - descender) / 2) + descender
3504+
3505+ lines =
3506+ [ adjustment.capital
3507+ , adjustment.baseline
3508+ , adjustment.descender
3509+ , adjustment.lowercase
3510+ ]
3511+
3512+ ascender =
3513+ Maybe.withDefault adjustment.capital (List.maximum lines)
3514+
3515+ descender =
3516+ Maybe.withDefault adjustment.descender (List.minimum lines)
3517+
3518+ newBaseline =
3519+ lines
3520+ |> List.filter (\x -> x /= descender)
3521+ |> List.minimum
3522+ |> Maybe.withDefault adjustment.baseline
3523+
3524+ capitalVertical =
3525+ 1 - ascender
3526+
3527+ capitalSize =
3528+ 1 / (ascender - newBaseline)
3529+
3530+ fullSize =
3531+ 1 / (ascender - descender)
3532+
3533+ fullVertical =
3534+ 1 - ascender
3535+
3536+ -- (oldMiddle - newFullMiddle) * 2
3537+ in
3538+ { full =
3539+ adjust fullSize (ascender - descender) fullVertical
3540+ , capital =
3541+ adjust capitalSize (ascender - newBaseline) capitalVertical
3542+ }
3543+
3544+
3545+adjust size height vertical =
3546+ { vertical = vertical
3547+ , height =
3548+ height / size
3549+ , size = size
3550+ }