Skip to content

Commit 51ccf72

Browse files
committed
Add support for css animations (@Keyframes)
1 parent e9adc45 commit 51ccf72

File tree

8 files changed

+148
-14
lines changed

8 files changed

+148
-14
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"dependencies": {
3333
"chalk": "1.1.1",
3434
"commander": "2.9.0",
35+
"elm-test": "^0.18.2",
3536
"node-elm-compiler": "2.3.2",
3637
"tmp": "0.0.28"
3738
},

src/Css.elm

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ module Css
462462
, projection
463463
, tv
464464
, mediaQuery
465+
, keyframes
465466
, src
466467
, qt
467468
, fontFamilies
@@ -615,7 +616,7 @@ module Css
615616
@docs screen, tv, projection, print
616617
617618
# Properties
618-
@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
619+
@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
619620
620621
# Values
621622
@@ -6390,6 +6391,25 @@ withMedia =
63906391
Preprocess.WithMedia
63916392

63926393

6394+
{-| Animation's @keyframe
6395+
6396+
keyframes "animationName"
6397+
[( 0
6398+
, [ backgroundColor blue
6399+
]
6400+
)
6401+
[( 100
6402+
, [ backgroundColor red
6403+
]
6404+
)
6405+
]
6406+
6407+
-}
6408+
keyframes : String -> List ( Float, List Mixin ) -> Snippet
6409+
keyframes name steps =
6410+
Preprocess.Snippet ([ Preprocess.Keyframes name steps ])
6411+
6412+
63936413

63946414
{- FONT PROPERTIES -}
63956415

src/Css/Preprocess.elm

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ type SnippetDeclaration
5252
| DocumentRule String String String String StyleBlock
5353
| PageRule String (List Property)
5454
| FontFace (List Property)
55-
| Keyframes String (List Structure.KeyframeProperty)
55+
| Keyframes String (List KeyframeStep)
5656
| Viewport (List Property)
5757
| CounterStyle (List Property)
5858
| FontFeatureValues (List ( String, List Property ))
5959

6060

61+
type alias KeyframeStep =
62+
( Float, List Mixin )
63+
64+
6165
type StyleBlock
6266
= StyleBlock Structure.Selector (List Structure.Selector) (List Mixin)
6367

src/Css/Preprocess/Resolve.elm

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Structure data structures and gathering warnings along the way.
55
-}
66

77
import String
8+
import List
89
import Css.Preprocess as Preprocess exposing (SnippetDeclaration, Snippet(Snippet), Mixin(AppendProperty, ExtendSelector, NestSnippet), unwrapSnippet)
910
import Css.Structure as Structure exposing (mapLast)
1011
import Css.Structure.Output as Output
@@ -141,11 +142,43 @@ resolveFontFace fontFaceProperties =
141142
}
142143

143144

144-
resolveKeyframes : String -> List Structure.KeyframeProperty -> DeclarationsAndWarnings
145-
resolveKeyframes str properties =
146-
{ declarations = [ Structure.Keyframes str properties ]
147-
, warnings = []
148-
}
145+
resolveKeyframes : String -> List Preprocess.KeyframeStep -> DeclarationsAndWarnings
146+
resolveKeyframes name steps =
147+
let
148+
( warnings, keyframes ) =
149+
extractWarningsFromKeyframes steps ( [], [] )
150+
in
151+
{ declarations = [ Structure.Keyframes name keyframes ]
152+
, warnings = warnings
153+
}
154+
155+
156+
extractWarningsFromKeyframes : List Preprocess.KeyframeStep -> ( List String, List Structure.KeyframeStep ) -> ( List String, List Structure.KeyframeStep )
157+
extractWarningsFromKeyframes ls ( warnings, steps ) =
158+
case ls of
159+
( step, mixins ) :: tl ->
160+
if step < 0 || step > 100 then
161+
-- keyframe is dropped
162+
extractWarningsFromKeyframes tl
163+
( "Keyframe must be between 0 and 100 (those are percents)." :: warnings
164+
, steps
165+
)
166+
else
167+
let
168+
props =
169+
Preprocess.toPropertyPairs mixins
170+
|> List.map pairToProperty
171+
172+
pairToProperty ( k, v ) =
173+
{ important = False
174+
, key = k
175+
, value = v
176+
}
177+
in
178+
extractWarningsFromKeyframes tl ( warnings, ( step, props ) :: steps )
179+
180+
[] ->
181+
( warnings, steps )
149182

150183

151184
resolveViewport : List Preprocess.Property -> DeclarationsAndWarnings
@@ -218,8 +251,8 @@ toDeclarations snippetDeclaration =
218251
Preprocess.FontFace fontFaceProperties ->
219252
resolveFontFace fontFaceProperties
220253

221-
Preprocess.Keyframes str properties ->
222-
resolveKeyframes str properties
254+
Preprocess.Keyframes name steps ->
255+
resolveKeyframes name steps
223256

