Commit Graph

414 Commits

Author SHA1 Message Date
Natalie Weizenbaum
390d0ac482 Remove another outdated TODO. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
265a4c8946 Preserve newlines through @extend. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
99c83a5834 Partial selector newline support.
In particular, newlines in selectors lists are now preserved during
parent selector resolution and emitted by the serializer. The output
matches Ruby Sass, but I'm not sure it's actually the best possible.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
98c5ffae9a Fix nested selector ordering. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
79630cdc47 Properly serialize parent selectors. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
25c16b975e Fix a parser bug. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
ae2ab6ec58 Remove outdated TODO. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f460ebb2a9 Parse functions -> constructors 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
4289011a84 Parse em properly. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
b47067ea4e Add if(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
1987d0b055 Add unique-id(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
af4234aedd Add call(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
ad1bbcc9bc Add comparable(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
69b61b1dc9 Fix unit stuff. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
4a42f948f9 Add unit(), unitless(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
138bb6bace Add type-of. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
0b7a448d76 Add function-exists(), mixin-exists(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
a9122ad162 Add variable-exists(), global-variable-exists(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8455903435 Add feature-exists(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
44d9ee54a9 Add selector-parse(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
534ac2e511 Add simple-selectors(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
046e17da17 Add is-superselector(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
754b1895ac Add selector-unify(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
a993a7667e Add selector-replace(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
63ec19f469 Fix a formatting nit. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f449fa0a98 Fix another extend bug. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
6fc656d260 Fix an extend bug. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
54f4a23d99 Add selector-extend(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
4a4cc3c277 Add selector-append(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
29ff1887a8 Add selector-nest(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
a5c1021035 Tweak function headers. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
5800b9358f Add map-has-key() and keywords(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
643771349f Add map-keys(), map-values(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
7ece4671fc Add map-remove(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
3421172bcb Add map-get(), map-merge(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
216ffece4b Fix some map/list equivalence stuff. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f3a4b07212 Fix fuzzyHashCode() to always return an int. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
6a949b027a Add index(), list-separator(), is-bracketed(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
6debf1e39a Add zip(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f7fbbb075a Add append(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
10d7da9d73 isBracketed -> hasBrackets
This is consistent with SassString.hasQuotes.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
4c9751fbb4 Add join(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
582afa3a20 Add set-nth(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
7418b78902 Add nth(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
d316f828fa Add length(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
816e32f08b Add Environment.defineFunction(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
158ac11d43 Add TODOs for persistent data structures. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8f9d2d3207 Add random(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
aed2a99234 Add max() and min(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
0bf39726a3 Add round(), ceil(), floor(), abs(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
b0a675ab14 Add percentage(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
e1a6178ced Add to-upper-case() and to-lower-case(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8d5228b368 Add str-slice(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
ff2d9f89e9 Add str-index(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8fd5818977 Add str-insert(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
41eec3c779 Add str-length(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
b8d89ad80d Add quoted(), unquoted(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
fb045bb955 Add ie-hex-str(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
7e0f642cd1 Use fuzzy rounding for consistency with Ruby Sass. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
4ff89b1aff Add change-color(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
3cbbe101f1 Add scale-color(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
fc4e6afad8 Add adjust-color(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8b8f6bfbee Add opacify() et al 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
04b012befe Add opacity(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
09a8198a01 Add alpha(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f499f31b64 Add grayscale(), complement(), invert(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
5873083110 Add lighten(), darken(), saturate(), desaturate(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
d2591122db Add adjust-hue(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
b529ac643c Add hsla(), hue(), saturation(), and lightness(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
30df7507c8 Add hsl(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
84d1339043 Parse function declaration parameters. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
dd85c34ae2 Use fuzzy comparisons for number operations.
Also implement ==, which apparently didn't exist for numbers yet.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
dbd55e16d8 Add red(), green(), and blue(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
048d7cff33 Add mix(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
227329f9c3 Add rgba().
This also adds built-in function overloading. This adds some extra
layers to the default function-call logic which could be avoided by
handling overloading purely in the callbacks of functions that require
it, but it's not clear how to share logic gracefully between the perform
visitor and function helpers.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
5cc5bf1914 Add rgb(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
dd8a0efd66 Add an ArgumentList class. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
e4e445b8d4 Fix argument parsing. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
8bbaf46fe6 Use the tuple package. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
c9af638f54 Support for units 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
bacc1c4529 Unify strings and identifiers.
The separation makes sense conceptually, but it would make string
functions a lot harder to write.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
9ac48fbc05 Add support for binary operations. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
7fb7804a52 Refactor list parsing.
Moving all list parsing into a single method with a giant switch will
make it possible to parse binary operations there in the future.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
33f56f31ff _spaceListOrValue -> _spaceListOrExpression 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
bcaaa1103f UnaryOperatorExpression -> UnaryOperationExpression 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
5d71ac78b9 Indented syntax parser. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
bca0907897 ignoreComments() -> whitespace() 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
aab7c741c7 Refactor comment statement parsing. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
3a2b7ca9df Split the parser up.
There are now separate parsers for selectors and at-root queries, since
those are parsed independently of the main stylesheet. The Parser class
contains utilities that are useful across different parsers.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
3329ba80b8 Re-add CssValue.toString(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
af61587807 Better known identifier parsing. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
913e81faaa Remove fixed TODOs. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
bde9c353f5 Further improve list serialization. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
ee7c3e5c3c Support expression &. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
db0cea9870 Fix some bugs with combinators. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
5e23c99b22 Get rid of more redundant toString() definitions. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
53635def75 Fix map serialization. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
232ee90b4d Fix parenthesis parsing. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
efd336dd20 Support null. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
1832879845 Support @each 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
e873242ac4 Support @while 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
80f0afb484 Support @for. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
202fcad40f Name all at-rules *Rule. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
f85b21a3c3 Support @error 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
69aabed63d Support @warn 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
da1cef3f6f Move advanced list paren logic to serializer. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
7a5029b5ae Support @debug. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
e8fdcc586a Add runtime exceptions and stack traces. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
60b8aae55f No more throwing strings. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
da7a58645e Add a proper exception class. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
987eee5c0a Support @extend !optional. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
507ae1790a ExtendRule -> Extend 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
3fb3ae1f3b Throw if an extend doesn't match. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
92f657db46 Don't emit placeholders. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
673db13d51 Move emptiness-checking to the serializer.
We can't actually know if a rule will be empty until we've evaluated the
entire stylesheet, since it might contain a placeholder that may or may
not be extended.
2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
cc56ea0f13 Implement CssNode.toString() using toCss(). 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
e607e7914f Support @at-root. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
17c5814a15 Fix a formatting nit. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
0f82f72fa4 Fix media query parsing. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
d3d4427028 Fix quoted strings in interpolation. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
0fe62a04a6 @supports support. 2016-09-30 12:41:41 -07:00
Natalie Weizenbaum
07a79e4557 Fix color serialization. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
7b5f8c7284 Fix an @extend bug. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
def4ffea0f Fix a selector-parsing bug. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
9b183ed32c Clean up output of childless rules. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
83c8c1a9b7 Add args support.
It doesn't really do anything yet.
2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
80e111eb56 Properly parse whitespace-only files. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
e2eb590ce6 Set precision to 10. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
cdc3065dfb Make visitor interfaces wholly abstract. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
ffb85921cb Buggy implementation of CSS @import. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
47929dfde3 Support @import.
CSS @import is still unsupported.
2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
f1ce6ea599 Format all code. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
faa86b697c Make (most) spans mandatory.
Arguments are still optional since they may be constructed for
user-defined arguments.
2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
82aca21682 Add @if. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
c4cda30bc0 Validate dynamic children. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
0f20b58044 Clean up at-rule parsing. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
0573fa7709 @content support. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
3b3e3046fd Fix variable parsing. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
ceacb840b3 Fix function/mixin scoping. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
631f0870ac Make Environment.scope scope mixins and functions. 2016-08-30 15:51:23 -07:00
Natalie Weizenbaum
bbaf8a5a2f Run arguments in the right environment. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
fcaa696f02 Re-organize AST files. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
6951774d70 Add a CallableInvocation interface. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
32db51f005 Add built-in functions. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
709f564f21 Refactor _runCallable. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
cba5881eb4 Remove redundant parameters. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
4e0a511570 Add mixins. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
7692d61ef4 Fix Environment.setFunction(). 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
64c2453a35 Fix printing of childless at-rules. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
0498e8a95c InterpolationExpression -> Interpolation 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
860f761c27 "Separator independent" -> "normalized" 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
50912350af Add support for functions.
Argument list objects are still not implemented.
2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
cbe3709914 Default values for boolean parameters. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
43027bf84a Fix list parsing. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
7bac6790af Merge both perform visitors together. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
77dd5c1e84 Make underscores and dashes equal. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
113b4787ed Stylistic consistency. 2016-08-30 15:51:22 -07:00
Natalie Weizenbaum
977bb9c3d2 Use unvendor() in Pseudo.
Also, fix unvendor().
2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
02a9780b43 Fix selector pseudo parsing. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
55e81951b2 Stringify the parent selector normally. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
64e4954656 Fix some pseudo bugs. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
0a0f7837b0 Parent selector support. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
e58af84cc6 Fix an analysis error. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
cf086471c6 Nested properties. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
dbf2c18ae6 Move selector serialization to the visitor. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
ce979fba35 Remove a TODO that's already been done. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
6c0a2547b0 Re-organize visitors. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
a206fdcddb Fix analysis. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
3108dc46e9 Add a default Value.toString(). 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
0b7ea7d8c9 Add nested list parenthsization. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
9f2f32c7e4 Fix comment formatting. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
6c6bd715ee Add maps. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
e38d290191 Fix analysis. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
4f4188fd12 Add StringExpression.asInterpolation. 2016-08-30 15:51:21 -07:00
Natalie Weizenbaum
8fa603feda Parse psuedo selector arguments. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
98682b67a8 Add support for custom properties. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
dda3a3d45c _declarationValue -> _declarationExpression
"Declaration value" already means something different.
2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
a2d645ee73 Add bracketed lists. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
2fb2e4a9a6 Fix Pseudo.*Specificity. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
e0333b303c Get simple extension working. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
69221190e7 Enable @extend.
Still tons of runtime errors.
2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
69a431c7bf Fix all analysis. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
8d396cc465 Add _mustUnify. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
b9c6a1dc4e _isParentSuperselector => complexIsParentSuperselector 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
a5a81382ac Add _paths. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
51c8213a6d Add _selectorPseudoIsSuperselector. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
b5b4cd5a8b Add PseudoSelector.normalizedName. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
2b120f005d Fix some hints. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
25f625af13 Fix most strong-mode errors. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
1ea3619d93 some analysis fixes 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
d5b029de9b Some extend infra juggling. 2016-08-30 15:51:20 -07:00
Natalie Weizenbaum
16ace03246 Add Extender.addExtension 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
3c0e8cbd86 Source tracking.
This is actually way simpler than the Ruby Sass version, but I think it
should obey the First Law just as well.
2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
a88670da4e Add selector specificity. 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
efaf64020f Add an LCS implementation. 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
ab2d8ae3f3 unify complex 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
9caecbe0d0 Simplify names. 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
ec5eb46747 Compound/Simple unification. 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
946c6c814c More extend stuff 2016-08-30 15:51:19 -07:00
Natalie Weizenbaum
5e93ee8667 Extend WIP 2016-08-30 15:51:19 -07:00