Add commas between PercentageTerms in keyframes (#151)

Fixes #105

A previous attempt unconditionally added commas between `PercentageTerm`
values, but those terms can also show up in places where commas are not
expected.

Add state on the visitor to track whether we are in the context of a
`keyframes` rule. I _think_ these are the only rules which need comma
separated terms, and that it can't be nested in a way where naively
reverting back to `false` after leaving should cause any problems.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18907e1..cc5e34a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.17.3-dev
+
+- Add commas between PercentageTerms in keyframe rules.
+
 ## 0.17.2
 
 - Fixed a crash caused by `min()`, `max()` and `clamp()` functions that contain
diff --git a/lib/src/css_printer.dart b/lib/src/css_printer.dart
index 0f5b822..3218f39 100644
--- a/lib/src/css_printer.dart
+++ b/lib/src/css_printer.dart
@@ -8,6 +8,7 @@
 class CssPrinter extends Visitor {
   StringBuffer _buff = StringBuffer();
   bool prettyPrint = true;
+  bool _isInKeyframes = false;
 
   /// Walk the [tree] Stylesheet. [pretty] if true emits line breaks, extra
   /// spaces, friendly property values, etc., if false emits compacted output.
@@ -217,9 +218,11 @@
     emit('$_newLine${node.keyFrameName} ');
     node.name!.visit(this);
     emit('$_sp{$_newLine');
+    _isInKeyframes = true;
     for (final block in node._blocks) {
       block.visit(this);
     }
+    _isInKeyframes = false;
     emit('}');
   }
 
@@ -624,6 +627,11 @@
         var previous = expressions[i - 1];
         if (previous is OperatorComma || previous is OperatorSlash) {
           emit(_sp);
+        } else if (previous is PercentageTerm &&
+            expression is PercentageTerm &&
+            _isInKeyframes) {
+          emit(',');
+          emit(_sp);
         } else {
           emit(' ');
         }
diff --git a/pubspec.yaml b/pubspec.yaml
index a71911b..035ae11 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: csslib
-version: 0.17.2
+version: 0.17.3-dev
 
 description: A library for parsing and analyzing CSS (Cascading Style Sheets)
 repository: https://github.com/dart-lang/csslib
diff --git a/test/keyframes_test.dart b/test/keyframes_test.dart
new file mode 100644
index 0000000..835c896
--- /dev/null
+++ b/test/keyframes_test.dart
@@ -0,0 +1,22 @@
+import 'package:csslib/src/messages.dart';
+import 'package:test/test.dart';
+
+import 'testing.dart';
+
+void main() {
+  test('keyframes', () {
+    final input =
+        r'@keyframes ping { 75%, 100% { transform: scale(2); opacity: 0; } }';
+    var errors = <Message>[];
+    var stylesheet = compileCss(input, errors: errors, opts: options);
+    expect(errors, isEmpty);
+    final expected = r'''
+@keyframes ping {
+  75%, 100% {
+  transform: scale(2);
+  opacity: 0;
+  }
+}''';
+    expect(prettyPrint(stylesheet), expected);
+  });
+}