224257
Preprocess.Viewport viewportProperties ->
225258
resolveViewport viewportProperties

src/Css/Structure.elm

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ type Declaration
5353
| DocumentRule String String String String StyleBlock
5454
| PageRule String (List Property)
5555
| FontFace (List Property)
56-
| Keyframes String (List KeyframeProperty)
56+
| Keyframes String (List KeyframeStep)
5757
| Viewport (List Property)
5858
| CounterStyle (List Property)
5959
| FontFeatureValues (List ( String, List Property ))
@@ -121,8 +121,8 @@ type SelectorCombinator
121121
| Descendant
122122

123123

124-
type alias KeyframeProperty =
125-
String
124+
type alias KeyframeStep =
125+
( Float, List Property )
126126

127127

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

144+
(Keyframes name steps) :: [] ->
145+
[ Keyframes name
146+
(mapLast (appendPropertyToKeyframe property) steps)
147+
]
148+
144149
-- TODO
145150
_ :: [] ->
146151
declarations
@@ -149,7 +154,6 @@ appendProperty property declarations =
149154
--| DocumentRule String String String String StyleBlock
150155
--| PageRule String (List Property)
151156
--| FontFace (List Property)
152-
--| Keyframes String (List KeyframeProperty)
153157
--| Viewport (List Property)
154158
--| CounterStyle (List Property)
155159
--| FontFeatureValues (List ( String, List Property ))
@@ -162,6 +166,11 @@ withPropertyAppended property (StyleBlock firstSelector otherSelectors propertie
162166
StyleBlock firstSelector otherSelectors (properties ++ [ property ])
163167

164168

169+
appendPropertyToKeyframe : Property -> KeyframeStep -> KeyframeStep
170+
appendPropertyToKeyframe prop ( step, props ) =
171+
( step, prop :: props )
172+
173+
165174
extendLastSelector : RepeatableSimpleSelector -> List Declaration -> List Declaration
166175
extendLastSelector selector declarations =
167176
case declarations of
@@ -229,7 +238,7 @@ extendLastSelector selector declarations =
229238
(FontFace _) :: [] ->
230239
declarations
231240

232-
(Keyframes _ _) :: [] ->
241+
(Keyframes name steps) :: [] ->
233242
declarations
234243

235244
(Viewport _) :: [] ->

src/Css/Structure/Output.elm

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,24 @@ prettyPrintDeclaration declaration =
6969
in
7070
"@media " ++ query ++ " {\n" ++ indent blocks ++ "\n}"
7171

72+
Keyframes name steps ->
73+
let
74+
prettyPrintStep ( step, props ) =
75+
(toString step)
76+
++ "% {\n"
77+
++ (prettyPrintProperties props |> indentLines)
78+
++ "\n}"
79+
in
80+
"@keyframes "
81+
++ name
82+
++ " {\n"
83+
++ (List.map prettyPrintStep steps
84+
|> List.reverse
85+
|> String.join "\n"
86+
|> indentLines
87+
)
88+
++ "\n}"
89+
7290
_ ->
7391
Debug.crash "not yet implemented :x"
7492

@@ -167,6 +185,13 @@ indent str =
167185
" " ++ str
168186

169187

188+
indentLines : String -> String
189+
indentLines =
190+
String.lines
191+
>> List.map ((++) " ")
192+
>> String.join "\n"
193+
194+
170195
prettyPrintProperties : List Property -> String
171196
prettyPrintProperties properties =
172197
properties

tests/Animations.elm

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module Animations exposing (all)
2+
3+
import Test exposing (..)
4+
import Expect
5+
import TestUtil exposing (prettyPrint)
6+
import Css exposing (..)
7+
import Css.Colors exposing (..)
8+
9+
10+
all : Test
11+
all =
12+
describe "animations"
13+
[ animations ]
14+
15+
16+
animations : Test
17+
animations =
18+
describe "Animations"
19+
[ test "keyframes" <|
20+
\() ->
21+
stylesheet
22+
[ keyframes "foo"
23+
[ ( 0, [ backgroundColor red ] )
24+
, ( 50, [ backgroundColor blue ] )
25+
, ( 100, [ backgroundColor yellow ] )
26+
]
27+
]
28+
|> prettyPrint
29+
|> Expect.equal """@keyframes foo {
30+
0% {
31+
background-color: #FF4136;
32+
}
33+
50% {
34+
background-color: #0074D9;
35+
}
36+
100% {
37+
background-color: #FFDC00;
38+
}
39+
}"""
40+
]

tests/Tests.elm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Fixtures
1010
import Properties
1111
import Selectors
1212
import Colors
13+
import Animations
1314

1415

1516
all : Test
@@ -43,6 +44,7 @@ all =
4344
, Selectors.all
4445
, Arithmetic.all
4546
, backgrounds
47+
, Animations.all
4648
]
4749

4850

0 commit comments

Comments
 (0)