Skip to content

Commit

Permalink
Add support for css animations (@Keyframes)
Browse files Browse the repository at this point in the history
  • Loading branch information
Warry committed Feb 17, 2017
1 parent e9adc45 commit 51ccf72
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 14 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"dependencies": {
"chalk": "1.1.1",
"commander": "2.9.0",
"elm-test": "^0.18.2",
"node-elm-compiler": "2.3.2",
"tmp": "0.0.28"
},
Expand Down
22 changes: 21 additions & 1 deletion src/Css.elm
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ module Css
, projection
, tv
, mediaQuery
, keyframes
, src
, qt
, fontFamilies
Expand Down Expand Up @@ -615,7 +616,7 @@ module Css
@docs screen, tv, projection, print
# Properties
@docs property, flex, flex2, flex3, medium, alignSelf, alignItems, justifyContent, order, flexDirection, flexFlow1, flexFlow2, flexWrap, flexBasis, flexGrow, flexShrink, transformStyle, transformBox, transform, transforms, currentColor, underline, overline, lineThrough, textOrientation, textDecoration, textDecoration2, textDecoration3, textDecorationLine, textDecorations, textDecorations2, textDecorations3, textDecorationLine, textDecorationLines, textDecorationStyle, textEmphasisColor, capitalize, uppercase, lowercase, fullWidth, hanging, eachLine, textIndent, textIndent2, textIndent3, clip, ellipsis, textOverflow, optimizeSpeed, optimizeLegibility, geometricPrecision, textRendering, textTransform, textAlign, textAlignLast, left, right, center, textJustify, justifyAll, start, end, matchParent, true, verticalAlign, display, opacity, minContent, maxContent, fitContent, fillAvailable, width, minWidth, maxWidth, height, minHeight, maxHeight, padding, padding2, padding3, padding4, paddingTop, paddingBottom, paddingRight, paddingLeft, paddingBlockStart, paddingBlockEnd, paddingInlineStart, paddingInlineEnd, margin, margin2, margin3, margin4, marginTop, marginBottom, marginRight, marginLeft, marginBlockStart, marginBlockEnd, marginInlineStart, marginInlineEnd, boxSizing, overflow, overflowX, overflowY, overflowWrap, whiteSpace, backgroundColor, color, withMedia, each, media, mediaQuery, textShadow, textShadow2, textShadow3, textShadow4, boxShadow, boxShadow2, boxShadow3, boxShadow4, boxShadow5, boxShadow6, lineHeight, letterSpacing, fontFace, fontFamily, fontSize, fontStyle, fontWeight, fontVariant, fontVariant2, fontVariant3, fontVariantLigatures, fontVariantCaps, fontVariantNumeric, fontVariantNumeric2, fontVariantNumeric3, fontFamilies, fontVariantNumerics, fontFeatureSettings, fontFeatureSettingsList, cursor, outline, outline3, outlineColor, outlineWidth, outlineStyle, outlineOffset, zIndex, spaceAround, spaceBetween, resize, fill
@docs property, flex, flex2, flex3, medium, alignSelf, alignItems, justifyContent, order, flexDirection, flexFlow1, flexFlow2, flexWrap, flexBasis, flexGrow, flexShrink, transformStyle, transformBox, transform, transforms, currentColor, underline, overline, lineThrough, textOrientation, textDecoration, textDecoration2, textDecoration3, textDecorationLine, textDecorations, textDecorations2, textDecorations3, textDecorationLine, textDecorationLines, textDecorationStyle, textEmphasisColor, capitalize, uppercase, lowercase, fullWidth, hanging, eachLine, textIndent, textIndent2, textIndent3, clip, ellipsis, textOverflow, optimizeSpeed, optimizeLegibility, geometricPrecision, textRendering, textTransform, textAlign, textAlignLast, left, right, center, textJustify, justifyAll, start, end, matchParent, true, verticalAlign, display, opacity, minContent, maxContent, fitContent, fillAvailable, width, minWidth, maxWidth, height, minHeight, maxHeight, padding, padding2, padding3, padding4, paddingTop, paddingBottom, paddingRight, paddingLeft, paddingBlockStart, paddingBlockEnd, paddingInlineStart, paddingInlineEnd, margin, margin2, margin3, margin4, marginTop, marginBottom, marginRight, marginLeft, marginBlockStart, marginBlockEnd, marginInlineStart, marginInlineEnd, boxSizing, overflow, overflowX, overflowY, overflowWrap, whiteSpace, backgroundColor, color, withMedia, each, media, mediaQuery, keyframes, textShadow, textShadow2, textShadow3, textShadow4, boxShadow, boxShadow2, boxShadow3, boxShadow4, boxShadow5, boxShadow6, lineHeight, letterSpacing, fontFace, fontFamily, fontSize, fontStyle, fontWeight, fontVariant, fontVariant2, fontVariant3, fontVariantLigatures, fontVariantCaps, fontVariantNumeric, fontVariantNumeric2, fontVariantNumeric3, fontFamilies, fontVariantNumerics, fontFeatureSettings, fontFeatureSettingsList, cursor, outline, outline3, outlineColor, outlineWidth, outlineStyle, outlineOffset, zIndex, spaceAround, spaceBetween, resize, fill
# Values
Expand Down Expand Up @@ -6390,6 +6391,25 @@ withMedia =
Preprocess.WithMedia


