git.iko.soy/typeable/elm-ui
on master help sign in
Add support for font variants. resolves #16
commitbe7356bb939f7a7cdaf1b13bab33cbf786753b6e authorMatthew Griffith <mdg.griffith@gmail.com> dateSat 22 Sep 2018, 17:15 (8 years ago) parent40ac5d9
5 files changed+218−4
src/Element/Font.elm+142 src/Internal/Flag.elm+5 src/Internal/Model.elm+38−3 src/Internal/Style.elm+29 tests/suite/Flags.elm+4−1
src/Element/Font.elm+142
@@ -5,6 +5,7 @@ module Element.Font exposing
55 , alignLeft, alignRight, center, justify, letterSpacing, wordSpacing
66 , underline, strike, italic, unitalicized
77 , heavy, extraBold, bold, semiBold, medium, regular, light, extraLight, hairline
8+ , Variant, variant, smallCaps, slashedZero, ligatures, ordinal, tabularNumbers, stackedFractions, diagonalFractions, swash, disable, feature, indexed
89 , glow, shadow
910 )
1011
@@ -70,6 +71,11 @@ module Element.Font exposing
7071@docs heavy, extraBold, bold, semiBold, medium, regular, light, extraLight, hairline
7172
7273
74+## Variants
75+
76+@docs Variant, variant, smallCaps, slashedZero, ligatures, ordinal, tabularNumbers, stackedFractions, diagonalFractions, swash, disable, feature, indexed
77+
78+
7379## Shadows
7480
7581@docs glow, shadow
@@ -151,6 +157,7 @@ with :
151157 { name : String
152158 , adjustment : Adjustment
153159 , url : Maybe String
160+ , variants : List Variant
154161 }
155162 -> Font
156163with =
@@ -333,3 +340,138 @@ glow clr i =
333340 in
334341 Internal.StyleClass Flag.txtShadows <|
335342 Internal.Single (Internal.textShadowName shade) "text-shadow" (Internal.formatTextShadow shade)
343+
344+
345+
346+{- Variants -}
347+
348+
349+type alias Variant =
350+ Internal.Variant
351+
352+
353+{-| You can use this to set a single variant on an element itself such as:
354+
355+ el
356+ [ Font.variant Font.smallcaps
357+ ]
358+ (text "rendered with smallcaps")
359+
360+**Note** These will **not** stack. If you want multiple variants, you should use `Font.with`.
361+
362+-}
363+variant : Variant -> Attribute msg
364+variant var =
365+ case var of
366+ Internal.VariantActive name ->
367+ Internal.Class Flag.fontVariant ("v-" ++ name)
368+
369+ Internal.VariantOff name ->
370+ Internal.Class Flag.fontVariant ("v-" ++ name ++ "-off")
371+
372+ Internal.VariantIndexed name index ->
373+ Internal.StyleClass Flag.fontVariant <|
374+ Internal.Single ("v-" ++ name ++ "-" ++ String.fromInt index)
375+ "font-feature-settings"
376+ ("\"" ++ name ++ "\" " ++ String.fromInt index)
377+
378+
379+{-| Less often you might want to disable an active variant.
380+
381+ el
382+ [ Font.variant (Font.disable Font.smallCaps)
383+ ]
384+ (text "Is not smallcaps")
385+
386+**Note** Generally try to set yourself up so that this isn't really necessary.
387+
388+-}
389+disable : Variant -> Variant
390+disable var =
391+ case var of
392+ Internal.VariantActive name ->
393+ Internal.VariantOff name
394+
395+ Internal.VariantIndexed name index ->
396+ Internal.VariantOff name
397+
398+ Internal.VariantOff name ->
399+ var
400+
401+
402+{-| [Small caps](https://en.wikipedia.org/wiki/Small_caps) are rendered using uppercase glyphs, but at the size of lowercase glyphs.
403+-}
404+smallCaps : Variant
405+smallCaps =
406+ Internal.VariantActive "smcp"
407+
408+
409+{-| Add a slash when rendering `0`
410+-}
411+slashedZero : Variant
412+slashedZero =
413+ Internal.VariantActive "zero"
414+
415+
416+{-| -}
417+ligatures : Variant
418+ligatures =
419+ Internal.VariantActive "liga"
420+
421+
422+{-| Oridinal markers like `1st` and `2nd` will receive special glyphs.
423+-}
424+ordinal : Variant
425+ordinal =
426+ Internal.VariantActive "ordn"
427+
428+
429+{-| Number figures will each take up the same space, allowing them to be easily aligned, such as in tables.
430+-}
431+tabularNumbers : Variant
432+tabularNumbers =
433+ Internal.VariantActive "tnum"
434+
435+
436+{-| Render fractions with the numerator stacked on top of the denominator.
437+-}
438+stackedFractions : Variant
439+stackedFractions =
440+ Internal.VariantActive "afrc"
441+
442+
443+{-| Render fractions
444+-}
445+diagonalFractions : Variant
446+diagonalFractions =
447+ Internal.VariantActive "frac"
448+
449+
450+{-| -}
451+swash : Int -> Variant
452+swash =
453+ Internal.VariantIndexed "swsh"
454+
455+
456+{-| Set a feature by name and whether it should be on or off.
457+
458+Feature names are four-letter names as defined in the [OpenType specification](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist).
459+
460+-}
461+feature : String -> Bool -> Variant
462+feature name on =
463+ if on then
464+ Internal.VariantIndexed name 1
465+
466+ else
467+ Internal.VariantIndexed name 0
468+
469+
470+{-| A font variant might have multiple versions within the font.
471+
472+In these cases we need to specify the index of the version we want.
473+
474+-}
475+indexed : String -> Int -> Variant
476+indexed name on =
477+ Internal.VariantIndexed name on
src/Internal/Flag.elm+5
@@ -22,6 +22,7 @@ module Internal.Flag exposing
2222 , fontColor
2323 , fontFamily
2424 , fontSize
25+ , fontVariant
2526 , fontWeight
2627 , gridPosition
2728 , gridTemplate
@@ -318,3 +319,7 @@ behind =
318319
319320heightTextAreaContent =
320321 flag 47
322+
323+
324+fontVariant =
325+ flag 48
src/Internal/Model.elm+38−3
@@ -29,6 +29,7 @@ module Internal.Model exposing
2929 , TransformComponent(..)
3030 , Transformation(..)
3131 , VAlign(..)
32+ , Variant(..)
3233 , XYZ
3334 , addNodeName
3435 , addWhen
@@ -223,9 +224,37 @@ type Font
223224 { name : String
224225 , url : Maybe String
225226 , adjustment : Adjustment
227+ , variants : List Variant
226228 }
227229
228230
231+type Variant
232+ = VariantActive String
233+ | VariantOff String
234+ | VariantIndexed String Int
235+
236+
237+renderVariant var =
238+ case var of
239+ VariantActive name ->
240+ "\"" ++ name ++ "\""
241+
242+ VariantOff name ->
243+ "\"" ++ name ++ "\" 0"
244+
245+ VariantIndexed name index ->
246+ "\"" ++ name ++ "\" " ++ String.fromInt index
247+
248+
249+renderVariants typeface =
250+ case typeface of
251+ FontWith font ->
252+ String.join ", " (List.map renderVariant font.variants)
253+
254+ _ ->
255+ ""
256+
257+
229258type Property
230259 = Property String String
231260
@@ -2474,18 +2503,25 @@ toStyleSheetString options stylesheet =
24742503
24752504 FontFamily name typefaces ->
24762505 let
2506+ features =
2507+ typefaces
2508+ |> List.map renderVariants
2509+ |> String.join ", "
2510+
24772511 families =
2478− Property "font-family"
2512+ [ Property "font-family"
24792513 (typefaces
24802514 |> List.map fontName
24812515 |> String.join ", "
24822516 )
2517+ , Property "font-feature-settings" features
2518+ ]
24832519 in
24842520 String.join " "
24852521 [ renderStyle
24862522 maybePseudo
24872523 ("." ++ name)
2488− [ families ]
2524+ families
24892525 ]
24902526
24912527 Single class prop val ->
@@ -3285,7 +3321,6 @@ convertAdjustment adjustment =
32853321 capitalVertical =
32863322 1 - ascender
32873323
3288−
32893324 capitalSize =
32903325 1 / (ascender - newBaseline)
32913326
src/Internal/Style.elm+29
@@ -785,7 +785,36 @@ commonValues =
785785 Class (".p-" ++ String.fromInt i) [ Prop "padding" (String.fromInt i ++ "px") ]
786786 )
787787 (List.range 0 24)
788+
789+ -- Common Font Variants
790+ , [ Class ".v-smcp"
791+ [ Prop "font-variant" "small-caps"
792+ ]
793+ , Class ".v-smcp-off"
794+ [ Prop "font-variant" "normal"
795+ ]
796+ ]
797+
798+ -- , fontVariant "smcp"
799+ , fontVariant "zero"
800+ , fontVariant "onum"
801+ , fontVariant "liga"
802+ , fontVariant "dlig"
803+ , fontVariant "ordn"
804+ , fontVariant "tnum"
805+ , fontVariant "afrc"
806+ , fontVariant "frac"
807+ ]
808+
809+
810+fontVariant var =
811+ [ Class (".v-" ++ var)
812+ [ Prop "font-feature-settings" ("\"" ++ var ++ "\"")
788813 ]
814+ , Class (".v-" ++ var ++ "-off")
815+ [ Prop "font-feature-settings" ("\"" ++ var ++ "\" 0")
816+ ]
817+ ]
789818
790819
791820rules : String
tests/suite/Flags.elm+4−1
@@ -1,4 +1,4 @@
1−module Main exposing (..)
1+module Main exposing (allFlags, doesntInvalidateOthers, invalidateSelf, main)
22
33import Html
44import Internal.Flag as Flag
@@ -18,6 +18,7 @@ main =
1818invalidateSelf i flag =
1919 if Flag.present flag (Flag.add flag Flag.none) then
2020 Html.text ""
21+
2122 else
2223 Html.div [] [ Html.text (toString (Flag.value flag) ++ " at index " ++ toString i ++ " does not invalidate itself") ]
2324
@@ -38,6 +39,7 @@ doesntInvalidateOthers i flag =
3839 in
3940 if passing then
4041 Html.text ""
42+
4143 else
4244 Html.div []
4345 [ Html.text (toString (Flag.value flag) ++ " at index " ++ toString i ++ " invalidates other flags!")
@@ -86,4 +88,5 @@ allFlags =
8688 , Flag.alignBottom
8789 , Flag.centerX
8890 , Flag.centerY
91+ , Flag.fontVariant
8992 ]