{-| Animation's @keyframe
keyframes "animationName"
[( 0
, [ backgroundColor blue
]
)
[( 100
, [ backgroundColor red
]
)
]
-}
keyframes : String -> List ( Float, List Mixin ) -> Snippet
keyframes name steps =
Preprocess.Snippet ([ Preprocess.Keyframes name steps ])



{- FONT PROPERTIES -}

Expand Down
6 changes: 5 additions & 1 deletion src/Css/Preprocess.elm
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ type SnippetDeclaration
| DocumentRule String String String String StyleBlock
| PageRule String (List Property)
| FontFace (List Property)
| Keyframes String (List Structure.KeyframeProperty)
| Keyframes String (List KeyframeStep)
| Viewport (List Property)
| CounterStyle (List Property)
| FontFeatureValues (List ( String, List Property ))


type alias KeyframeStep =
( Float, List Mixin )


type StyleBlock
= StyleBlock Structure.Selector (List Structure.Selector) (List Mixin)

Expand Down
47 changes: 40 additions & 7 deletions src/Css/Preprocess/Resolve.elm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Structure data structures and gathering warnings along the way.
-}

import String
import List
import Css.Preprocess as Preprocess exposing (SnippetDeclaration, Snippet(Snippet), Mixin(AppendProperty, ExtendSelector, NestSnippet), unwrapSnippet)
import Css.Structure as Structure exposing (mapLast)
import Css.Structure.Output as Output
Expand Down Expand Up @@ -141,11 +142,43 @@ resolveFontFace fontFaceProperties =
}


resolveKeyframes : String -> List Structure.KeyframeProperty -> DeclarationsAndWarnings
resolveKeyframes str properties =
{ declarations = [ Structure.Keyframes str properties ]
, warnings = []
}
resolveKeyframes : String -> List Preprocess.KeyframeStep -> DeclarationsAndWarnings
resolveKeyframes name steps =
let
( warnings, keyframes ) =
extractWarningsFromKeyframes steps ( [], [] )
in
{ declarations = [ Structure.Keyframes name keyframes ]
, warnings = warnings
}


extractWarningsFromKeyframes : List Preprocess.KeyframeStep -> ( List String, List Structure.KeyframeStep ) -> ( List String, List Structure.KeyframeStep )
extractWarningsFromKeyframes ls ( warnings, steps ) =
case ls of
( step, mixins ) :: tl ->
if step < 0 || step > 100 then
-- keyframe is dropped
extractWarningsFromKeyframes tl
( "Keyframe must be between 0 and 100 (those are percents)." :: warnings
, steps
)
else
let
props =
Preprocess.toPropertyPairs mixins
|> List.map pairToProperty

pairToProperty ( k, v ) =
{ important = False
, key = k
, value = v
}
in
extractWarningsFromKeyframes tl ( warnings, ( step, props ) :: steps )

[] ->
( warnings, steps )


resolveViewport : List Preprocess.Property -> DeclarationsAndWarnings
Expand Down Expand Up @@ -218,8 +251,8 @@ toDeclarations snippetDeclaration =
Preprocess.FontFace fontFaceProperties ->
resolveFontFace fontFaceProperties

Preprocess.Keyframes str properties ->
resolveKeyframes str properties
Preprocess.Keyframes name steps ->
resolveKeyframes name steps

Preprocess.Viewport viewportProperties ->
resolveViewport viewportProperties
Expand Down
19 changes: 14 additions & 5 deletions src/Css/Structure.elm
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Declaration
| DocumentRule String String String String StyleBlock
| PageRule String (List Property)
| FontFace (List Property)
| Keyframes String (List KeyframeProperty)
| Keyframes String (List KeyframeStep)
| Viewport (List Property)
| CounterStyle (List Property)
| FontFeatureValues (List ( String, List Property ))
Expand Down Expand Up @@ -121,8 +121,8 @@ type SelectorCombinator
| Descendant


type alias KeyframeProperty =
String
type alias KeyframeStep =
( Float, List Property )


{-| Add a property to the last style block in the given declarations.
Expand All @@ -141,6 +141,11 @@ appendProperty property declarations =
(mapLast (withPropertyAppended property) styleBlocks)
]

(Keyframes name steps) :: [] ->
[ Keyframes name
(mapLast (appendPropertyToKeyframe property) steps)
]

-- TODO
_ :: [] ->
declarations
Expand All @@ -149,7 +154,6 @@ appendProperty property declarations =
--| DocumentRule String String String String StyleBlock
--| PageRule String (List Property)
--| FontFace (List Property)
--| Keyframes String (List KeyframeProperty)
--| Viewport (List Property)
--| CounterStyle (List Property)
--| FontFeatureValues (List ( String, List Property ))
Expand All @@ -162,6 +166,11 @@ withPropertyAppended property (StyleBlock firstSelector otherSelectors propertie
StyleBlock firstSelector otherSelectors (properties ++ [ property ])


appendPropertyToKeyframe : Property -> KeyframeStep -> KeyframeStep
appendPropertyToKeyframe prop ( step, props ) =
( step, prop :: props )


extendLastSelector : RepeatableSimpleSelector -> List Declaration -> List Declaration
extendLastSelector selector declarations =
case declarations of
Expand Down Expand Up @@ -229,7 +238,7 @@ extendLastSelector selector declarations =
(FontFace _) :: [] ->
declarations

(Keyframes _ _) :: [] ->
(Keyframes name steps) :: [] ->
declarations

(Viewport _) :: [] ->
Expand Down
25 changes: 25 additions & 0 deletions src/Css/Structure/Output.elm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ prettyPrintDeclaration declaration =
in
"@media " ++ query ++ " {\n" ++ indent blocks ++ "\n}"

Keyframes name steps ->
let
prettyPrintStep ( step, props ) =
(toString step)
++ "% {\n"
++ (prettyPrintProperties props |> indentLines)
++ "\n}"
in
"@keyframes "
++ name
++ " {\n"
++ (List.map prettyPrintStep steps
|> List.reverse
|> String.join "\n"
|> indentLines
)
++ "\n}"

_ ->
Debug.crash "not yet implemented :x"

Expand Down Expand Up @@ -167,6 +185,13 @@ indent str =
" " ++ str


indentLines : String -> String
indentLines =
String.lines
>> List.map ((++) " ")
>> String.join "\n"


prettyPrintProperties : List Property -> String
prettyPrintProperties properties =
properties
Expand Down
40 changes: 40 additions & 0 deletions tests/Animations.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Animations exposing (all)

import Test exposing (..)
import Expect
import TestUtil exposing (prettyPrint)
import Css exposing (..)
import Css.Colors exposing (..)


all : Test
all =
describe "animations"
[ animations ]


animations : Test
animations =
describe "Animations"
[ test "keyframes" <|
\() ->
stylesheet
[ keyframes "foo"
[ ( 0, [ backgroundColor red ] )
, ( 50, [ backgroundColor blue ] )
, ( 100, [ backgroundColor yellow ] )
]
]
|> prettyPrint
|> Expect.equal """@keyframes foo {
0% {
background-color: #FF4136;
}
50% {
background-color: #0074D9;
}
100% {
background-color: #FFDC00;
}
}"""
]
2 changes: 2 additions & 0 deletions tests/Tests.elm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Fixtures
import Properties
import Selectors
import Colors
import Animations


all : Test
Expand Down Expand Up @@ -43,6 +44,7 @@ all =
, Selectors.all
, Arithmetic.all
, backgrounds
, Animations.all
]


Expand Down

0 comments on commit 51ccf72

Please sign in to comment.