diff --git a/.gitignore b/.gitignore index a680deb6..6a22cf4f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,10 @@ node_modules !node_modules/mocha/LICENCE !node_modules/chai/chai.js !node_modules/chai-LICENCE -web-animations-*.min.js -web-animations-*.min.js.map -web-animations.min.js -web-animations.min.js.map + inter-* +*.min.js* + *~ sauce_connect.log +test.html diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..cda89c08 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test/web-platform-tests"] + path = test/web-platform-tests + url = https://github.com/web-platform-tests/wpt.git diff --git a/.travis-setup.sh b/.travis-setup.sh index e688e4f1..00ca7389 100755 --- a/.travis-setup.sh +++ b/.travis-setup.sh @@ -26,6 +26,9 @@ uname -a cat /etc/lsb-release npm install +# npm may update the package-lock.json. Revert this to avoid failing grunt-checkrepo. +git checkout HEAD package-lock.json + npm install -g grunt-cli sudo apt-get update --fix-missing @@ -62,31 +65,33 @@ Chrome) sudo dpkg --install $CHROME || sudo apt-get -f install which google-chrome ls -l `which google-chrome` - + if [ -f /opt/google/chrome/chrome-sandbox ]; then export CHROME_SANDBOX=/opt/google/chrome/chrome-sandbox else export CHROME_SANDBOX=$(ls /opt/google/chrome*/chrome-sandbox) fi - + # Download a custom chrome-sandbox which works inside OpenVC containers (used on travis). sudo rm -f $CHROME_SANDBOX sudo wget https://googledrive.com/host/0B5VlNZ_Rvdw6NTJoZDBSVy1ZdkE -O $CHROME_SANDBOX sudo chown root:root $CHROME_SANDBOX; sudo chmod 4755 $CHROME_SANDBOX sudo md5sum $CHROME_SANDBOX - + google-chrome --version ;; Firefox) sudo rm -f /usr/local/bin/firefox case $VERSION in + stable) + ;; beta) yes "\n" | sudo add-apt-repository -y ppa:mozillateam/firefox-next ;; - aurora) - yes "\n" | sudo add-apt-repository -y ppa:ubuntu-mozilla-daily/firefox-aurora - ;; + # TODO(alancutter): Add support for firefox-aurora. + # This will need to download the binary manually as the ubuntu-mozilla-daily + # ppa doesn't support the version of linux that Travis uses. esac sudo apt-get update --fix-missing sudo apt-get install firefox diff --git a/.travis.yml b/.travis.yml index 83979d83..b3755942 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,6 @@ +dist: xenial +services: xvfb language: node_js - -node_js: - - "0.10" - -install: - - BROWSER="Firefox-aurora" ./.travis-setup.sh - -before_script: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start +node_js: "10.15.3" +install: BROWSER="Firefox-stable" ./.travis-setup.sh +script: xvfb-run -a npm test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..40ac14dc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,140 @@ +## Developer instructions + +### Setup + +1. Fork web-animations/web-animations-js. +1. `git clone git@github.com:$GITHUB_USER/web-animations-js.git` +1. `git submodule update --init --recursive` (Necessary for running tests.) +1. Install [node](https://nodejs.org/en/) and make sure `npm` is in your $PATH +1. Run `npm install` in the respository to pull in development dependencies. +1. Run `npm install -g grunt-cli` to get the build tools for the command line. + +### Contributing + +Note that development should occur against the `dev` branch, not `master`. This +is the default target for pull requests. + +1. In your fork of web-animations-js, `git checkout dev` or create a new branch whose parent is dev. +1. Run `grunt` to build the polyfill. +1. Run `grunt test` to run polyfill and web-platform-tests tests. +1. Commit changes to your fork. +1. Create a pull request from your fork of web-animations-js to + [web-animations/web-animations-js/dev](https://github.com/web-animations/web-animations-js/tree/dev). +1. Ensure that you've signed the [Google Contributor License Agreement](https://cla.developers.google.com/clas). + + +## Debugging tests + +You can run the tests in an interactive mode with `grunt debug`. This starts the +Karma server once for each polyfill target for each test framework. +Navigate to `http://localhost:9876/debug.html` to open the test runner in your +browser of choice, all test results appear in the Javascript console. +Test failures can be accessed via `window.failures` and `window.formattedFailures` +once the tests have completed. + +The polyfill target and tests can be specified as arguments to the `debug` task. +Example: `grunt debug:web-animations-next:test/web-platform-tests/web-animations/animation/pause.html` +Multiple test files may be listed with comma separation. Specifying files will output their URL in the command line. +Example: `http://localhost:9876/base/test/web-platform-tests/web-animations/animation/pause.html` + + +## Design notes + +[Design diagrams](https://drive.google.com/folderview?id=0B9rpPoIDv3vTNlZxOVp6a2tNa1E&usp=sharing) + + +## Publishing a release + +1. Clone a fresh copy of [web-animations-js](https://github.com/web-animations/web-animations-js). + +1. Make sure you are on the `dev` branch. + + ```sh + git checkout dev + ``` + +1. Determine the version number for the release + + * Increment the first number and reset others to 0 when there are large breaking changes + * Increment the second number and reset the third to 0 when there are significant new, but backwards compatible features + * Otherwise, increment the third number + +1. Add versioned release notes to `History.md`, for example: + + ### 3.13.37 — *November 1, 2001* + + * Fixed a bug where nothing worked + + Use the following to generate a summary of commits, but edit the list to contain only + relevant information. + + git log --first-parent `git describe --tags --abbrev=0 master`..dev --pretty=format:" * %s" + +1. Specify the new version inside `package.json` (for NPM), for example: + + ```js + "version": "3.13.37", + ``` + +1. Build the polyfill with `npm install && grunt` then update `docs/experimental.md`'s Build Target Comparison with the current gzipped sizes. + +1. Commit and push the above changes to web-animations-js/dev. + + ```sh + # Create a commit with above changes + git push origin dev + ``` + +1. Merge to local master branch: + + ```sh + git checkout master + git merge dev --no-edit --quiet + ``` + +1. Build and commit minified JavaScript files. + + ```sh + npm install + grunt + # Optional "grunt test" to make sure everything still passes. + git add -f *.min.js{,.map} + git rm --ignore-unmatch .gitignore + git commit -m 'Add build artifacts from '`cat .git/refs/heads/dev` + git push origin master + ``` + +1. Draft a [new release](https://github.com/web-animations/web-animations-js/releases). + + * For the **tag version**, put the new version number of this release. + * For the **target**, select "master". + * For the **title**, look at previous releases for examples. + * For the **description**, copy the release notes from `History.md` added in step #2. + +1. Once you've pushed to web-animations-js, run `npm publish` from that checked-out folder + + To do this, you'll need to be a collaborator [on the NPM project](https://www.npmjs.com/package/web-animations-js), or have a collaborator help you. + +1. If there are any breaking changes to the API in this release you must notify web-animations-changes@googlegroups.com. + + Only owners of the group may post to it so you may need to request ownership or ask someone to post it for you. + +## Testing architecture + +This is an overview of what happens when `grunt test` is run. + +1. Polyfill tests written in mocha and chai are run. + 1. grunt creates a karma config with mocha and chai adapters. + 1. grunt adds the test/js files as includes to the karma config. + 1. grunt starts the karma server with the config and waits for the result. + 1. The mocha adaptor runs the included tests and reports the results to karma. + 1. karma outputs results to the console and returns the final pass/fail result to grunt. +1. web-platform-tests/web-animations tests written in testtharness.js are run. + 1. grunt creates a karma config with karma-testharness-adaptor.js included. + 1. grunt adds the web-platform-tests/web-animations files to the custom testharnessTests config in the karma config. + 1. grunt adds failure expectations to the custom testharnessTests config in the karma config. + 1. grunt starts the karma server with the config and waits for the result. + 1. The testharness.js adaptor runs the included tests (ignoring expected failures) and reports the results to karma. + 1. karma outputs results to the console and returns the final pass/fail result to grunt. +1. grunt exits successfully if both test runs passed. + diff --git a/Gruntfile.js b/Gruntfile.js index 842d2ac8..bac72207 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -56,7 +56,7 @@ module.exports = function(grunt) { var record = config.uglify[target]; record.options.sourceMapIn = source + '.map'; record.options.banner = grunt.file.read('templates/boilerplate'); - record.options.wrap = true; + record.options.enclose = true; record.options.compress.dead_code = true; record.options.mangle = { eval: true }; return name; @@ -116,31 +116,33 @@ module.exports = function(grunt) { WEB_ANIMATIONS_TESTING: false }; - function buildWebAnimations1(target) { + function build(target) { var config = targetConfig[target]; - return genTarget(target).concat([ - concat(config.scopeSrc.concat(config.sharedSrc).concat(config.webAnimations1Src), 'inter-raw-' + target + '.js', concatDefines), - guard('inter-raw-' + target + '.js', 'inter-' + target + '.js'), - compress('inter-' + target + '.js', target + '.min.js', concatDefines) - ]); - } - - function buildWebAnimationsNext(target) { - var config = targetConfig[target]; - return genTarget(target).concat([ + var steps = [ concat(config.scopeSrc.concat(config.sharedSrc), 'inter-' + target + '-preamble.js', concatDefines), - concat(config.webAnimations1Src, 'inter-component-' + target + 'web-animations-1.js', concatDefines), - guard('inter-component-' + target + 'web-animations-1.js', 'inter-guarded-' + target + '-web-animations-1.js'), - concat(config.webAnimationsNextSrc, 'inter-component-' + target + '.js', concatDefines), - concatWithMaps(['inter-' + target + '-preamble.js', 'inter-guarded-' + target + '-web-animations-1.js', 'inter-component-' + target + '.js'], - 'inter-' + target + '.js'), + concat(config.webAnimations1Src, 'inter-component-' + target + '-web-animations-1.js', concatDefines), + guard('inter-component-' + target + '-web-animations-1.js', 'inter-guarded-' + target + '-web-animations-1.js'), + concat(config.webAnimations1BonusSrc, 'inter-bonus-' + target + '.js', concatDefines), + ]; + var filenames = [ + 'inter-' + target + '-preamble.js', + 'inter-guarded-' + target + '-web-animations-1.js', + 'inter-bonus-' + target + '.js', + ]; + if (config.webAnimationsNextSrc.length > 0) { + steps.push(concat(config.webAnimationsNextSrc, 'inter-component-' + target + '.js', concatDefines)); + filenames.push('inter-component-' + target + '.js'); + } + steps.push( + concatWithMaps(filenames, 'inter-' + target + '.js'), compress('inter-' + target + '.js', target + '.min.js', concatDefines) - ]); + ); + return genTarget(target).concat(steps); } - grunt.registerTask('web-animations', buildWebAnimations1('web-animations')); - grunt.registerTask('web-animations-next', buildWebAnimationsNext('web-animations-next')); - grunt.registerTask('web-animations-next-lite', buildWebAnimationsNext('web-animations-next-lite')); + grunt.registerTask('web-animations', build('web-animations')); + grunt.registerTask('web-animations-next', build('web-animations-next')); + grunt.registerTask('web-animations-next-lite', build('web-animations-next-lite')); var testTargets = {'web-animations': {}, 'web-animations-next': {}}; @@ -180,30 +182,124 @@ module.exports = function(grunt) { } }, test: testTargets, + debug: testTargets, sauce: testTargets, }); - grunt.task.registerMultiTask('test', 'Run tests under Karma', function() { - var done = this.async(); - var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config.js'), {}); - var config = targetConfig[this.target]; - karmaConfig.files = ['test/runner.js'].concat(config.src, config.test); - var karmaServer = require('karma').server; - karmaServer.start(karmaConfig, function(exitCode) { - done(exitCode === 0); + function runKarma(configCallback) { + return new Promise(function(resolve) { + var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config.js'), {}); + configCallback(karmaConfig); + new (require('karma').Server)(karmaConfig, function(exitCode) { + resolve(exitCode == 0); + }).start(); + }); + } + + function runTests(task, configCallback, testFilter) { + var done = task.async(); + var config = targetConfig[task.target]; + if (testFilter) { + testFilter = new Set(testFilter.split(',')); + } + + function filterTests(testFiles) { + console.assert(testFiles.length > 0); + if (!testFilter) { + return testFiles; + } + return testFiles.filter(file => testFilter.has(file)); + } + + function runPolyfillTests() { + var testFiles = filterTests(config.polyfillTests); + if (testFiles.length == 0) { + return Promise.resolve(true); + } + + console.info('Running polyfill tests...'); + return runKarma(function(karmaConfig) { + configCallback(karmaConfig); + karmaConfig.plugins.push('karma-mocha', 'karma-chai'); + karmaConfig.frameworks.push('mocha', 'chai'); + karmaConfig.files = ['test/karma-mocha-setup.js'].concat(config.src, testFiles); + }); + } + function runWebPlatformTests(withNativeFallback) { + var testFiles = filterTests(grunt.file.expand(config.webPlatformTests)); + if (testFiles.length == 0) { + return Promise.resolve(true); + } + + var withOrWithout = withNativeFallback ? 'with' : 'without'; + console.info('Running web-platform-tests/web-animations tests for target ' + task.target + ' ' + withOrWithout + ' native fallback...'); + return runKarma(function(karmaConfig) { + configCallback(karmaConfig); + karmaConfig.client.testharnessTests = require('./test/web-platform-tests-expectations.js'); + karmaConfig.client.testharnessTests.testURLList = testFiles; + karmaConfig.client.testharnessTests.target = task.target; + karmaConfig.client.testharnessTests.withNativeFallback = withNativeFallback; + karmaConfig.files.push('test/karma-testharness-adapter.js'); + var servedFiles = [ + 'test/web-platform-tests/resources/**', + 'test/web-platform-tests/web-animations/**', + 'test/resources/*', + 'src/**', + '*.js*', + + // TODO(alancutter): Make a separate grunt task for serving these imported Blink tests. + 'test/blink/**', + ]; + for (var pattern of servedFiles) { + karmaConfig.files.push({pattern, included: false, served: true, nocache: true}); + } + }); + } + + var polyfillTestsPassed = false; + var webPlatformTestsWithFallbackPassed = false; + var webPlatformTestsWithoutFallbackPassed = false; + runPolyfillTests().then(success => { + polyfillTestsPassed = success; + }).then(() => runWebPlatformTests(true)).then(success => { + webPlatformTestsWithFallbackPassed = success; + }).then(() => runWebPlatformTests(false)).then(success => { + webPlatformTestsWithoutFallbackPassed = success; + done(polyfillTestsPassed && webPlatformTestsWithFallbackPassed && webPlatformTestsWithoutFallbackPassed); + }).catch(function(error) { + console.error(error); + done(false); }); + } + + grunt.task.registerMultiTask('test', 'Run tests under Karma', function(testFilter) { + runTests(this, function(karmaConfig) { + karmaConfig.singleRun = true; + }, testFilter); + }); + + grunt.task.registerMultiTask('debug', 'Debug tests under Karma', function(testFilter) { + if (testFilter) { + console.log('Test file URLs:'); + for (var testFile of testFilter.split(',')) { + console.log('http://localhost:9876/base/' + testFile); + } + } else { + console.log('Test runner URL: http://localhost:9876/debug.html'); + } + runTests(this, function(karmaConfig) { + karmaConfig.browsers = []; + karmaConfig.singleRun = false; + }, testFilter); }); grunt.task.registerMultiTask('sauce', 'Run tests under Karma on Saucelabs', function() { - var done = this.async(); - var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config-ci.js'), {}); - var config = targetConfig[this.target]; - karmaConfig.files = ['test/runner.js'].concat(config.src, config.test); - karmaConfig.sauceLabs.testName = 'web-animation-next ' + this.target + ' Unit tests'; - var karmaServer = require('karma').server; - karmaServer.start(karmaConfig, function(exitCode) { - done(exitCode === 0); + var target = this.target; + runTests(this, function(karmaConfig) { + karmaConfig.singleRun = true; + karmaConfig.plugins.push('karma-saucelabs-launcher'); + karmaConfig.sauceLabs = {testName: 'web-animation-next ' + target + ' Unit tests'}; }); }); @@ -282,12 +378,18 @@ module.exports = function(grunt) { grunt.file.write(this.target + '.map', outMapGenerator.toString()); }); - grunt.task.registerTask('clean', 'Remove files generated by grunt', function() { - grunt.file.expand('web-animations*').concat(grunt.file.expand('test/runner-*.html')).concat(grunt.file.expand('inter-*')).forEach(function(file) { - grunt.file.delete(file); - grunt.log.writeln('File ' + file + ' removed'); + grunt.task.registerTask('clean', 'Remove files generated by grunt', function(arg) { + var filePatterns = ['inter-*']; + if (arg != 'inter') { + filePatterns.push('*min.js*'); + } + filePatterns.forEach(function(filePattern) { + grunt.file.expand(filePattern).forEach(function(file) { + grunt.file.delete(file); + grunt.log.writeln('File ' + file + ' removed'); + }); }); }); - grunt.task.registerTask('default', ['web-animations', 'web-animations-next', 'web-animations-next-lite', 'gjslint']); + grunt.task.registerTask('default', ['web-animations', 'web-animations-next', 'web-animations-next-lite', 'gjslint', 'clean:inter']); }; diff --git a/History.md b/History.md index 4c50afa4..1d1227fc 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,166 @@ +### 2.3.2 - *June 25 2019* + + * [Fix the wrapping IIFE of the prod bundle.](https://github.com/web-animations/web-animations-js/issues/208) + * [Minor fixes for Closure compilation compatibility.](https://github.com/web-animations/web-animations-js/issues/200) + * [Fixed `Cannot set property _isFinished of # which has only a getter`](https://github.com/web-animations/web-animations-js/issues/165) + +### 2.3.1 - *July 20 2017* + + * Fix [https://github.com/web-animations/web-animations-js/issues/157](missing web-animations.min.js issue) + +### 2.3.0 - *July 20 2017* + + * [Support IE/Edge SVG transforms.](https://github.com/web-animations/web-animations-js/pull/148) + + * [Parse and evaluate calc expressions without eval.](https://github.com/web-animations/web-animations-js/pull/151) + +### 2.2.5 - *April 17 2017* + + * Removed erroneously added *.gz files from release. + +### 2.2.4 - *April 14 2017* + + * [Reverted adding 'use strict' to source files.](https://github.com/web-animations/web-animations-next/pull/124) + +### 2.2.3 - *April 13 2017* + + * [Added HTML import targets.](https://github.com/web-animations/web-animations-js/pull/94) + + * Added support for animating SVG related properties: + * [fill](https://github.com/web-animations/web-animations-next/pull/484) + * [floodColor](https://github.com/web-animations/web-animations-next/pull/484) + * [lightingColor](https://github.com/web-animations/web-animations-next/pull/484) + * [stopColor](https://github.com/web-animations/web-animations-next/pull/484) + * [strokeDashoffset](https://github.com/web-animations/web-animations-js/pull/96) + * [strokeDasharray](https://github.com/web-animations/web-animations-js/pull/120) + + * [Fixed crash when animating non-invertable matrices.](https://github.com/web-animations/web-animations-js/pull/121) + + * [Fixed source maps for Bower installs.](https://github.com/web-animations/web-animations-js/pull/93) + + * [Updated README.md documentation structure.](https://github.com/web-animations/web-animations-next/pull/489) + + * [Added 'use strict' to source files.](https://github.com/web-animations/web-animations-next/pull/488) + +### 2.2.2 - *August 3 2016* + + * [Fixed handling of keyframes with overlapping offsets.](https://github.com/web-animations/web-animations-next/pull/470) + + * [Throw TypeError on invalid keyframe input.](https://github.com/web-animations/web-animations-next/pull/471) + + * [Fixed display and other animation properties being animated.](https://github.com/web-animations/web-animations-next/pull/474) + + * [Throw InvalidStateError when calling play() on reversed infinite animation.](https://github.com/web-animations/web-animations-next/pull/475) + + * [Fixed infinite loop in cubic-bezier timing function.](https://github.com/web-animations/web-animations-next/pull/476) + + * [Fixed idle animations not becoming paused when seeked.](https://github.com/web-animations/web-animations-next/pull/479) + + * [Fixed pause() not rewinding idl animations.](https://github.com/web-animations/web-animations-next/pull/480) + + * [Extended cubic-bezier timing function domain from [0, 1] to (-Infinity, Infinity).](https://github.com/web-animations/web-animations-next/pull/481) + + * [Fixed timing model to handle corner cases involving Infinity and 0 correctly.](https://github.com/web-animations/web-animations-next/pull/482) + + * [Fixed source files missing from npm package.](https://github.com/web-animations/web-animations-next/pull/483) + + * [Improved performance of starting and updating individual animations.](https://github.com/web-animations/web-animations-next/pull/485) + +### 2.2.1 - *April 28 2016* + * [Deprecated invalid timing inputs](https://github.com/web-animations/web-animations-next/pull/437) as they will soon throw [TypeErrors](https://github.com/web-animations/web-animations-next/pull/426) in native browsers. + + For example, this is deprecated and will eventually throw a TypeError: + + element.animate([], { + duration: -1, + iterationStart: -1, + iterations: -1, + easing: 'garbage string', + }); + + * [Fixed polyfill crash in browsers based on Chromium 36 to 46.](https://github.com/web-animations/web-animations-next/pull/434) + + * [Increased cubic-bezier accuracy.](https://github.com/web-animations/web-animations-next/pull/428) + + * [Added support for grad and turn units for angles.](https://github.com/web-animations/web-animations-next/pull/427) + +### 2.2.0 - *April 6 2016* + * Deprecated the use of hyphens in property names. + + For example, this is deprecated: + + element.animate([{'font-size': '0px'}, {'font-size': '10px'}]); + + and this should be used instead: + + element.animate([{fontSize: '0px'}, {fontSize: '10px'}]); + + * Added arbitrary easing capitalisation. + + * Added "id" effect option. (https://drafts.csswg.org/web-animations/#dom-keyframeanimationoptions-id) + + * Added "oncancel" event handler. + + * Added value list keyframe syntax. + + As as alternative to: + + element.animate([{color: 'red'}, {color: 'green'}, {color: 'blue'}]); + + you can now use: + + element.animate({color: ['red', 'green', 'blue']}); + + * Fixed easing TypeError in FireFox Nightly when using groups. + + * Fixed delayed animation updates on Safari and Firefox + + * Fixed infinite recursion when setting onfinish to null. + +### 2.1.4 - *December 1 2015* + * Use `Date.now()` instead of `performace.now()` for mobile Safari. + +### 2.1.3 - *October 12 2015* + * Removed web-animations.min.js.gz + +### 2.1.2 - *July 8 2015* + * Fix a bug where onfinish was being called for GroupEffects before they were finished. + +### 2.1.1 - *July 1 2015* + * Add Animation.timeline getter + * Add AnimationEffect.parent getter + * Make AnimationEffectTiming (returned by AnimationEffect.timing) attributes mutable + * Expose the Animation constructor + * Change custom effects from AnimationEffects to onsample functions. Custom effects should now be created by setting the onsample attribute of a KeyframeEffect. + + For example, this is deprecated: + + var myEffect = new KeyframeEffect( + element, + function(timeFraction, target, effect) { + target.style.opacity = timeFraction; + }, + 1000); + var myAnimation = document.timeline.play(myEffect); + + and this should be used insead: + + var myEffect = new KeyframeEffect(element, [], 1000); + effect.onsample = function(timeFraction, effect, animation) { + effect.target.style.opacity = timeFraction; + }; + var myAnimation = document.timeline.play(myEffect); + +### 2.1.0 - *June 15 2015* + * Fix bug affecting GroupEffects with infinite iteration children + * Add GroupEffect.firstChild and GroupEffect.lastChild + * Add initial values for most CSS properties + * Allow `timeline.play()` to be called with no arguments + * Add AnimationEffect.clone + * Add GroupEffect.append and GroupEffect.prepend + * Add AnimationEffect.remove + * Add Animation.ready and Animation.finished promises + ### 2.0.0 - *April 5 2015* * Improve behavior of group Animation playback rate. diff --git a/README.md b/README.md index e3e7d53a..06a71f1a 100644 --- a/README.md +++ b/README.md @@ -1,161 +1,80 @@ -Quick Start ------------ - -To provide native Chrome Web Animation features (`Element.animate` and Playback -Control) in other browsers, use `web-animations.min.js`. To explore all of the -proposed Web Animations API, use `web-animations-next.min.js`. - What is Web Animations? ----------------------- -Web Animations is a new JavaScript API for driving animated content on the web. -By unifying the animation features of SVG and CSS, Web Animations unlocks -features previously only usable declaratively, and exposes powerful, -high-performance animation capabilities to developers. - -For more details see the -[W3C specification](http://w3c.github.io/web-animations/). - -What is the polyfill? ---------------------- - -The polyfill is a JavaScript implementation of the Web Animations API. It works -on modern versions of all major browsers. For more details about browser -support see . - -Getting Started ---------------- - -Here's a simple example of an animation that scales and changes the opacity of -a `
` over 0.5 seconds. The animation alternates producing a pulsing -effect. - - -
Hello world!
- - -Web Animations supports off-main-thread animations, and also allows procedural -generation of animations and fine-grained control of animation playback. See - for ideas and inspiration! - -Native Fallback ---------------- - -When the polyfill runs on a browser that implements `Element.animate` and -`Animation` Playback Control it will detect and use the underlying native -features. - -Different Build Targets ------------------------ - -### web-animations.min.js - -Tracks the Web Animations features that are supported natively in browsers. -Today that means Element.animate and Playback Control in Chrome. If you’re not -sure what features you will need, start with this. - -### web-animations-next.min.js - -Contains all of web-animations.min.js plus features that are still undergoing -discussion or have yet to be implemented natively. - -### web-animations-next-lite.min.js +A new JavaScript API for driving animated content on the web. By unifying +the animation features of SVG and CSS, Web Animations unlocks features +previously only usable declaratively, and exposes powerful, high-performance +animation capabilities to developers. -A cut down version of web-animations-next, it removes several lesser used -property handlers and some of the larger and less used features such as matrix -interpolation/decomposition. +What is in this repository? +--------------------------- -### Build Target Comparison +A JavaScript implementation of the Web Animations API that provides Web +Animation features in browsers that do not support it natively. The polyfill +falls back to the native implementation when one is available. -| | web-animations | web-animations-next | web-animations-next-lite | -|------------------------|:--------------:|:-------------------:|:------------------------:| -|Size (gzipped) | 12.5kb | 14kb | 10.5kb | -|Element.animate | ✔ | ✔ | ✔ | -|Timing input (easings, duration, fillMode, etc.) for animation effects| ✔ | ✔ | ✔ | -|Playback control | ✔ | ✔ | ✔ | -|Support for animating lengths, transforms and opacity| ✔ | ✔ | ✔ | -|Support for animating other CSS properties| ✔ | ✔ | 🚫 | -|Matrix fallback for transform animations | ✔ | ✔ | 🚫 | -|KeyframeEffect constructor | 🚫 | ✔ | ✔ | -|Simple GroupEffects & SequenceEffects | 🚫 | ✔ | ✔ | -|Custom Effects | 🚫 | ✔ | ✔ | -|Timing input (easings, duration, fillMode, etc.) for groups
| 🚫 | 🚫\* | 🚫 | -|Additive animation | 🚫 | 🚫\* | 🚫 | -|Motion path | 🚫\* | 🚫\* | 🚫 | -|Modifiable keyframe effect timing| 🚫 | 🚫\* | 🚫\* | -|Modifiable group timing | 🚫 | 🚫\* | 🚫\* | -|Usable inline style\*\* | ✔ | ✔ | 🚫 | - -\* support is planned for these features. -\*\* see inline style caveat below. - -Caveats -------- - -Some things won’t ever be faithful to the native implementation due to browser -and CSS API limitations. These include: - -### Inline Style - -Inline style modification is the mechanism used by the polyfill to animate -properties. Both web-animations and web-animations-next incorporate a module -that emulates a vanilla inline style object, so that style modification from -JavaScript can still work in the presence of animations. However, to keep the -size of web-animations-next-lite as small as possible, the style emulation -module is not included. When using this version of the polyfill, JavaScript -inline style modification will be overwritten by animations. -Due to browser constraints inline style modification is not supported on iOS 7 -or Safari 6 (or earlier versions). - -### Prefix handling - -The polyfill will automatically detect the correctly prefixed name to use when -writing animated properties back to the platform. Where possible, the polyfill -will only accept unprefixed versions of experimental features. For example: - - var effect = new KeyframeEffect(elem, {"transform": "translate(100px, 100px)"}, 2000); - -will work in all browsers that implement a conforming version of transform, but - - var effect = new KeyframeEffect(elem, {"-webkit-transform": "translate(100px, 100px)"}, 2000); - -will not work anywhere. - -API and Specification Feedback ------------------------------- +Quick start +----------- -File an issue on GitHub: . -Alternatively, send an email to with subject line -“[web-animations] … message topic …” +Here's a simple example of an animation that fades and scales a `
`. +[Try it as a live demo.](http://jsbin.com/yageyezabo/edit?html,js,output) + +```html + + + + +
Hello world!
+ + + +``` + +Documentation +------------- + +* [Codelab tutorial](https://github.com/web-animations/web-animations-codelabs) +* [Examples of usage](/docs/examples.md) +* [Live demos](https://web-animations.github.io/web-animations-demos) +* [MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) +* [W3C specification](https://drafts.csswg.org/web-animations/) + +We love feedback! +----------------- + +* For feedback on the API and the specification: + * File an issue on GitHub: + * Alternatively, send an email to with subject line +"[web-animations] ... message topic ..." ([archives](http://lists.w3.org/Archives/Public/public-fx/)). -Polyfill Issues ---------------- +* For issues with the polyfill, report them on GitHub: +. -Report any issues with this implementation on GitHub: -. +Keep up-to-date +--------------- -Breaking changes ----------------- +Breaking polyfill changes will be announced on this low-volume mailing list: +[web-animations-changes@googlegroups.com](https://groups.google.com/forum/#!forum/web-animations-changes). -When we make a potentially breaking change to the polyfill's API -surface (like a rename) we will, where possible, continue supporting the -old version, deprecated, for three months, and ensure that there are -console warnings to indicate that a change is pending. After three -months, the old version of the API surface (e.g. the old version of a -function name) will be removed. *If you see deprecation warnings you -can't avoid it by not updating*. +More info +--------- -We also announce anything that isn't a bug fix on -[web-animations-changes@googlegroups.com](https://groups.google.com/forum/#!forum/web-animations-changes). +* [Technical details about the polyfill](/docs/support.md) + * [Browser support](/docs/support.md#browser-support) + * [Fallback to native](/docs/support.md#native-fallback) + * [Feature list](/docs/support.md#features) + * [Feature deprecation and removal processes](/docs/support.md#process-for-breaking-changes) +* To test experimental API features, try one of the + [experimental targets](/docs/experimental.md) diff --git a/bower.json b/bower.json index 22f26b5e..afa0f9e1 100644 --- a/bower.json +++ b/bower.json @@ -16,7 +16,6 @@ "node_modules", "templates", "test", - "src", "Gruntfile.js", "package.json", "target-config.js", diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 00000000..d61c16a7 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,241 @@ +#Examples of using Web Animations + +Property indexed keyframes syntax +--------------------------------- +- Each CSS property specifies its keyframe values as a list, different properties may have differently sized lists. +- The `easing` property applies its timing function to all keyframes. + +[**Live demo**](http://jsbin.com/qiyeriruru/edit?js,output) +```javascript +element.animate({ + transform: [ + 'scaleY(0.5)', + 'scaleX(0.5)', + 'scaleY(0.5)', + ], + background: [ + 'red', + 'blue', + 'orange', + 'red', + ], + easing: 'ease-in-out', +}, { + duration: 2000, + iterations: Infinity, +}); +``` + +Keyframe list syntax +-------------------- +- Keyframes can be specified as a list of multiple CSS property values. +- Individual keyframes can be given specific offsets and easings. +- Not all properties need to be specified in every keyframe. +- Offsets are implicitly distributed if not specified. + +[**Live demo**](http://jsbin.com/yajatoyere/edit?js,output) +```javascript +element.animate([ + { + background: 'red', + transform: 'none', + easing: 'ease-out', + }, + { + offset: 0.1, + transform: 'translateY(100px)', + easing: 'ease-in-out', + }, + { + offset: 0.2, + transform: 'translate(100px, 100px)', + easing: 'ease-in-out', + }, + { + offset: 0.4, + transform: 'translateX(100px)', + easing: 'ease-out', + }, + { + background: 'blue', + transform: 'none', + }, +], { + duration: 4000, + iterations: Infinity, +}); +``` + +Timing parameters +----------------- +- Web Animations inherits many of its timing parameters from CSS Animations. +- See the [specification](https://drafts.csswg.org/web-animations/#animationeffecttimingreadonly) for details on each parameter. + +[**Live demo**](http://jsbin.com/dabehipiyo/edit?js,output) +```javascript +element.animate({ + transform: ['none', 'translateX(100px)'], + background: ['green', 'lime'], +}, { + // Apply effect during delay. + fill: 'backwards', + + // Delay starting by 500ms. + delay: 500, + + // Iterations last for 2000ms. + duration: 2000, + + // Start at 25% through an iteration. + iterationStart: 0.25, + + // Run for 2 iterations. + iterations: 2, + + // Play every second iteration backwards. + direction: 'alternate', + + // Stop animating 500ms earlier. + endDelay: -500, + + // The timing function to use with each iteration. + easing: 'ease-in-out', +}); +``` + +Playback controls +----------------- +- element.animate() returns an Animation object with basic playback controls. +- See the [specification](https://drafts.csswg.org/web-animations/#the-animation-interface) for details on each method. + +[**Live demo**](http://jsbin.com/kutaqoxejo/edit?js,output) +```javascript +var animation = element.animate({ + transform: ['none', 'translateX(200px)'], + background: ['red', 'orange'], +}, { + duration: 4000, + fill: 'both', +}); +animation.play(); +animation.reverse(); +animation.pause(); +animation.currentTime = 2000; +animation.playbackRate += 0.25; +animation.playbackRate -= 0.25; +animation.finish(); +animation.cancel(); +``` + +Transitioning states with element.animate() +------------------------------------------- +- This is an example of how to animate from one state to another using Web Animations. + +[**Live demo**](http://jsbin.com/musufiwule/edit?js,output) +```javascript +var isOpen = false; +var openHeight = '100px'; +var closedHeight = '0px'; +var duration = 300; + +button.addEventListener('click', function() { + // Prevent clicks while we transition states. + button.disabled = true; + button.textContent = '...'; + + // Determine where we're animation from/to. + var fromHeight = isOpen ? openHeight : closedHeight; + var toHeight = isOpen ? closedHeight : openHeight; + + // Start an animation transitioning from our current state to the final state. + var animation = element.animate({ height: [fromHeight, toHeight] }, duration); + + // Update the button once the animation finishes. + animation.onfinish = function() { + isOpen = !isOpen; + button.textContent = isOpen ? 'Close' : 'Open'; + button.disabled = false; + }; + + // Put our element in the final state. + // Inline styles are overridden by active animations. + // When the above animation finishes it will stop applying and + // the element's style will fall back onto this inline style value. + element.style.setProperty('height', toHeight); +}); +``` + +Generating animations +--------------------- +- The Javascript API allows for procedurally generating a diverse range of interesting animations. + +[**Live demo**](http://jsbin.com/xolacasiyu/edit?js,output) +```html + + + + + +
+
+
+ + +``` diff --git a/docs/experimental.md b/docs/experimental.md new file mode 100644 index 00000000..e3f22898 --- /dev/null +++ b/docs/experimental.md @@ -0,0 +1,58 @@ + +Experimental build targets +-------------------------- + +Most people should use the basic polyfill in `web-animations.min.js`. This +tracks the Web Animations features that are supported natively in browsers. +However, we also provide two additional build targets that contain experimental +features. + +### web-animations-next.min.js + +Contains all of web-animations.min.js plus features that are still undergoing +discussion or have yet to be implemented natively. + +### web-animations-next-lite.min.js + +A cut down version of web-animations-next, it removes several lesser used +property handlers and some of the larger and less used features such as matrix +interpolation/decomposition. + +Build target comparison +----------------------- + +| | web-animations | web-animations-next | web-animations-next-lite | +|------------------------|:--------------:|:-------------------:|:------------------------:| +|Size (gzipped) | 15KB | 19KB | 15KB | +|Element.animate | ✔ | ✔ | ✔ | +|Timing input (easings, duration, fillMode, etc.) for animation effects| ✔ | ✔ | ✔ | +|Playback control | ✔ | ✔ | ✔ | +|Support for animating lengths, transforms and opacity| ✔ | ✔ | ✔ | +|Support for animating other CSS properties| ✔ | ✔ | 🚫 | +|Matrix fallback for transform animations | ✔ | ✔ | 🚫 | +|KeyframeEffect constructor | 🚫 | ✔ | ✔ | +|Simple GroupEffects & SequenceEffects | 🚫 | ✔ | ✔ | +|Custom Effects | 🚫 | ✔ | ✔ | +|Timing input (easings, duration, fillMode, etc.) for groups
| 🚫 | 🚫\* | 🚫 | +|Additive animation | 🚫\* | 🚫\* | 🚫 | +|Motion path | 🚫\* | 🚫\* | 🚫 | +|Modifiable keyframe effect timing| 🚫 | 🚫\* | 🚫\* | +|Modifiable group timing | 🚫 | 🚫\* | 🚫\* | +|Usable inline style\*\* | ✔ | ✔ | 🚫 | + +\* support is planned for these features. +\*\* see inline style caveat below. + +Caveat: Inline style +-------------------- + +Inline style modification is the mechanism used by the polyfill to animate +properties. Both web-animations and web-animations-next incorporate a module +that emulates a vanilla inline style object, so that style modification from +JavaScript can still work in the presence of animations. However, to keep the +size of web-animations-next-lite as small as possible, the style emulation +module is not included. When using this version of the polyfill, JavaScript +inline style modification will be overwritten by animations. +Due to browser constraints inline style modification is not supported on iOS 7 +or Safari 6 (or earlier versions). + diff --git a/docs/support.md b/docs/support.md new file mode 100644 index 00000000..4fe76e66 --- /dev/null +++ b/docs/support.md @@ -0,0 +1,73 @@ + +Getting the polyfill +-------------------- + +There are three ways to get a copy of the polyfill: + +1. Download and use the `web-animations.min.js` file directly from this repository +1. Using npm: Add [`web-animations-js`](https://www.npmjs.com/package/web-animations-js) to your `package.json` +1. Using Bower: Add `web-animations/web-animations-js` to your `bower.json` + +Browser support +--------------- + +The polyfill is supported on modern versions of all major browsers, including: + +* Chrome 56+ +* Firefox 27+ +* IE10+ (including Edge) +* Safari (iOS) 7.1+ +* Safari (Mac) 9+ + +In particular, the polyfill requires requestAnimationFrame. If your browser does not +have requestAnimationFrame, consider loading a requestAnimationFrame polyfill first +([example](https://gist.githubusercontent.com/paulirish/1579671/raw/682e5c880c92b445650c4880a6bf9f3897ec1c5b/rAF.js)). + +Native fallback +--------------- + +When the polyfill runs on a browser that implements `Element.animate()` and +`Animation` playback control, it will detect and use the underlying native +features for better performance. + +Features +-------- + +The `web-animations.min.js` polyfill target tracks the Web Animations features +that are supported natively in browsers. These include: + +* Element.animate() +* Timing input (easings, duration, fillMode, etc.) for animation effects +* Playback control (play, pause, reverse, currentTime, cancel, onfinish) +* Support for animating CSS properties + +Caveat: Prefix handling +----------------------- + +The polyfill will automatically detect the correctly prefixed name to use when +writing animated properties back to the platform. Where possible, the polyfill +will only accept unprefixed versions of experimental features. For example: + +```js +element.animate({transform: ['none', 'translateX(100px)']}, 1000); +``` + +will work in all browsers that implement a conforming version of transform, but + +```js +element.animate({webkitTransform: ['none', 'translateX(100px)']}, 1000); +``` + +will not work anywhere. + +Process for breaking changes +---------------------------- + +When we make a potentially breaking change to the polyfill's API +surface (like a rename) we will, where possible, continue supporting the +old version, deprecated, for three months, and ensure that there are +console warnings to indicate that a change is pending. After three +months, the old version of the API surface (e.g. the old version of a +function name) will be removed. *If you see deprecation warnings, you +can't avoid them by not updating*. + diff --git a/externs/README.md b/externs/README.md new file mode 100644 index 00000000..3f16bf65 --- /dev/null +++ b/externs/README.md @@ -0,0 +1,10 @@ + +Closure Compiler Externs for Web Animations +------------------------------------------- + +This folder contains externs for using the Web Animations API with the Closure +Compiler. These externs aren't strictly part of the polyfill, as they can be +used for either the native or polyfilled versions. + +web-animations-next requires that you also include web-animations. + diff --git a/externs/web-animations-next.js b/externs/web-animations-next.js new file mode 100644 index 00000000..743a3ba5 --- /dev/null +++ b/externs/web-animations-next.js @@ -0,0 +1,113 @@ +/* + * Copyright 2016 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + + +/** + * @fileoverview Basic externs for the Web Animations API (Level 2 / Groups). + * This is not intended to be exhaustive, and requires the base externs from + * web-animations.js. + * @externs + */ + + +/** + * @interface + */ +var AnimationEffectReadOnly = function() {}; + +/** @type {!AnimationEffectTiming} */ +AnimationEffectReadOnly.prototype.timing; + + +/** + * @param {Element} target + * @param {!Array} frames + * @param {(number|AnimationEffectTimingProperties)=} opt_options + * @constructor + * @implements {AnimationEffectReadOnly} + */ +var KeyframeEffect = function(target, frames, opt_options) {}; + +/** + * @return {!Array} + */ +KeyframeEffect.prototype.getFrames = function() {}; + +/** @type {!AnimationEffectTiming} */ +KeyframeEffect.prototype.timing; + +/** @type {Element} */ +KeyframeEffect.prototype.target; + +/** @type {?function(number, !KeyframeEffect, !Animation)} */ +KeyframeEffect.prototype.onsample; + + +/** + * @param {!Array} children + * @param {AnimationEffectTimingProperties=} opt_timing + * @constructor + * @implements {AnimationEffectReadOnly} + */ +var SequenceEffect = function(children, opt_timing) {}; + +/** @type {!AnimationEffectTiming} */ +SequenceEffect.prototype.timing; + +/** @type {!Array} */ +SequenceEffect.prototype.children; + + +/** + * @param {!Array} children + * @param {AnimationEffectTimingProperties=} opt_timing + * @constructor + * @implements {AnimationEffectReadOnly} + */ +var GroupEffect = function(children, opt_timing) {}; + +/** @type {!AnimationEffectTiming} */ +GroupEffect.prototype.timing; + +/** @type {!Array} */ +GroupEffect.prototype.children; + + +/** + * @interface + */ +var AnimationTimeline = function() {}; + +/** @type {?number} */ +AnimationTimeline.prototype.currentTime; + +/** + * @param {!AnimationEffectReadOnly} effect + * @return {!Animation} + */ +AnimationTimeline.prototype.play = function(effect) {}; + +/** + * @interface + * @extends {AnimationTimeline} + */ +var DocumentTimeline = function() {}; + +/** @type {AnimationEffectReadOnly|undefined} */ +Animation.prototype.effect; + +/** @type {!DocumentTimeline} */ +Document.prototype.timeline; diff --git a/externs/web-animations.js b/externs/web-animations.js new file mode 100644 index 00000000..b3b604ba --- /dev/null +++ b/externs/web-animations.js @@ -0,0 +1,126 @@ +/* + * Copyright 2016 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + + +/** + * @fileoverview Basic externs for the Web Animations API. This is not + * nessecarily exhaustive. For more information, see the spec- + * https://drafts.csswg.org/web-animations/ + * @externs + */ + + +/** + * @param {!Array} frames + * @param {(number|AnimationEffectTimingProperties)=} opt_options + * @return {!Animation} + */ +Element.prototype.animate = function(frames, opt_options) {}; + + +/** + * @interface + * @extends {EventTarget} + */ +var Animation = function() {}; + +/** + * @return {undefined} + */ +Animation.prototype.cancel = function() {}; + +/** + * @return {undefined} + */ +Animation.prototype.finish = function() {}; + +/** + * @return {undefined} + */ +Animation.prototype.reverse = function() {}; + +/** + * @return {undefined} + */ +Animation.prototype.pause = function() {}; + +/** + * @return {undefined} + */ +Animation.prototype.play = function() {}; + +/** @type {number} */ +Animation.prototype.startTime; + +/** @type {number} */ +Animation.prototype.currentTime; + +/** @type {number} */ +Animation.prototype.playbackRate; + +/** @type {string} */ +Animation.prototype.playState; + +/** @type {?function(!Event)} */ +Animation.prototype.oncancel; + +/** @type {?function(!Event)} */ +Animation.prototype.onfinish; + + +/** + * @typedef {{ + * delay: (number|undefined), + * endDelay: (number|undefined), + * fillMode: (string|undefined), + * iterationStart: (number|undefined), + * iterations: (number|undefined), + * duration: (number|string|undefined), + * direction: (string|undefined), + * easing: (string|undefined) + * }} + */ +var AnimationEffectTimingProperties; + + +/** + * @interface + */ +var AnimationEffectTiming = function() {}; + +/** @type {number} */ +AnimationEffectTiming.prototype.delay; + +/** @type {number} */ +AnimationEffectTiming.prototype.endDelay; + +/** @type {string} */ +AnimationEffectTiming.prototype.fillMode; + +/** @type {number} */ +AnimationEffectTiming.prototype.iterationStart; + +/** @type {number} */ +AnimationEffectTiming.prototype.iterations; + +/** @type {number|string} */ +AnimationEffectTiming.prototype.duration; + +/** @type {string} */ +AnimationEffectTiming.prototype.direction; + +/** @type {string} */ +AnimationEffectTiming.prototype.easing; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..d90f0e50 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4855 @@ +{ + "name": "web-animations-js", + "version": "2.3.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "adm-zip": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "archiver": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.4.10.tgz", + "integrity": "sha1-3w/qyPHRKV5ezrOiBVWQctIfR0c=", + "dev": true, + "requires": { + "iconv-lite": "~0.2.11", + "readable-stream": "~1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "~1.7.0", + "underscore.string": "~2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz", + "integrity": "sha1-2T/9u2esVQd3m+MWp9ZRRkF77vg=", + "dev": true + }, + "assertion-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz", + "integrity": "sha1-PYHKabR0seFlGHKLUcJP8Lvtxuk=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "~1.0.26" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.x" + }, + "dependencies": { + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "caseless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.9.0.tgz", + "integrity": "sha1-t7Zc5r8UE4hlOc/VM/CzDv+pz4g=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chai": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-1.10.0.tgz", + "integrity": "sha1-5AMcyHZURhp1lD5aNatG6vOcHrk=", + "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + } + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "chokidar": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "closure-linter-wrapper": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/closure-linter-wrapper/-/closure-linter-wrapper-1.1.0.tgz", + "integrity": "sha1-1lTNhU56yMqhQNDKSMy/MChUsSg=", + "dev": true, + "requires": { + "colors": "^1.1.2" + } + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.9.tgz", + "integrity": "sha1-Qi2SdDDAGr0GzUVbbfwEy0z4ADw=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.1", + "crc32-stream": "~0.3.1", + "node-int64": "~0.3.0", + "readable-stream": "~1.0.26" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-jar": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz", + "integrity": "sha1-vJon1OK5fhhs1XyeIGPLmfpozMw=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "crc32-stream": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.4.tgz", + "integrity": "sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.1", + "readable-stream": "~1.0.24" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "requires": { + "boom": "0.4.x" + } + }, + "ctype": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz", + "integrity": "sha1-/oCR1Gijc6Cwyf+Lv7NCXACXOh0=", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "date-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", + "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", + "dev": true + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + } + }, + "deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", + "dev": true + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz", + "integrity": "sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ=", + "dev": true + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "~3.2.9", + "lodash": "~2.4.1" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "dev": true, + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.8.tgz", + "integrity": "sha1-CJDNEAXFzOzAudJKiAUskkQtDbU=", + "dev": true, + "requires": { + "async": "~0.2.7", + "combined-stream": "~0.0.4", + "mime": "~1.2.2" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "requires": { + "async": "~0.1.22", + "coffee-script": "~1.3.3", + "colors": "~0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.1.2", + "getobject": "~0.1.0", + "glob": "~3.1.21", + "grunt-legacy-log": "~0.1.0", + "grunt-legacy-util": "~0.2.0", + "hooker": "~0.2.3", + "iconv-lite": "~0.2.11", + "js-yaml": "~2.0.5", + "lodash": "~0.9.2", + "minimatch": "~0.2.12", + "nopt": "~1.0.10", + "rimraf": "~2.2.8", + "underscore.string": "~2.2.1", + "which": "~1.0.5" + }, + "dependencies": { + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "grunt-checkrepo": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/grunt-checkrepo/-/grunt-checkrepo-0.1.0.tgz", + "integrity": "sha1-4bhgKRhtAe98BfoJG/Z54Uzg1y0=", + "dev": true, + "requires": { + "semver": "~2.1.0", + "shelljs": "~0.2.5" + } + }, + "grunt-contrib-uglify": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.4.1.tgz", + "integrity": "sha1-1D87xuAsM1Vj+MT58IE/tLD/ebE=", + "dev": true, + "requires": { + "chalk": "^0.4.0", + "maxmin": "^0.1.0", + "uglify-js": "^2.4.0" + } + }, + "grunt-git-status": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-git-status/-/grunt-git-status-1.0.0.tgz", + "integrity": "sha1-qw9MfiUXKpUWkPd0assdtt8QiM8=", + "dev": true + }, + "grunt-gjslint": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/grunt-gjslint/-/grunt-gjslint-0.2.1.tgz", + "integrity": "sha1-e7BLC8rfWoLrrQ9RmZ1owyvgYD8=", + "dev": true + }, + "grunt-karma": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/grunt-karma/-/grunt-karma-3.0.2.tgz", + "integrity": "sha512-imNhQO1bR1O7X6/3F5vO0o7mKy4xdkpSd40QVfxGO70cBAFcOqjv2Zu5QzsfEsSrppuu3N0vIQPbfBRjeGdpWg==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "requires": { + "colors": "~0.6.2", + "grunt-legacy-log-utils": "~0.1.1", + "hooker": "~0.2.3", + "lodash": "~2.4.1", + "underscore.string": "~2.3.3" + }, + "dependencies": { + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "requires": { + "colors": "~0.6.2", + "lodash": "~2.4.1", + "underscore.string": "~2.3.3" + }, + "dependencies": { + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "requires": { + "async": "~0.1.22", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~0.9.2", + "underscore.string": "~2.2.1", + "which": "~1.0.5" + } + }, + "grunt-saucelabs": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/grunt-saucelabs/-/grunt-saucelabs-4.0.4.tgz", + "integrity": "sha1-OLFDJmIukE3rNS7Ow0NHMCAZ7hw=", + "dev": true, + "requires": { + "colors": "~0.6.0", + "request": "~2.12.0", + "saucelabs": "~0.0.7", + "wd": "~0.0.26" + }, + "dependencies": { + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + } + } + }, + "grunt-template": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/grunt-template/-/grunt-template-0.2.3.tgz", + "integrity": "sha1-JBVa/qeJhL5nMMHHc7uS3odHo3A=", + "dev": true + }, + "gzip-size": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-0.1.1.tgz", + "integrity": "sha1-rjNIO2/IIk6DQilt4Qjvk3V/duA=", + "dev": true, + "requires": { + "concat-stream": "^1.4.1", + "zlib-browserify": "^0.0.3" + } + }, + "har-validator": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", + "integrity": "sha1-2DhCsOtMQ1lgrrEIoGejqpTA7rI=", + "dev": true, + "requires": { + "bluebird": "^2.9.30", + "chalk": "^1.0.0", + "commander": "^2.8.1", + "is-my-json-valid": "^2.12.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hawk": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-0.13.1.tgz", + "integrity": "sha1-NheViCH1gxHk1/beKR/KZitBLvQ=", + "dev": true, + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.8.x", + "sntp": "0.2.x" + } + }, + "hoek": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.8.5.tgz", + "integrity": "sha1-Hp/XcO9+vgJ0rfy1sIBqAlpeTp8=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-signature": { + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.9.11.tgz", + "integrity": "sha1-nognFFcjFeZ5Cl0KeVXv/x8Z5lM=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.2", + "ctype": "0.5.2" + } + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "~ 0.1.11", + "esprima": "~ 1.0.2" + } + }, + "json-stringify-safe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-4.0.0.tgz", + "integrity": "sha1-d8JxqupUMC5o7+rMtWq78GqbGlQ=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true, + "optional": true + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "karma": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", + "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "braces": "^2.3.2", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "dependencies": { + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true + }, + "karma-chrome-launcher": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-0.1.12.tgz", + "integrity": "sha1-CsDiLlc2UPZUExL9ynlcOCTM+WI=", + "dev": true, + "requires": { + "which": "^1.0.9" + } + }, + "karma-firefox-launcher": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-0.1.7.tgz", + "integrity": "sha1-wF3YZTNpHmLzGVJZUJjovTV9OfM=", + "dev": true + }, + "karma-ie-launcher": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-0.1.5.tgz", + "integrity": "sha1-7kO9I49hxF3Y+8FpSxOlDftaPhs=", + "dev": true + }, + "karma-mocha": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-0.1.10.tgz", + "integrity": "sha1-Ke1R1LEhrxNzRE7FVbIKkFv0K5I=", + "dev": true + }, + "karma-safari-launcher": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-0.1.1.tgz", + "integrity": "sha1-pjgKzKtgpYP91iT0G5o/EP30EAg=", + "dev": true + }, + "karma-sauce-launcher": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-0.2.14.tgz", + "integrity": "sha1-5C5BJRfF9AU0yLun0Uu08Qcntqc=", + "dev": true, + "requires": { + "q": "~0.9.6", + "sauce-connect-launcher": "~0.11.1", + "saucelabs": "~0.1.0", + "wd": "~0.3.4" + }, + "dependencies": { + "archiver": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.14.4.tgz", + "integrity": "sha1-W53bn17hzu8hy487Ag5iQOy0MVw=", + "dev": true, + "requires": { + "async": "~0.9.0", + "buffer-crc32": "~0.2.1", + "glob": "~4.3.0", + "lazystream": "~0.1.0", + "lodash": "~3.2.0", + "readable-stream": "~1.0.26", + "tar-stream": "~1.1.0", + "zip-stream": "~0.5.0" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + } + } + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.x.x" + } + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "dev": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime-types": "~2.0.3" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, + "glob": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "hawk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", + "integrity": "sha1-HnMc45RH+h0PbXB/e87r7A/R7B8=", + "dev": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "lodash": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz", + "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=", + "dev": true + }, + "mime-db": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", + "dev": true + }, + "mime-types": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "dev": true, + "requires": { + "mime-db": "~1.12.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "oauth-sign": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.6.0.tgz", + "integrity": "sha1-fb6uRPbKRU4fFoRR1jB0ZzWBPOM=", + "dev": true + }, + "qs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz", + "integrity": "sha1-9854jld33wtQENp/fE5zujJHD1o=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "request": { + "version": "2.55.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.55.0.tgz", + "integrity": "sha1-11wc32eddrsQD5v/4f5VG1wk6T0=", + "dev": true, + "requires": { + "aws-sign2": "~0.5.0", + "bl": "~0.9.0", + "caseless": "~0.9.0", + "combined-stream": "~0.0.5", + "forever-agent": "~0.6.0", + "form-data": "~0.2.0", + "har-validator": "^1.4.0", + "hawk": "~2.3.0", + "http-signature": "~0.10.0", + "isstream": "~0.1.1", + "json-stringify-safe": "~5.0.0", + "mime-types": "~2.0.1", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.6.0", + "qs": "~2.4.0", + "stringstream": "~0.0.4", + "tough-cookie": ">=0.12.0", + "tunnel-agent": "~0.4.0" + } + }, + "saucelabs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz", + "integrity": "sha1-Xg6hzz1zXW6hX96Utb2mvBXSwG0=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "underscore.string": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.0.3.tgz", + "integrity": "sha1-Rhe4waJQz25QZPu7Nj0PqWzxRVI=", + "dev": true + }, + "wd": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/wd/-/wd-0.3.12.tgz", + "integrity": "sha1-P7Tx11n4yF3eU5PRczT/4D6bsyk=", + "dev": true, + "requires": { + "archiver": "~0.14.0", + "async": "~1.0.0", + "lodash": "~3.9.3", + "q": "~1.4.1", + "request": "~2.55.0", + "underscore.string": "~3.0.3", + "vargs": "~0.1.0" + }, + "dependencies": { + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + } + } + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazystream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "dev": true, + "requires": { + "readable-stream": "~1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "log4js": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.3.2.tgz", + "integrity": "sha512-72GjgSP+ifL156MD/bXEhE7UlFLKS2KkCXujodb1nl1z6PpKhCfS+41dyNQ7zKi4iM49TQl+aWLEISXGLcGCCQ==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.2", + "streamroller": "^1.0.5" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "maxmin": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-0.1.0.tgz", + "integrity": "sha1-ldgcUonjqdMPf8fcVZwCTlAwydA=", + "dev": true, + "requires": { + "chalk": "^0.4.0", + "gzip-size": "^0.1.0", + "pretty-bytes": "^0.1.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mocha": { + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.4.tgz", + "integrity": "sha1-531pw3c7o+K0/mtijCi13UOICtw=", + "dev": true, + "requires": { + "commander": "2.0.0", + "debug": "*", + "diff": "1.0.7", + "glob": "3.2.3", + "growl": "1.8.x", + "jade": "0.26.3", + "mkdirp": "0.3.5" + }, + "dependencies": { + "commander": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "~2.0.0", + "inherits": "2", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "node-int64": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz", + "integrity": "sha1-LW5rLs5d6FiLQ9iNG8QbJs0fqE0=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-bytes": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-0.1.2.tgz", + "integrity": "sha1-zZApTVihyk6KXQ+5yCJZmIgazwA=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.33.tgz", + "integrity": "sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + } + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.12.0.tgz", + "integrity": "sha1-EfRvILPQ9ISMY4OZHIB5CvFsjkg=", + "dev": true, + "requires": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "dependencies": { + "form-data": { + "version": "0.0.3", + "bundled": true, + "dev": true, + "requires": { + "async": "~0.1.9", + "combined-stream": "0.0.3", + "mime": "~1.2.2" + }, + "dependencies": { + "async": { + "version": "0.1.9", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "0.0.3", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + }, + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "bundled": true, + "dev": true + } + } + } + } + }, + "mime": { + "version": "1.2.7", + "bundled": true, + "dev": true + } + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sauce-connect-launcher": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-0.11.1.tgz", + "integrity": "sha1-ZfUdiJEkn9q6rxdZlzTeGQJHYSk=", + "dev": true, + "requires": { + "adm-zip": "~0.4.3", + "async": "0.9.0", + "lodash": "3.5.0", + "rimraf": "2.2.6" + }, + "dependencies": { + "async": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "integrity": "sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc=", + "dev": true + }, + "lodash": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.5.0.tgz", + "integrity": "sha1-Gbs/TVEnjwuMgY7RRcdOz5/kDm0=", + "dev": true + }, + "rimraf": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=", + "dev": true + } + } + }, + "saucelabs": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.0.9.tgz", + "integrity": "sha1-CrP/0XCCpa6Sd+d+9rY5EPXbLGg=", + "dev": true + }, + "semver": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-2.1.0.tgz", + "integrity": "sha1-NWKUqQaQtph3TWLPNdfJH5g+coo=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shelljs": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", + "integrity": "sha1-kEktcv/MgVmXa6umL7D2iE8MM3g=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "requires": { + "hoek": "0.9.x" + }, + "dependencies": { + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "streamroller": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", + "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", + "dev": true, + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tape": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/tape/-/tape-0.2.2.tgz", + "integrity": "sha1-ZMz6S37PSgBgAH5hcW1CR4FnFjc=", + "dev": true, + "requires": { + "deep-equal": "~0.0.0", + "defined": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "tar-stream": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.5.tgz", + "integrity": "sha1-vpIYwTDCACnhB7D5Z/sj3gV50Tw=", + "dev": true, + "requires": { + "bl": "^0.9.0", + "end-of-stream": "^1.0.0", + "readable-stream": "~1.0.33", + "xtend": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dev": true, + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", + "integrity": "sha1-rWgbaPUyGtKCfEz7G31d8s/pQu4=", + "dev": true + }, + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "vargs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", + "integrity": "sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "wd": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/wd/-/wd-0.0.34.tgz", + "integrity": "sha1-yNAMzbsoYvkUt71ZNTMKU8+ohWI=", + "dev": true, + "requires": { + "archiver": "~0.4.6", + "async": "0.2.x", + "q": "0.9.x", + "request": "~2.21.0", + "underscore": "1.4.x", + "vargs": "~0.1.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "request": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.21.0.tgz", + "integrity": "sha1-VyirnEXlqHyZ2szVMCmLZnOoaNc=", + "dev": true, + "requires": { + "aws-sign": "~0.3.0", + "cookie-jar": "~0.3.0", + "forever-agent": "~0.5.0", + "form-data": "0.0.8", + "hawk": "~0.13.0", + "http-signature": "~0.9.11", + "json-stringify-safe": "~4.0.0", + "mime": "~1.2.9", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~0.6.0", + "tunnel-agent": "~0.3.0" + } + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + } + } + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "zip-stream": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.2.tgz", + "integrity": "sha1-Mty8UG0Nq00hNyYlvX66rDwv/1Y=", + "dev": true, + "requires": { + "compress-commons": "~0.2.0", + "lodash": "~3.2.0", + "readable-stream": "~1.0.26" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "zlib-browserify": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.3.tgz", + "integrity": "sha1-JAzNv9AgP6hCsTDe77FBQSLIzFA=", + "dev": true, + "requires": { + "tape": "~0.2.2" + } + } + } +} diff --git a/package.json b/package.json index b579b79d..8d386c70 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,33 @@ { "name": "web-animations-js", - "private": true, + "description": "JavaScript implementation of the Web Animations API", "repository": { "type": "git", "url": "https://github.com/web-animations/web-animations-js.git" }, + "version": "2.3.2", + "keywords": [ + "animations", + "polyfill" + ], + "homepage": "https://github.com/web-animations", + "license": "Apache-2.0", + "main": "web-animations.min.js", + "files": [ + "src/*", + "*.min.js", + "*.min.js.map" + ], "devDependencies": { + "minimatch": "^3.0.4", "mocha": "1.21.4", "chai": "^1.9.1", "grunt": "~0.4.5", "grunt-contrib-uglify": "^0.4.0", - "grunt-gjslint": "^0.1.4", - "grunt-karma": "^0.8.2", - "karma": "^0.12.14", + "grunt-gjslint": "^0.2.1", + "closure-linter-wrapper": "^1.0.0", + "grunt-karma": "3.x", + "karma": "4.x", "karma-mocha": "^0.1.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "~0.1.4", @@ -22,12 +37,11 @@ "karma-sauce-launcher": "~0.2.3", "grunt-checkrepo": "~0.1.0", "grunt-saucelabs": "~4.0.2", - "grunt-checkrepo": "~0.1.0", "grunt-git-status": "~1.0.0", "grunt-template": "~0.2.3", "source-map": "~0.1.40" }, "scripts": { - "test": "grunt test gjslint git-status checkrepo" + "test": "grunt web-animations web-animations-next test gjslint git-status checkrepo" } } diff --git a/src/animation.js b/src/animation.js index ecc77d70..69b9d2f9 100644 --- a/src/animation.js +++ b/src/animation.js @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -(function(scope, testing) { +(function(shared, scope, testing) { - var sequenceNumber = 0; + shared.sequenceNumber = 0; var AnimationEvent = function(target, currentTime, timelineTime) { this.target = target; @@ -31,13 +31,17 @@ }; scope.Animation = function(effect) { - this._sequenceNumber = sequenceNumber++; + this.id = ''; + if (effect && effect._id) { + this.id = effect._id; + } + this._sequenceNumber = shared.sequenceNumber++; this._currentTime = 0; this._startTime = null; - this.paused = false; + this._paused = false; this._playbackRate = 1; this._inTimeline = true; - this._finishedFlag = false; + this._finishedFlag = true; this.onfinish = null; this._finishHandlers = []; this._effect = effect; @@ -64,7 +68,7 @@ _tickCurrentTime: function(newTime, ignoreLimit) { if (newTime != this._currentTime) { this._currentTime = newTime; - if (this.finished && !ignoreLimit) + if (this._isFinished && !ignoreLimit) this._currentTime = this._playbackRate > 0 ? this._totalDuration : 0; this._ensureAlive(); } @@ -79,14 +83,18 @@ if (isNaN(newTime)) return; scope.restart(); - if (!this.paused && this._startTime != null) { + if (!this._paused && this._startTime != null) { this._startTime = this._timeline.currentTime - newTime / this._playbackRate; } this._currentTimePending = false; if (this._currentTime == newTime) return; + if (this._idle) { + this._idle = false; + this._paused = true; + } this._tickCurrentTime(newTime, true); - scope.invalidateEffects(); + scope.applyDirtiedAnimation(this); }, get startTime() { return this._startTime; @@ -95,11 +103,11 @@ newTime = +newTime; if (isNaN(newTime)) return; - if (this.paused || this._idle) + if (this._paused || this._idle) return; this._startTime = newTime; this._tickCurrentTime((this._timeline.currentTime - this._startTime) * this.playbackRate); - scope.invalidateEffects(); + scope.applyDirtiedAnimation(this); }, get playbackRate() { return this._playbackRate; @@ -112,13 +120,16 @@ this._playbackRate = value; this._startTime = null; if (this.playState != 'paused' && this.playState != 'idle') { - this.play(); + this._finishedFlag = false; + this._idle = false; + this._ensureAlive(); + scope.applyDirtiedAnimation(this); } if (oldCurrentTime != null) { this.currentTime = oldCurrentTime; } }, - get finished() { + get _isFinished() { return !this._idle && (this._playbackRate > 0 && this._currentTime >= this._totalDuration || this._playbackRate < 0 && this._currentTime <= 0); }, @@ -126,32 +137,45 @@ get playState() { if (this._idle) return 'idle'; - if ((this._startTime == null && !this.paused && this.playbackRate != 0) || this._currentTimePending) + if ((this._startTime == null && !this._paused && this.playbackRate != 0) || this._currentTimePending) return 'pending'; - if (this.paused) + if (this._paused) return 'paused'; - if (this.finished) + if (this._isFinished) return 'finished'; return 'running'; }, + _rewind: function() { + if (this._playbackRate >= 0) { + this._currentTime = 0; + } else if (this._totalDuration < Infinity) { + this._currentTime = this._totalDuration; + } else { + throw new DOMException( + 'Unable to rewind negative playback rate animation with infinite duration', + 'InvalidStateError'); + } + }, play: function() { - this.paused = false; - if (this.finished || this._idle) { - this._currentTime = this._playbackRate > 0 ? 0 : this._totalDuration; + this._paused = false; + if (this._isFinished || this._idle) { + this._rewind(); this._startTime = null; - scope.invalidateEffects(); } this._finishedFlag = false; - scope.restart(); this._idle = false; this._ensureAlive(); + scope.applyDirtiedAnimation(this); }, pause: function() { - if (!this.finished && !this.paused && !this._idle) { + if (!this._isFinished && !this._paused && !this._idle) { this._currentTimePending = true; + } else if (this._idle) { + this._rewind(); + this._idle = false; } this._startTime = null; - this.paused = true; + this._paused = true; }, finish: function() { if (this._idle) @@ -159,12 +183,21 @@ this.currentTime = this._playbackRate > 0 ? this._totalDuration : 0; this._startTime = this._totalDuration - this.currentTime; this._currentTimePending = false; + scope.applyDirtiedAnimation(this); }, cancel: function() { + if (!this._inEffect) + return; this._inEffect = false; this._idle = true; - this.currentTime = 0; + this._paused = false; + this._finishedFlag = true; + this._currentTime = 0; this._startTime = null; + this._effect._update(null); + // effects are invalid after cancellation as the animation state + // needs to un-apply. + scope.applyDirtiedAnimation(this); }, reverse: function() { this.playbackRate *= -1; @@ -182,29 +215,59 @@ this._finishHandlers.splice(index, 1); }, _fireEvents: function(baseTime) { - var finished = this.finished; - if ((finished || this._idle) && !this._finishedFlag) { - var event = new AnimationEvent(this, this._currentTime, baseTime); - var handlers = this._finishHandlers.concat(this.onfinish ? [this.onfinish] : []); - setTimeout(function() { - handlers.forEach(function(handler) { - handler.call(event.target, event); - }); - }, 0); - } - this._finishedFlag = finished; - }, - _tick: function(timelineTime) { - if (!this._idle && !this.paused) { - if (this._startTime == null) - this.startTime = timelineTime - this._currentTime / this.playbackRate; - else if (!this.finished) + if (this._isFinished) { + if (!this._finishedFlag) { + var event = new AnimationEvent(this, this._currentTime, baseTime); + var handlers = this._finishHandlers.concat(this.onfinish ? [this.onfinish] : []); + setTimeout(function() { + handlers.forEach(function(handler) { + handler.call(event.target, event); + }); + }, 0); + this._finishedFlag = true; + } + } else { + this._finishedFlag = false; + } + }, + _tick: function(timelineTime, isAnimationFrame) { + if (!this._idle && !this._paused) { + if (this._startTime == null) { + if (isAnimationFrame) { + this.startTime = timelineTime - this._currentTime / this.playbackRate; + } + } else if (!this._isFinished) { this._tickCurrentTime((timelineTime - this._startTime) * this.playbackRate); + } } - this._currentTimePending = false; - this._fireEvents(timelineTime); - return !this._idle && (this._inEffect || !this._finishedFlag); + if (isAnimationFrame) { + this._currentTimePending = false; + this._fireEvents(timelineTime); + } + }, + get _needsTick() { + return (this.playState in {'pending': 1, 'running': 1}) || !this._finishedFlag; + }, + _targetAnimations: function() { + var target = this._effect._target; + if (!target._activeAnimations) { + target._activeAnimations = []; + } + return target._activeAnimations; + }, + _markTarget: function() { + var animations = this._targetAnimations(); + if (animations.indexOf(this) === -1) { + animations.push(this); + } + }, + _unmarkTarget: function() { + var animations = this._targetAnimations(); + var index = animations.indexOf(this); + if (index !== -1) { + animations.splice(index, 1); + } }, }; @@ -212,4 +275,4 @@ testing.webAnimations1Animation = scope.Animation; } -})(webAnimations1, webAnimationsTesting); +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/src/apply-preserving-inline-style.js b/src/apply-preserving-inline-style.js index 795be364..4002a2f5 100644 --- a/src/apply-preserving-inline-style.js +++ b/src/apply-preserving-inline-style.js @@ -14,6 +14,28 @@ (function(scope, testing) { + var SVG_TRANSFORM_PROP = '_webAnimationsUpdateSvgTransformAttr'; + + /** + * IE/Edge do not support `transform` styles for SVG elements. Instead, + * `transform` attribute can be animated with some restrictions. + * See https://connect.microsoft.com/IE/feedback/details/811744/ie11-bug-with-implementation-of-css-transforms-in-svg, + * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/1173754/, + * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101242/, etc. + * The same problem is exhibited by pre-Chrome Android browsers (ICS). + * Unfortunately, there's no easy way to feature-detect it. + */ + function updateSvgTransformAttr(window, element) { + if (!element.namespaceURI || element.namespaceURI.indexOf('/svg') == -1) { + return false; + } + if (!(SVG_TRANSFORM_PROP in window)) { + window[SVG_TRANSFORM_PROP] = + /Trident|MSIE|IEMobile|Edge|Android 4/i.test(window.navigator.userAgent); + } + return window[SVG_TRANSFORM_PROP]; + } + var styleAttributes = { cssText: 1, length: 1, @@ -44,6 +66,7 @@ WEB_ANIMATIONS_TESTING && console.assert(!(element.style instanceof AnimatedCSSStyleDeclaration), 'Element must not already have an animated style attached.'); + this._element = element; // Stores the inline style of the element on its behalf while the // polyfill uses the element's inline style to simulate web animations. // This is needed to fake regular inline style CSSOM access on the element. @@ -51,6 +74,8 @@ this._style = element.style; this._length = 0; this._isAnimatedProperty = {}; + this._updateSvgTransformAttr = updateSvgTransformAttr(window, element); + this._savedTransformAttr = null; // Copy the inline style contents over to the surrogate. for (var i = 0; i < this._style.length; i++) { @@ -110,9 +135,30 @@ _set: function(property, value) { this._style[property] = value; this._isAnimatedProperty[property] = true; + if (this._updateSvgTransformAttr && + scope.unprefixedPropertyName(property) == 'transform') { + // On IE/Edge, also set SVG element's `transform` attribute to 2d + // matrix of the transform. The `transform` style does not work, but + // `transform` attribute can be used instead. + // Notice, if the platform indeed supports SVG/CSS transforms the CSS + // declaration is supposed to override the attribute. + if (this._savedTransformAttr == null) { + this._savedTransformAttr = this._element.getAttribute('transform'); + } + this._element.setAttribute('transform', scope.transformToSvgMatrix(value)); + } }, _clear: function(property) { this._style[property] = this._surrogateStyle[property]; + if (this._updateSvgTransformAttr && + scope.unprefixedPropertyName(property) == 'transform') { + if (this._savedTransformAttr) { + this._element.setAttribute('transform', this._savedTransformAttr); + } else { + this._element.removeAttribute('transform'); + } + this._savedTransformAttr = null; + } delete this._isAnimatedProperty[property]; }, }; @@ -185,7 +231,9 @@ } }; - if (WEB_ANIMATIONS_TESTING) + if (WEB_ANIMATIONS_TESTING) { testing.ensureStyleIsPatched = ensureStyleIsPatched; + testing.updateSvgTransformAttr = updateSvgTransformAttr; + } })(webAnimations1, webAnimationsTesting); diff --git a/src/color-handler.js b/src/color-handler.js index b32a8899..3a05bff0 100644 --- a/src/color-handler.js +++ b/src/color-handler.js @@ -51,7 +51,8 @@ scope.addPropertiesHandler(parseColor, mergeColors, ['background-color', 'border-bottom-color', 'border-left-color', 'border-right-color', - 'border-top-color', 'color', 'outline-color', 'text-decoration-color']); + 'border-top-color', 'color', 'fill', 'flood-color', 'lighting-color', + 'outline-color', 'stop-color', 'stroke', 'text-decoration-color']); scope.consumeColor = scope.consumeParenthesised.bind(null, parseColor); scope.mergeColors = mergeColors; diff --git a/src/deprecation.js b/src/deprecation.js index 33499379..6bdb4a22 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -17,6 +17,10 @@ var silenced = {}; shared.isDeprecated = function(feature, date, advice, plural) { + if (WEB_ANIMATIONS_TESTING) { + return true; + } + var auxVerb = plural ? 'are' : 'is'; var today = new Date(); var expiry = new Date(date); diff --git a/src/dimension-handler.js b/src/dimension-handler.js index 66afe0d2..9e487f97 100644 --- a/src/dimension-handler.js +++ b/src/dimension-handler.js @@ -14,6 +14,78 @@ (function(scope, testing) { + // Evaluates a calc expression. + // https://drafts.csswg.org/css-values-3/#calc-notation + function calculate(expression) { + // In calc expressions, white space is required on both sides of the + // + and - operators. https://drafts.csswg.org/css-values-3/#calc-notation + // Thus any + or - immediately adjacent to . or 0..9 is part of the number, + // e.g. -1.23e+45 + // This regular expression matches ( ) * / + - and numbers. + var tokenRegularExpression = /([\+\-\w\.]+|[\(\)\*\/])/g; + var currentToken; + function consume() { + var matchResult = tokenRegularExpression.exec(expression); + if (matchResult) + currentToken = matchResult[0]; + else + currentToken = undefined; + } + consume(); // Read the initial token. + + function calcNumber() { + // https://drafts.csswg.org/css-values-3/#number-value + var result = Number(currentToken); + consume(); + return result; + } + + function calcValue() { + // = | | | ( ) + if (currentToken !== '(') + return calcNumber(); + consume(); + var result = calcSum(); + if (currentToken !== ')') + return NaN; + consume(); + return result; + } + + function calcProduct() { + // = [ '*' | '/' ]* + var left = calcValue(); + while (currentToken === '*' || currentToken === '/') { + var operator = currentToken; + consume(); + var right = calcValue(); + if (operator === '*') + left *= right; + else + left /= right; + } + return left; + } + + function calcSum() { + // = [ [ '+' | '-' ] ]* + var left = calcProduct(); + while (currentToken === '+' || currentToken === '-') { + var operator = currentToken; + consume(); + var right = calcProduct(); + if (operator === '+') + left += right; + else + left -= right; + } + return left; + } + + // = calc( ) + return calcSum(); + } + function parseDimension(unitRegExp, string) { string = string.trim().toLowerCase(); @@ -36,10 +108,10 @@ var taggedUnitRegExp = 'U(' + unitRegExp.source + ')'; // Validating input is simply applying as many reductions as we can. - var typeCheck = string.replace(/[-+]?(\d*\.)?\d+/g, 'N') - .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D') - .replace(/\s[+-]\s/g, 'O') - .replace(/\s/g, ''); + var typeCheck = string.replace(/[-+]?(\d*\.)?\d+([Ee][-+]?\d+)?/g, 'N') + .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D') + .replace(/\s[+-]\s/g, 'O') + .replace(/\s/g, ''); var reductions = [/N\*(D)/g, /(N|D)[*/]N/g, /(N|D)O\1/g, /\((N|D)\)/g]; var i = 0; while (i < reductions.length) { @@ -54,7 +126,7 @@ return; for (var unit in matchedUnits) { - var result = eval(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0')); + var result = calculate(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0')); if (!isFinite(result)) return; matchedUnits[unit] = result; @@ -158,6 +230,7 @@ 'perspective', 'right', 'shape-margin', + 'stroke-dashoffset', 'text-indent', 'top', 'vertical-align', diff --git a/src/effect-callback.js b/src/effect-callback.js index e187241e..3051a593 100644 --- a/src/effect-callback.js +++ b/src/effect-callback.js @@ -18,21 +18,32 @@ var sequenceNumber = 0; scope.bindAnimationForCustomEffect = function(animation) { var target = animation.effect.target; - var effectFunction = animation.effect._normalizedKeyframes; + var effectFunction; + var isKeyframeEffect = typeof animation.effect.getFrames() == 'function'; + if (isKeyframeEffect) { + effectFunction = animation.effect.getFrames(); + } else { + effectFunction = animation.effect._onsample; + } var timing = animation.effect.timing; var last = null; timing = shared.normalizeTimingInput(timing); var callback = function() { var t = callback._animation ? callback._animation.currentTime : null; if (t !== null) { - t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + t = shared.calculateIterationProgress(shared.calculateActiveDuration(timing), t, timing); if (isNaN(t)) t = null; } // FIXME: There are actually more conditions under which the effectFunction // should be called. - if (t !== last) - effectFunction(t, target, animation.effect); + if (t !== last) { + if (isKeyframeEffect) { + effectFunction(t, target, animation.effect); + } else { + effectFunction(t, animation.effect, animation.effect._animation); + } + } last = t; }; diff --git a/src/element-animatable.js b/src/element-animatable.js index 6bcf1dce..765edf06 100644 --- a/src/element-animatable.js +++ b/src/element-animatable.js @@ -13,7 +13,11 @@ // limitations under the License. (function(scope) { - window.Element.prototype.animate = function(effectInput, timingInput) { - return scope.timeline._play(scope.KeyframeEffect(this, effectInput, timingInput)); + window.Element.prototype.animate = function(effectInput, options) { + var id = ''; + if (options && options.id) { + id = options.id; + } + return scope.timeline._play(scope.KeyframeEffect(this, effectInput, options, id)); }; })(webAnimations1); diff --git a/src/group-constructors.js b/src/group-constructors.js index 1700dde7..e5c0a102 100644 --- a/src/group-constructors.js +++ b/src/group-constructors.js @@ -18,13 +18,20 @@ return node._timing.delay + node.activeDuration + node._timing.endDelay; } - function constructor(children, timingInput) { + function constructor(children, timingInput, id) { + this._id = id; + this._parent = null; this.children = children || []; + this._reparent(this.children); + timingInput = shared.numericTimingToObject(timingInput); + this._timingInput = shared.cloneTimingInput(timingInput); this._timing = shared.normalizeTimingInput(timingInput, true); - this.timing = shared.makeTiming(timingInput, true); + this.timing = shared.makeTiming(timingInput, true, this); + this.timing._effect = this; - if (this._timing.duration === 'auto') + if (this._timing.duration === 'auto') { this._timing.duration = this.activeDuration; + } } window.SequenceEffect = function() { @@ -35,62 +42,152 @@ constructor.apply(this, arguments); }; - window.SequenceEffect.prototype = { - get activeDuration() { - var total = 0; - this.children.forEach(function(child) { - total += groupChildDuration(child); - }); - return Math.max(total, 0); + constructor.prototype = { + _isAncestor: function(effect) { + var a = this; + while (a !== null) { + if (a == effect) + return true; + a = a._parent; + } + return false; + }, + _rebuild: function() { + // Re-calculate durations for ancestors with specified duration 'auto'. + var node = this; + while (node) { + if (node.timing.duration === 'auto') { + node._timing.duration = node.activeDuration; + } + node = node._parent; + } + if (this._animation) { + this._animation._rebuildUnderlyingAnimation(); + } + }, + _reparent: function(newChildren) { + scope.removeMulti(newChildren); + for (var i = 0; i < newChildren.length; i++) { + newChildren[i]._parent = this; + } + }, + _putChild: function(args, isAppend) { + var message = isAppend ? 'Cannot append an ancestor or self' : 'Cannot prepend an ancestor or self'; + for (var i = 0; i < args.length; i++) { + if (this._isAncestor(args[i])) { + throw { + type: DOMException.HIERARCHY_REQUEST_ERR, + name: 'HierarchyRequestError', + message: message + }; + } + } + var oldParents = []; + for (var i = 0; i < args.length; i++) { + isAppend ? this.children.push(args[i]) : this.children.unshift(args[i]); + } + this._reparent(args); + this._rebuild(); + }, + append: function() { + this._putChild(arguments, true); + }, + prepend: function() { + this._putChild(arguments, false); + }, + get parent() { + return this._parent; + }, + get firstChild() { + return this.children.length ? this.children[0] : null; + }, + get lastChild() { + return this.children.length ? this.children[this.children.length - 1] : null; + }, + clone: function() { + var clonedTiming = shared.cloneTimingInput(this._timingInput); + var clonedChildren = []; + for (var i = 0; i < this.children.length; i++) { + clonedChildren.push(this.children[i].clone()); + } + return (this instanceof GroupEffect) ? + new GroupEffect(clonedChildren, clonedTiming) : + new SequenceEffect(clonedChildren, clonedTiming); + }, + remove: function() { + scope.removeMulti([this]); } }; - window.GroupEffect.prototype = { - get activeDuration() { - var max = 0; - this.children.forEach(function(child) { - max = Math.max(max, groupChildDuration(child)); + window.SequenceEffect.prototype = Object.create(constructor.prototype); + Object.defineProperty( + window.SequenceEffect.prototype, + 'activeDuration', + { + get: function() { + var total = 0; + this.children.forEach(function(child) { + total += groupChildDuration(child); + }); + return Math.max(total, 0); + } + }); + + window.GroupEffect.prototype = Object.create(constructor.prototype); + Object.defineProperty( + window.GroupEffect.prototype, + 'activeDuration', + { + get: function() { + var max = 0; + this.children.forEach(function(child) { + max = Math.max(max, groupChildDuration(child)); + }); + return max; + } }); - return max; - } - }; scope.newUnderlyingAnimationForGroup = function(group) { var underlyingAnimation; var timing = null; var ticker = function(tf) { var animation = underlyingAnimation._wrapper; - if (animation.playState == 'pending') + if (!animation) { return; - - if (!animation.effect) + } + if (animation.playState == 'pending') { return; - + } + if (!animation.effect) { + return; + } if (tf == null) { - animation._removeChildren(); + animation._removeChildAnimations(); return; } // If the group has a negative playback rate and is not fill backwards/both, then it should go // out of effect when it reaches the start of its active interval (tf == 0). If it is fill - // backwards/both then it should stay in effect. calculateTimeFraction will return 0 in the + // backwards/both then it should stay in effect. calculateIterationProgress will return 0 in the // backwards-filling case, and null otherwise. if (tf == 0 && animation.playbackRate < 0) { if (!timing) { timing = shared.normalizeTimingInput(animation.effect.timing); } - tf = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), -1, timing); + tf = shared.calculateIterationProgress(shared.calculateActiveDuration(timing), -1, timing); if (isNaN(tf) || tf == null) { animation._forEachChild(function(child) { child.currentTime = -1; }); - animation._removeChildren(); + animation._removeChildAnimations(); return; } } }; - underlyingAnimation = scope.timeline.play(new scope.KeyframeEffect(null, ticker, group._timing)); + var underlyingEffect = new KeyframeEffect(null, [], group._timing, group._id); + underlyingEffect.onsample = ticker; + underlyingAnimation = scope.timeline._play(underlyingEffect); return underlyingAnimation; }; @@ -98,27 +195,10 @@ animation._animation._wrapper = animation; animation._isGroup = true; scope.awaitStartTime(animation); - animation._constructChildren(); + animation._constructChildAnimations(); animation._setExternalAnimation(animation); }; scope.groupChildDuration = groupChildDuration; - // Alias GroupEffect & SequenceEffect to AnimationGroup & AnimationSequence respectively, to - // support old constructors (Animation*) for a deprecation period. Should be removed after 23 June - // 2015. - window.AnimationSequence = function() { - shared.deprecated('window.AnimationSequence', '2015-03-23', 'Use window.SequenceEffect instead.'); - window.SequenceEffect.apply(this, arguments); - }; - window.AnimationSequence.prototype = Object.create(window.SequenceEffect.prototype); - window.AnimationSequence.prototype.constructor = window.AnimationSequence; - - window.AnimationGroup = function() { - shared.deprecated('window.AnimationGroup', '2015-03-23', 'Use window.GroupEffect instead.'); - window.GroupEffect.apply(this, arguments); - }; - window.AnimationGroup.prototype = Object.create(window.GroupEffect.prototype); - window.AnimationGroup.prototype.constructor = window.AnimationGroup; - })(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/src/keyframe-effect-constructor.js b/src/keyframe-effect-constructor.js index 4e37f8ec..3d0f1bd6 100644 --- a/src/keyframe-effect-constructor.js +++ b/src/keyframe-effect-constructor.js @@ -14,64 +14,127 @@ (function(shared, scope, testing) { - // FIXME: Make this shareable and rename to SharedKeyframeList. + var disassociate = function(effect) { + effect._animation = undefined; + if (effect instanceof window.SequenceEffect || effect instanceof window.GroupEffect) { + for (var i = 0; i < effect.children.length; i++) { + disassociate(effect.children[i]); + } + } + }; + + scope.removeMulti = function(effects) { + var oldParents = []; + for (var i = 0; i < effects.length; i++) { + var effect = effects[i]; + if (effect._parent) { + if (oldParents.indexOf(effect._parent) == -1) { + oldParents.push(effect._parent); + } + effect._parent.children.splice(effect._parent.children.indexOf(effect), 1); + effect._parent = null; + disassociate(effect); + } else if (effect._animation && (effect._animation.effect == effect)) { + effect._animation.cancel(); + effect._animation.effect = new KeyframeEffect(null, []); + if (effect._animation._callback) { + effect._animation._callback._animation = null; + } + effect._animation._rebuildUnderlyingAnimation(); + disassociate(effect); + } + } + for (i = 0; i < oldParents.length; i++) { + oldParents[i]._rebuild(); + } + }; + function KeyframeList(effectInput) { this._frames = shared.normalizeKeyframes(effectInput); } - // FIXME: This constructor is also used for custom effects. This won't be the case once custom - // effects are change to callbacks. - scope.KeyframeEffect = function(target, effectInput, timingInput) { + scope.KeyframeEffect = function(target, effectInput, timingInput, id) { this.target = target; + this._parent = null; - // TODO: Store a clone, not the same instance. - this._timingInput = timingInput; + timingInput = shared.numericTimingToObject(timingInput); + this._timingInput = shared.cloneTimingInput(timingInput); this._timing = shared.normalizeTimingInput(timingInput); - // TODO: Make modifications to timing update the underlying animation - this.timing = shared.makeTiming(timingInput); - // TODO: Make this a live object - will need to separate normalization of keyframes into a - // shared module. - // FIXME: This is a bit weird. Custom effects will soon be implemented as - // callbacks, and effectInput will no longer be allowed to be a function. - if (typeof effectInput == 'function') + this.timing = shared.makeTiming(timingInput, false, this); + this.timing._effect = this; + if (typeof effectInput == 'function') { + shared.deprecated('Custom KeyframeEffect', '2015-06-22', 'Use KeyframeEffect.onsample instead.'); this._normalizedKeyframes = effectInput; - else + } else { this._normalizedKeyframes = new KeyframeList(effectInput); + } this._keyframes = effectInput; this.activeDuration = shared.calculateActiveDuration(this._timing); + this._id = id; return this; }; scope.KeyframeEffect.prototype = { getFrames: function() { - // FIXME: Once custom effects are switched over to callbacks we can - // always return this._normalizedKeyframes._frames here. if (typeof this._normalizedKeyframes == 'function') return this._normalizedKeyframes; return this._normalizedKeyframes._frames; }, - get effect() { - shared.deprecated('KeyframeEffect.effect', '2015-03-23', 'Use KeyframeEffect.getFrames() instead.'); - return this._normalizedKeyframes; + set onsample(callback) { + if (typeof this.getFrames() == 'function') { + throw new Error('Setting onsample on custom effect KeyframeEffect is not supported.'); + } + this._onsample = callback; + if (this._animation) { + this._animation._rebuildUnderlyingAnimation(); + } + }, + get parent() { + return this._parent; + }, + clone: function() { + if (typeof this.getFrames() == 'function') { + throw new Error('Cloning custom effects is not supported.'); + } + var clone = new KeyframeEffect(this.target, [], shared.cloneTimingInput(this._timingInput), this._id); + clone._normalizedKeyframes = this._normalizedKeyframes; + clone._keyframes = this._keyframes; + return clone; + }, + remove: function() { + scope.removeMulti([this]); } }; var originalElementAnimate = Element.prototype.animate; - Element.prototype.animate = function(effectInput, timing) { - return scope.timeline.play(new scope.KeyframeEffect(this, effectInput, timing)); + Element.prototype.animate = function(effectInput, options) { + var id = ''; + if (options && options.id) { + id = options.id; + } + return scope.timeline._play(new scope.KeyframeEffect(this, effectInput, options, id)); }; var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); scope.newUnderlyingAnimationForKeyframeEffect = function(keyframeEffect) { - var target = keyframeEffect.target || nullTarget; - var keyframes = keyframeEffect._keyframes; - if (typeof keyframes == 'function') { - keyframes = []; + if (keyframeEffect) { + var target = keyframeEffect.target || nullTarget; + var keyframes = keyframeEffect._keyframes; + if (typeof keyframes == 'function') { + keyframes = []; + } + var options = keyframeEffect._timingInput; + options.id = keyframeEffect._id; + } else { + var target = nullTarget; + var keyframes = []; + var options = 0; } - return originalElementAnimate.apply(target, [keyframes, keyframeEffect._timingInput]); + return originalElementAnimate.apply(target, [keyframes, options]); }; + // TODO: Remove this once we remove support for custom KeyframeEffects. scope.bindAnimationForKeyframeEffect = function(animation) { if (animation.effect && typeof animation.effect._normalizedKeyframes == 'function') { scope.bindAnimationForCustomEffect(animation); @@ -90,7 +153,8 @@ function updatePendingGroups() { var updated = false; while (pendingGroups.length) { - pendingGroups.shift()._updateChildren(); + var group = pendingGroups.shift(); + group._updateChildren(); updated = true; } return updated; @@ -100,9 +164,11 @@ configurable: true, enumerable: true, value: function() { + scope.timeline._updateAnimationsPromises(); var result = originalGetComputedStyle.apply(this, arguments); if (updatePendingGroups()) result = originalGetComputedStyle.apply(this, arguments); + scope.timeline._updateAnimationsPromises(); return result; }, }); @@ -113,25 +179,5 @@ return animation.effect !== null && animation.effect.target == this; }.bind(this)); }; - window.Element.prototype.getAnimationPlayers = function() { - shared.deprecated('Element.getAnimationPlayers', '2015-03-23', 'Use Element.getAnimations instead.'); - return this.getAnimations(); - }; - - // Alias KeyframeEffect to Animation, to support old constructor (Animation) for a deprecation - // period. Should be removed after 23 June 2015. - // - // This is only on window and not on scope, because the constructor that was called - // webAnimationsNext.Player - now called webAnimationsNext.Animation - is already on the scope. - // - // FIXME: Add this to scope & expose the other scope.Animation (nee scope.Player). I.e. both this - // function and the constructor in web-animations-next-animation should be scope.Animation and - // window.Animation until 23 June 2015. - window.Animation = function() { - shared.deprecated('window.Animation', '2015-03-23', 'Use window.KeyframeEffect instead.'); - window.KeyframeEffect.apply(this, arguments); - }; - window.Animation.prototype = Object.create(window.KeyframeEffect.prototype); - window.Animation.prototype.constructor = window.Animation; }(webAnimationsShared, webAnimationsNext, webAnimationsTesting)); diff --git a/src/keyframe-effect.js b/src/keyframe-effect.js index c910d35e..7775d585 100644 --- a/src/keyframe-effect.js +++ b/src/keyframe-effect.js @@ -18,17 +18,13 @@ var timeFraction = 0; var activeDuration = shared.calculateActiveDuration(timing); var effectTime = function(localTime) { - return shared.calculateTimeFraction(activeDuration, localTime, timing); + return shared.calculateIterationProgress(activeDuration, localTime, timing); }; effectTime._totalDuration = timing.delay + activeDuration + timing.endDelay; - effectTime._isCurrent = function(localTime) { - var phase = shared.calculatePhase(activeDuration, localTime, timing); - return phase === PhaseActive || phase === PhaseBefore; - }; return effectTime; } - scope.KeyframeEffect = function(target, effectInput, timingInput) { + scope.KeyframeEffect = function(target, effectInput, timingInput, id) { var effectTime = EffectTime(shared.normalizeTimingInput(timingInput)); var interpolations = scope.convertEffectInput(effectInput); var timeFraction; @@ -47,31 +43,12 @@ keyframeEffect._hasSameTarget = function(otherTarget) { return target === otherTarget; }; - keyframeEffect._isCurrent = effectTime._isCurrent; + keyframeEffect._target = target; keyframeEffect._totalDuration = effectTime._totalDuration; + keyframeEffect._id = id; return keyframeEffect; }; - scope.NullEffect = function(clear) { - var nullEffect = function() { - if (clear) { - clear(); - clear = null; - } - }; - nullEffect._update = function() { - return null; - }; - nullEffect._totalDuration = 0; - nullEffect._isCurrent = function() { - return false; - }; - nullEffect._hasSameTarget = function() { - return false; - }; - return nullEffect; - }; - if (WEB_ANIMATIONS_TESTING) { testing.webAnimations1KeyframeEffect = scope.KeyframeEffect; testing.effectTime = EffectTime; diff --git a/src/keyframe-interpolations.js b/src/keyframe-interpolations.js index cdd6fc2b..cab801ed 100644 --- a/src/keyframe-interpolations.js +++ b/src/keyframe-interpolations.js @@ -21,13 +21,11 @@ return function(target, fraction) { if (fraction != null) { interpolations.filter(function(interpolation) { - return (fraction <= 0 && interpolation.startTime == 0) || - (fraction >= 1 && interpolation.endTime == 1) || - (fraction >= interpolation.startTime && fraction <= interpolation.endTime); + return fraction >= interpolation.applyFrom && fraction < interpolation.applyTo; }).forEach(function(interpolation) { - var offsetFraction = fraction - interpolation.startTime; - var localDuration = interpolation.endTime - interpolation.startTime; - var scaledLocalTime = localDuration == 0 ? 0 : interpolation.easing(offsetFraction / localDuration); + var offsetFraction = fraction - interpolation.startOffset; + var localDuration = interpolation.endOffset - interpolation.startOffset; + var scaledLocalTime = localDuration == 0 ? 0 : interpolation.easingFunction(offsetFraction / localDuration); scope.apply(target, interpolation.property, interpolation.interpolation(scaledLocalTime)); }); } else { @@ -73,30 +71,45 @@ function makeInterpolations(propertySpecificKeyframeGroups) { var interpolations = []; for (var groupName in propertySpecificKeyframeGroups) { - var group = propertySpecificKeyframeGroups[groupName]; - for (var i = 0; i < group.length - 1; i++) { - var startTime = group[i].offset; - var endTime = group[i + 1].offset; - var startValue = group[i].value; - var endValue = group[i + 1].value; - if (startTime == endTime) { - if (endTime == 1) { - startValue = endValue; - } else { - endValue = startValue; + var keyframes = propertySpecificKeyframeGroups[groupName]; + for (var i = 0; i < keyframes.length - 1; i++) { + var startIndex = i; + var endIndex = i + 1; + var startOffset = keyframes[startIndex].offset; + var endOffset = keyframes[endIndex].offset; + var applyFrom = startOffset; + var applyTo = endOffset; + + if (i == 0) { + applyFrom = -Infinity; + WEB_ANIMATIONS_TESTING && console.assert(startOffset == 0); + if (endOffset == 0) { + endIndex = startIndex; } } + if (i == keyframes.length - 2) { + applyTo = Infinity; + WEB_ANIMATIONS_TESTING && console.assert(endOffset == 1); + if (startOffset == 1) { + startIndex = endIndex; + } + } + interpolations.push({ - startTime: startTime, - endTime: endTime, - easing: group[i].easing, + applyFrom: applyFrom, + applyTo: applyTo, + startOffset: keyframes[startIndex].offset, + endOffset: keyframes[endIndex].offset, + easingFunction: shared.parseEasingFunction(keyframes[startIndex].easing), property: groupName, - interpolation: scope.propertyInterpolation(groupName, startValue, endValue) + interpolation: scope.propertyInterpolation(groupName, + keyframes[startIndex].value, + keyframes[endIndex].value) }); } } interpolations.sort(function(leftInterpolation, rightInterpolation) { - return leftInterpolation.startTime - rightInterpolation.startTime; + return leftInterpolation.startOffset - rightInterpolation.startOffset; }); return interpolations; } diff --git a/src/matrix-decomposition.js b/src/matrix-decomposition.js index c825372e..aa9cfe76 100644 --- a/src/matrix-decomposition.js +++ b/src/matrix-decomposition.js @@ -97,8 +97,6 @@ v1[0] * v2[1] - v1[1] * v2[0]]; } - // TODO: Implement 2D matrix decomposition. - // http://dev.w3.org/csswg/css-transforms/#decomposing-a-2d-matrix function decomposeMatrix(matrix) { var m3d = [ matrix.slice(0, 4), @@ -122,7 +120,7 @@ } if (determinant(perspectiveMatrix) === 0) { - return false; + return null; } var rhs = []; @@ -255,31 +253,32 @@ ]; } - // TODO: This can probably be made smaller. + function toRadians(arg) { + var rads = arg.rad || 0; + var degs = arg.deg || 0; + var grads = arg.grad || 0; + var turns = arg.turn || 0; + var angle = (degs / 360 + grads / 400 + turns) * (2 * Math.PI) + rads; + return angle; + } + function convertItemToMatrix(item) { switch (item.t) { - // TODO: Handle units other than rads and degs. case 'rotatex': - var rads = item.d[0].rad || 0; - var degs = item.d[0].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[0]); return [1, 0, 0, 0, 0, Math.cos(angle), Math.sin(angle), 0, 0, -Math.sin(angle), Math.cos(angle), 0, 0, 0, 0, 1]; case 'rotatey': - var rads = item.d[0].rad || 0; - var degs = item.d[0].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[0]); return [Math.cos(angle), 0, -Math.sin(angle), 0, 0, 1, 0, 0, Math.sin(angle), 0, Math.cos(angle), 0, 0, 0, 0, 1]; case 'rotate': case 'rotatez': - var rads = item.d[0].rad || 0; - var degs = item.d[0].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[0]); return [Math.cos(angle), Math.sin(angle), 0, 0, -Math.sin(angle), Math.cos(angle), 0, 0, 0, 0, 1, 0, @@ -288,9 +287,7 @@ var x = item.d[0]; var y = item.d[1]; var z = item.d[2]; - var rads = item.d[3].rad || 0; - var degs = item.d[3].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[3]); var sqrLength = x * x + y * y + z * z; if (sqrLength === 0) { @@ -350,35 +347,25 @@ 0, item.d[1], 0, 0, 0, 0, item.d[2], 0, 0, 0, 0, 1]; - // FIXME: Skew behaves differently in Blink, FireFox and here. Need to work out why. case 'skew': - var xDegs = item.d[0].deg || 0; - var xRads = item.d[0].rad || 0; - var yDegs = item.d[1].deg || 0; - var yRads = item.d[1].rad || 0; - var xAngle = (xDegs * Math.PI / 180) + xRads; - var yAngle = (yDegs * Math.PI / 180) + yRads; + var xAngle = toRadians(item.d[0]); + var yAngle = toRadians(item.d[1]); return [1, Math.tan(yAngle), 0, 0, Math.tan(xAngle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; case 'skewx': - var rads = item.d[0].rad || 0; - var degs = item.d[0].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[0]); return [1, 0, 0, 0, Math.tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; case 'skewy': - var rads = item.d[0].rad || 0; - var degs = item.d[0].deg || 0; - var angle = (degs * Math.PI / 180) + rads; + var angle = toRadians(item.d[0]); return [1, Math.tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; - // TODO: Work out what to do with non-px values. case 'translate': var x = item.d[0].px || 0; var y = item.d[1].px || 0; @@ -448,5 +435,6 @@ scope.dot = dot; scope.makeMatrixDecomposition = makeMatrixDecomposition; + scope.transformListToMatrix = convertToMatrix; })(webAnimations1, webAnimationsTesting); diff --git a/src/normalize-keyframes.js b/src/normalize-keyframes.js index dbab8bf8..1337e47a 100644 --- a/src/normalize-keyframes.js +++ b/src/normalize-keyframes.js @@ -150,8 +150,16 @@ return value; } + function isNotAnimatable(property) { + // https://drafts.csswg.org/web-animations/#concept-not-animatable + return property === 'display' || property.lastIndexOf('animation', 0) === 0 || property.lastIndexOf('transition', 0) === 0; + } + // This delegates parsing shorthand value syntax to the browser. function expandShorthandAndAntiAlias(property, value, result) { + if (isNotAnimatable(property)) { + return; + } var longProperties = shorthandToLonghand[property]; if (longProperties) { shorthandExpanderElem.style[property] = value; @@ -165,12 +173,63 @@ } }; - function normalizeKeyframes(effectInput) { - if (!Array.isArray(effectInput) && effectInput !== null) - throw new TypeError('Keyframes must be null or an array of keyframes'); + function convertToArrayForm(effectInput) { + var normalizedEffectInput = []; + + for (var property in effectInput) { + if (property in ['easing', 'offset', 'composite']) { + continue; + } + + var values = effectInput[property]; + if (!Array.isArray(values)) { + values = [values]; + } - if (effectInput == null) + var keyframe; + var numKeyframes = values.length; + for (var i = 0; i < numKeyframes; i++) { + keyframe = {}; + + if ('offset' in effectInput) { + keyframe.offset = effectInput.offset; + } else if (numKeyframes == 1) { + keyframe.offset = 1.0; + } else { + keyframe.offset = i / (numKeyframes - 1.0); + } + + if ('easing' in effectInput) { + keyframe.easing = effectInput.easing; + } + + if ('composite' in effectInput) { + keyframe.composite = effectInput.composite; + } + + keyframe[property] = values[i]; + + normalizedEffectInput.push(keyframe); + } + } + + normalizedEffectInput.sort(function(a, b) { return a.offset - b.offset; }); + return normalizedEffectInput; + }; + + function normalizeKeyframes(effectInput) { + if (effectInput == null) { return []; + } + + if (window.Symbol && Symbol.iterator && Array.prototype.from && effectInput[Symbol.iterator]) { + // Handle custom iterables in most browsers by converting to an array + effectInput = Array.from(effectInput); + } + + if (!Array.isArray(effectInput)) { + effectInput = convertToArrayForm(effectInput); + } var keyframes = effectInput.map(function(originalKeyframe) { var keyframe = {}; @@ -180,16 +239,22 @@ if (memberValue != null) { memberValue = Number(memberValue); if (!isFinite(memberValue)) - throw new TypeError('keyframe offsets must be numbers.'); + throw new TypeError('Keyframe offsets must be numbers.'); + if (memberValue < 0 || memberValue > 1) + throw new TypeError('Keyframe offsets must be between 0 and 1.'); } } else if (member == 'composite') { - throw { - type: DOMException.NOT_SUPPORTED_ERR, - name: 'NotSupportedError', - message: 'add compositing is not supported' - }; + if (memberValue == 'add' || memberValue == 'accumulate') { + throw { + type: DOMException.NOT_SUPPORTED_ERR, + name: 'NotSupportedError', + message: 'add compositing is not supported' + }; + } else if (memberValue != 'replace') { + throw new TypeError('Invalid composite mode ' + memberValue + '.'); + } } else if (member == 'easing') { - memberValue = shared.toTimingFunction(memberValue); + memberValue = shared.normalizeEasing(memberValue); } else { memberValue = '' + memberValue; } @@ -198,7 +263,7 @@ if (keyframe.offset == undefined) keyframe.offset = null; if (keyframe.easing == undefined) - keyframe.easing = shared.toTimingFunction('linear'); + keyframe.easing = 'linear'; return keyframe; }); @@ -209,11 +274,7 @@ var offset = keyframes[i].offset; if (offset != null) { if (offset < previousOffset) { - throw { - code: DOMException.INVALID_MODIFICATION_ERR, - name: 'InvalidModificationError', - message: 'Keyframes are not loosely sorted by offset. Sort or specify offsets.' - }; + throw new TypeError('Keyframes are not loosely sorted by offset. Sort or specify offsets.'); } previousOffset = offset; } else { @@ -250,6 +311,7 @@ return keyframes; } + shared.convertToArrayForm = convertToArrayForm; shared.normalizeKeyframes = normalizeKeyframes; if (WEB_ANIMATIONS_TESTING) { diff --git a/src/number-handler.js b/src/number-handler.js index 75093739..7d0e7f9b 100644 --- a/src/number-handler.js +++ b/src/number-handler.js @@ -15,7 +15,7 @@ (function(scope, testing) { function numberToString(x) { - return x.toFixed(3).replace('.000', ''); + return x.toFixed(3).replace(/0+$/, '').replace(/\.$/, ''); } function clamp(min, max, x) { @@ -52,11 +52,37 @@ }; } + function parseNumberList(string) { + var items = string.trim().split(/\s*[\s,]\s*/); + if (items.length === 0) { + return; + } + var result = []; + for (var i = 0; i < items.length; i++) { + var number = parseNumber(items[i]); + if (number === undefined) { + return; + } + result.push(number); + } + return result; + } + + function mergeNumberLists(left, right) { + if (left.length != right.length) { + return; + } + return [left, right, function(numberList) { + return numberList.map(numberToString).join(' '); + }]; + } + function round(left, right) { return [left, right, Math.round]; } scope.clamp = clamp; + scope.addPropertiesHandler(parseNumberList, mergeNumberLists, ['stroke-dasharray']); scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, Infinity), ['border-image-width', 'line-height']); scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, 1), ['opacity', 'shape-image-threshold']); scope.addPropertiesHandler(parseNumber, mergeFlex, ['flex-grow', 'flex-shrink']); @@ -64,6 +90,7 @@ scope.addPropertiesHandler(parseNumber, round, ['z-index']); scope.parseNumber = parseNumber; + scope.parseNumberList = parseNumberList; scope.mergeNumbers = mergeNumbers; scope.numberToString = numberToString; diff --git a/src/property-interpolation.js b/src/property-interpolation.js index 8634bf6b..b7e594f3 100644 --- a/src/property-interpolation.js +++ b/src/property-interpolation.js @@ -12,10 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -(function(scope, testing) { +(function(shared, scope, testing) { var propertyHandlers = {}; + function toCamelCase(property) { + return property.replace(/-(.)/g, function(_, c) { + return c.toUpperCase(); + }); + } + function addPropertyHandler(parser, merger, property) { propertyHandlers[property] = propertyHandlers[property] || []; propertyHandlers[property].push([parser, merger]); @@ -24,19 +30,79 @@ for (var i = 0; i < properties.length; i++) { var property = properties[i]; WEB_ANIMATIONS_TESTING && console.assert(property.toLowerCase() === property); - addPropertyHandler(parser, merger, property); - if (/-/.test(property)) { - // Add camel cased variant. - addPropertyHandler(parser, merger, property.replace(/-(.)/g, function(_, c) { - return c.toUpperCase(); - })); - } + addPropertyHandler(parser, merger, toCamelCase(property)); } } scope.addPropertiesHandler = addPropertiesHandler; + var initialValues = { + backgroundColor: 'transparent', + backgroundPosition: '0% 0%', + borderBottomColor: 'currentColor', + borderBottomLeftRadius: '0px', + borderBottomRightRadius: '0px', + borderBottomWidth: '3px', + borderLeftColor: 'currentColor', + borderLeftWidth: '3px', + borderRightColor: 'currentColor', + borderRightWidth: '3px', + // Spec says this should be 0 but in practise it is 2px. + borderSpacing: '2px', + borderTopColor: 'currentColor', + borderTopLeftRadius: '0px', + borderTopRightRadius: '0px', + borderTopWidth: '3px', + bottom: 'auto', + clip: 'rect(0px, 0px, 0px, 0px)', + color: 'black', // Depends on user agent. + fontSize: '100%', + fontWeight: '400', + height: 'auto', + left: 'auto', + letterSpacing: 'normal', + lineHeight: '120%', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + maxHeight: 'none', + maxWidth: 'none', + minHeight: '0px', + minWidth: '0px', + opacity: '1.0', + outlineColor: 'invert', + outlineOffset: '0px', + outlineWidth: '3px', + paddingBottom: '0px', + paddingLeft: '0px', + paddingRight: '0px', + paddingTop: '0px', + right: 'auto', + strokeDasharray: 'none', + strokeDashoffset: '0px', + textIndent: '0px', + textShadow: '0px 0px 0px transparent', + top: 'auto', + transform: '', + verticalAlign: '0px', + visibility: 'visible', + width: 'auto', + wordSpacing: 'normal', + zIndex: 'auto' + }; + function propertyInterpolation(property, left, right) { - var handlers = left == right ? [] : propertyHandlers[property]; + var ucProperty = property; + if (/-/.test(property) && !shared.isDeprecated('Hyphenated property names', '2016-03-22', 'Use camelCase instead.', true)) { + ucProperty = toCamelCase(property); + } + if (left == 'initial' || right == 'initial') { + if (left == 'initial') + left = initialValues[ucProperty]; + if (right == 'initial') + right = initialValues[ucProperty]; + } + var handlers = left == right ? [] : propertyHandlers[ucProperty]; for (var i = 0; handlers && i < handlers.length; i++) { var parsedLeft = handlers[i][0](left); var parsedRight = handlers[i][0](right); @@ -58,5 +124,4 @@ } scope.propertyInterpolation = propertyInterpolation; -})(webAnimations1, webAnimationsTesting); - +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/src/property-names.js b/src/property-names.js index c52d990c..f106c066 100644 --- a/src/property-names.js +++ b/src/property-names.js @@ -14,13 +14,15 @@ (function(scope, testing) { - var aliased = {}; + var prefixed = {}; + var unprefixed = {}; function alias(name, aliases) { aliases.concat([name]).forEach(function(candidate) { if (candidate in document.documentElement.style) { - aliased[name] = candidate; + prefixed[name] = candidate; } + unprefixed[candidate] = name; }); } alias('transform', ['webkitTransform', 'msTransform']); @@ -29,7 +31,10 @@ alias('perspectiveOrigin', ['webkitPerspectiveOrigin']); scope.propertyName = function(property) { - return aliased[property] || property; + return prefixed[property] || property; + }; + scope.unprefixedPropertyName = function(property) { + return unprefixed[property] || property; }; })(webAnimations1, webAnimationsTesting); diff --git a/src/shadow-handler.js b/src/shadow-handler.js index 3f8201d8..9a28b74b 100644 --- a/src/shadow-handler.js +++ b/src/shadow-handler.js @@ -26,12 +26,12 @@ shadow.inset = true; return result; } - var result = scope.consumeLengthOrPercent(string); + result = scope.consumeLengthOrPercent(string); if (result) { shadow.lengths.push(result[0]); return result; } - var result = scope.consumeColor(string); + result = scope.consumeColor(string); if (result) { shadow.color = result[0]; return result; diff --git a/src/tick.js b/src/tick.js index 57baac41..08b0a140 100644 --- a/src/tick.js +++ b/src/tick.js @@ -37,11 +37,13 @@ function processRafCallbacks(t) { var processing = rafCallbacks; rafCallbacks = []; - tick(t); + if (t < timeline.currentTime) + t = timeline.currentTime; + timeline._animations.sort(compareAnimations); + timeline._animations = tick(t, true, timeline._animations)[0]; processing.forEach(function(entry) { entry[1](t); }); - if (needsRetick) - tick(t); applyPendingEffects(); + _now = undefined; } function compareAnimations(leftAnimation, rightAnimation) { @@ -62,11 +64,23 @@ animation._timeline = this; this._animations.push(animation); scope.restart(); - scope.invalidateEffects(); + scope.applyDirtiedAnimation(animation); return animation; } }; + var _now = undefined; + + if (WEB_ANIMATIONS_TESTING) { + var now = function() { return timeline.currentTime; }; + } else { + var now = function() { + if (_now == undefined) + _now = window.performance && performance.now ? performance.now() : Date.now(); + return _now; + }; + } + var ticking = false; var hasRestartedThisFrame = false; @@ -79,9 +93,25 @@ return hasRestartedThisFrame; }; - var needsRetick = false; - scope.invalidateEffects = function() { - needsRetick = true; + // RAF is supposed to be the last script to occur before frame rendering but not + // all browsers behave like this. This function is for synchonously updating an + // animation's effects whenever its state is mutated by script to work around + // incorrect script execution ordering by the browser. + scope.applyDirtiedAnimation = function(animation) { + if (inTick) { + return; + } + animation._markTarget(); + var animations = animation._targetAnimations(); + animations.sort(compareAnimations); + var inactiveAnimations = tick(scope.timeline.currentTime, false, animations.slice())[1]; + inactiveAnimations.forEach(function(animation) { + var index = timeline._animations.indexOf(animation); + if (index !== -1) { + timeline._animations.splice(index, 1); + } + }); + applyPendingEffects(); }; var pendingEffects = []; @@ -90,55 +120,57 @@ pendingEffects.length = 0; } - var originalGetComputedStyle = window.getComputedStyle; - Object.defineProperty(window, 'getComputedStyle', { - configurable: true, - enumerable: true, - value: function() { - if (needsRetick) tick(timeline.currentTime); - applyPendingEffects(); - return originalGetComputedStyle.apply(this, arguments); - }, - }); - - function tick(t) { + var t60hz = 1000 / 60; + + var inTick = false; + function tick(t, isAnimationFrame, updatingAnimations) { + inTick = true; hasRestartedThisFrame = false; var timeline = scope.timeline; + timeline.currentTime = t; - timeline._animations.sort(compareAnimations); ticking = false; - var updatingAnimations = timeline._animations; - timeline._animations = []; var newPendingClears = []; var newPendingEffects = []; - updatingAnimations = updatingAnimations.filter(function(animation) { - animation._inTimeline = animation._tick(t); + var activeAnimations = []; + var inactiveAnimations = []; + updatingAnimations.forEach(function(animation) { + animation._tick(t, isAnimationFrame); - if (!animation._inEffect) + if (!animation._inEffect) { newPendingClears.push(animation._effect); - else + animation._unmarkTarget(); + } else { newPendingEffects.push(animation._effect); + animation._markTarget(); + } - if (!animation.finished && !animation.paused && !animation._idle) + if (animation._needsTick) ticking = true; - return animation._inTimeline; + var alive = animation._inEffect || animation._needsTick; + animation._inTimeline = alive; + if (alive) { + activeAnimations.push(animation); + } else { + inactiveAnimations.push(animation); + } }); // FIXME: Should remove dupliactes from pendingEffects. pendingEffects.push.apply(pendingEffects, newPendingClears); pendingEffects.push.apply(pendingEffects, newPendingEffects); - timeline._animations.push.apply(timeline._animations, updatingAnimations); - needsRetick = false; - if (ticking) requestAnimationFrame(function() {}); + + inTick = false; + return [activeAnimations, inactiveAnimations]; }; if (WEB_ANIMATIONS_TESTING) { - testing.tick = processRafCallbacks; + testing.tick = function(t) { timeline.currentTime = t; processRafCallbacks(t); }; testing.isTicking = function() { return ticking; }; testing.setTicking = function(newVal) { ticking = newVal; }; } diff --git a/src/timeline.js b/src/timeline.js index 0209e2df..2b213b55 100644 --- a/src/timeline.js +++ b/src/timeline.js @@ -14,6 +14,14 @@ (function(shared, scope, testing) { + var originalRequestAnimationFrame = window.requestAnimationFrame; + window.requestAnimationFrame = function(f) { + return originalRequestAnimationFrame(function(x) { + scope.timeline._updateAnimationsPromises(); + f(x); + scope.timeline._updateAnimationsPromises(); + }); + }; scope.AnimationTimeline = function() { this._animations = []; @@ -21,24 +29,23 @@ }; scope.AnimationTimeline.prototype = { - // FIXME: This needs to return the wrapped animations in Web Animations Next - // TODO: Does this need to be sorted? - // TODO: Do we need to consider needsRetick? getAnimations: function() { this._discardAnimations(); return this._animations.slice(); }, - getAnimationPlayers: function() { - shared.deprecated('AnimationTimeline.getAnimationPlayers', '2015-03-23', 'Use AnimationTimeline.getAnimations instead.'); - return this.getAnimations(); + _updateAnimationsPromises: function() { + scope.animationsWithPromises = scope.animationsWithPromises.filter(function(animation) { + return animation._updatePromises(); + }); }, _discardAnimations: function() { + this._updateAnimationsPromises(); this._animations = this._animations.filter(function(animation) { return animation.playState != 'finished' && animation.playState != 'idle'; }); }, - play: function(effect) { - var animation = new scope.Animation(effect); + _play: function(effect) { + var animation = new scope.Animation(effect, this); this._animations.push(animation); scope.restartWebAnimationsNextTick(); // Use animation._animation.play() here, NOT animation.play(). @@ -46,9 +53,17 @@ // Timeline.play calls new scope.Animation(effect) which (indirectly) calls Timeline.play on // effect's children, and Animation.play is also recursive. We only need to call play on each // animation in the tree once. + animation._updatePromises(); animation._animation.play(); + animation._updatePromises(); return animation; }, + play: function(effect) { + if (effect) { + effect.remove(); + } + return this._play(effect); + } }; var ticking = false; @@ -61,7 +76,7 @@ }; function webAnimationsNextTick(t) { - var timeline = window.document.timeline; + var timeline = scope.timeline; timeline.currentTime = t; timeline._discardAnimations(); if (timeline._animations.length == 0) diff --git a/src/timing-utilities.js b/src/timing-utilities.js index 43558cc7..eb4ef7a5 100644 --- a/src/timing-utilities.js +++ b/src/timing-utilities.js @@ -16,19 +16,117 @@ var fills = 'backwards|forwards|both|none'.split('|'); var directions = 'reverse|alternate|alternate-reverse'.split('|'); + var linear = function(x) { return x; }; + + function cloneTimingInput(timingInput) { + if (typeof timingInput == 'number') { + return timingInput; + } + var clone = {}; + for (var m in timingInput) { + clone[m] = timingInput[m]; + } + return clone; + } + + function AnimationEffectTiming() { + this._delay = 0; + this._endDelay = 0; + this._fill = 'none'; + this._iterationStart = 0; + this._iterations = 1; + this._duration = 0; + this._playbackRate = 1; + this._direction = 'normal'; + this._easing = 'linear'; + this._easingFunction = linear; + } + + function isInvalidTimingDeprecated() { + return shared.isDeprecated('Invalid timing inputs', '2016-03-02', 'TypeError exceptions will be thrown instead.', true); + } + + AnimationEffectTiming.prototype = { + _setMember: function(member, value) { + this['_' + member] = value; + if (this._effect) { + this._effect._timingInput[member] = value; + this._effect._timing = shared.normalizeTimingInput(this._effect._timingInput); + this._effect.activeDuration = shared.calculateActiveDuration(this._effect._timing); + if (this._effect._animation) { + this._effect._animation._rebuildUnderlyingAnimation(); + } + } + }, + get playbackRate() { + return this._playbackRate; + }, + set delay(value) { + this._setMember('delay', value); + }, + get delay() { + return this._delay; + }, + set endDelay(value) { + this._setMember('endDelay', value); + }, + get endDelay() { + return this._endDelay; + }, + set fill(value) { + this._setMember('fill', value); + }, + get fill() { + return this._fill; + }, + set iterationStart(value) { + if ((isNaN(value) || value < 0) && isInvalidTimingDeprecated()) { + throw new TypeError('iterationStart must be a non-negative number, received: ' + value); + } + this._setMember('iterationStart', value); + }, + get iterationStart() { + return this._iterationStart; + }, + set duration(value) { + if (value != 'auto' && (isNaN(value) || value < 0) && isInvalidTimingDeprecated()) { + throw new TypeError('duration must be non-negative or auto, received: ' + value); + } + this._setMember('duration', value); + }, + get duration() { + return this._duration; + }, + set direction(value) { + this._setMember('direction', value); + }, + get direction() { + return this._direction; + }, + set easing(value) { + this._easingFunction = parseEasingFunction(normalizeEasing(value)); + this._setMember('easing', value); + }, + get easing() { + return this._easing; + }, + set iterations(value) { + if ((isNaN(value) || value < 0) && isInvalidTimingDeprecated()) { + throw new TypeError('iterations must be non-negative, received: ' + value); + } + this._setMember('iterations', value); + }, + get iterations() { + return this._iterations; + } + }; - function makeTiming(timingInput, forGroup) { - var timing = { - delay: 0, - endDelay: 0, - fill: forGroup ? 'both' : 'none', - iterationStart: 0, - iterations: 1, - duration: forGroup ? 'auto' : 0, - playbackRate: 1, - direction: 'normal', - easing: 'linear', - }; + function makeTiming(timingInput, forGroup, effect) { + var timing = new AnimationEffectTiming(); + if (forGroup) { + timing.fill = 'both'; + timing.duration = 'auto'; + } if (typeof timingInput == 'number' && !isNaN(timingInput)) { timing.duration = timingInput; } else if (timingInput !== undefined) { @@ -55,10 +153,20 @@ return timing; } + function numericTimingToObject(timingInput) { + if (typeof timingInput == 'number') { + if (isNaN(timingInput)) { + timingInput = { duration: 0 }; + } else { + timingInput = { duration: timingInput }; + } + } + return timingInput; + } + function normalizeTimingInput(timingInput, forGroup) { - var timing = makeTiming(timingInput, forGroup); - timing.easing = toTimingFunction(timing.easing); - return timing; + timingInput = shared.numericTimingToObject(timingInput); + return makeTiming(timingInput, forGroup); } function cubic(a, b, c, d) { @@ -66,12 +174,29 @@ return linear; } return function(x) { + if (x <= 0) { + var start_gradient = 0; + if (a > 0) + start_gradient = b / a; + else if (!b && c > 0) + start_gradient = d / c; + return start_gradient * x; + } + if (x >= 1) { + var end_gradient = 0; + if (c < 1) + end_gradient = (d - 1) / (c - 1); + else if (c == 1 && a < 1) + end_gradient = (b - 1) / (a - 1); + return 1 + end_gradient * (x - 1); + } + var start = 0, end = 1; - while (1) { + function f(a, b, m) { return 3 * a * (1 - m) * (1 - m) * m + 3 * b * (1 - m) * m * m + m * m * m}; + while (start < end) { var mid = (start + end) / 2; - function f(a, b, m) { return 3 * a * (1 - m) * (1 - m) * m + 3 * b * (1 - m) * m * m + m * m * m}; var xEst = f(a, c, mid); - if (Math.abs(x - xEst) < 0.001) { + if (Math.abs(x - xEst) < 0.00001) { return f(b, d, mid); } if (xEst < x) { @@ -80,6 +205,7 @@ end = mid; } } + return f(b, d, mid); } } @@ -108,32 +234,59 @@ 'step-end': step(1, End) }; + var styleForCleaning = null; var numberString = '\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*'; var cubicBezierRe = new RegExp('cubic-bezier\\(' + numberString + ',' + numberString + ',' + numberString + ',' + numberString + '\\)'); - var stepRe = /steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/; - var linear = function(x) { return x; }; + var step1Re = /steps\(\s*(\d+)\s*\)/; + var step2Re = /steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/; - function toTimingFunction(easing) { - var cubicData = cubicBezierRe.exec(easing); + function normalizeEasing(easing) { + if (!styleForCleaning) { + styleForCleaning = document.createElement('div').style; + } + styleForCleaning.animationTimingFunction = ''; + styleForCleaning.animationTimingFunction = easing; + var normalizedEasing = styleForCleaning.animationTimingFunction; + if (normalizedEasing == '' && isInvalidTimingDeprecated()) { + throw new TypeError(easing + ' is not a valid value for easing'); + } + return normalizedEasing; + } + + function parseEasingFunction(normalizedEasing) { + if (normalizedEasing == 'linear') { + return linear; + } + var cubicData = cubicBezierRe.exec(normalizedEasing); if (cubicData) { return cubic.apply(this, cubicData.slice(1).map(Number)); } - var stepData = stepRe.exec(easing); - if (stepData) { - return step(Number(stepData[1]), {'start': Start, 'middle': Middle, 'end': End}[stepData[2]]); + var step1Data = step1Re.exec(normalizedEasing); + if (step1Data) { + return step(Number(step1Data[1]), End); + } + var step2Data = step2Re.exec(normalizedEasing); + if (step2Data) { + return step(Number(step2Data[1]), {'start': Start, 'middle': Middle, 'end': End}[step2Data[2]]); } - var preset = presets[easing]; + var preset = presets[normalizedEasing]; if (preset) { return preset; } + // At this point none of our parse attempts succeeded; the easing is invalid. + // Fall back to linear in the interest of not crashing the page. return linear; - }; + } function calculateActiveDuration(timing) { return Math.abs(repeatedDuration(timing) / timing.playbackRate); } function repeatedDuration(timing) { + // https://drafts.csswg.org/web-animations/#calculating-the-active-duration + if (timing.duration === 0 || timing.iterations === 0) { + return 0; + } return timing.duration * timing.iterations; } @@ -143,19 +296,24 @@ var PhaseActive = 3; function calculatePhase(activeDuration, localTime, timing) { + // https://drafts.csswg.org/web-animations/#animation-effect-phases-and-states if (localTime == null) { return PhaseNone; } - if (localTime < timing.delay) { + + var endTime = timing.delay + activeDuration + timing.endDelay; + if (localTime < Math.min(timing.delay, endTime)) { return PhaseBefore; } - if (localTime >= timing.delay + activeDuration) { + if (localTime >= Math.min(timing.delay + activeDuration, endTime)) { return PhaseAfter; } + return PhaseActive; } function calculateActiveTime(activeDuration, fillMode, localTime, phase, delay) { + // https://drafts.csswg.org/web-animations/#calculating-the-active-time switch (phase) { case PhaseBefore: if (fillMode == 'backwards' || fillMode == 'both') @@ -172,71 +330,96 @@ } } - function calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing) { - return (timing.playbackRate < 0 ? activeTime - activeDuration : activeTime) * timing.playbackRate + startOffset; + function calculateOverallProgress(iterationDuration, phase, iterations, activeTime, iterationStart) { + // https://drafts.csswg.org/web-animations/#calculating-the-overall-progress + var overallProgress = iterationStart; + if (iterationDuration === 0) { + if (phase !== PhaseBefore) { + overallProgress += iterations; + } + } else { + overallProgress += activeTime / iterationDuration; + } + return overallProgress; } - function calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, timing) { - if (scaledActiveTime === Infinity || scaledActiveTime === -Infinity || (scaledActiveTime - startOffset == repeatedDuration && timing.iterations && ((timing.iterations + timing.iterationStart) % 1 == 0))) { - return iterationDuration; - } + function calculateSimpleIterationProgress(overallProgress, iterationStart, phase, iterations, activeTime, iterationDuration) { + // https://drafts.csswg.org/web-animations/#calculating-the-simple-iteration-progress - return scaledActiveTime % iterationDuration; + var simpleIterationProgress = (overallProgress === Infinity) ? iterationStart % 1 : overallProgress % 1; + if (simpleIterationProgress === 0 && phase === PhaseAfter && iterations !== 0 && + (activeTime !== 0 || iterationDuration === 0)) { + simpleIterationProgress = 1; + } + return simpleIterationProgress; } - function calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, timing) { - if (scaledActiveTime === 0) { - return 0; + function calculateCurrentIteration(phase, iterations, simpleIterationProgress, overallProgress) { + // https://drafts.csswg.org/web-animations/#calculating-the-current-iteration + if (phase === PhaseAfter && iterations === Infinity) { + return Infinity; } - if (iterationTime == iterationDuration) { - return timing.iterationStart + timing.iterations - 1; + if (simpleIterationProgress === 1) { + return Math.floor(overallProgress) - 1; } - return Math.floor(scaledActiveTime / iterationDuration); + return Math.floor(overallProgress); } - function calculateTransformedTime(currentIteration, iterationDuration, iterationTime, timing) { - var currentIterationIsOdd = currentIteration % 2 >= 1; - var currentDirectionIsForwards = timing.direction == 'normal' || timing.direction == (currentIterationIsOdd ? 'alternate-reverse' : 'alternate'); - var directedTime = currentDirectionIsForwards ? iterationTime : iterationDuration - iterationTime; - var timeFraction = directedTime / iterationDuration; - return iterationDuration * timing.easing(timeFraction); + function calculateDirectedProgress(playbackDirection, currentIteration, simpleIterationProgress) { + // https://drafts.csswg.org/web-animations/#calculating-the-directed-progress + var currentDirection = playbackDirection; + if (playbackDirection !== 'normal' && playbackDirection !== 'reverse') { + var d = currentIteration; + if (playbackDirection === 'alternate-reverse') { + d += 1; + } + currentDirection = 'normal'; + if (d !== Infinity && d % 2 !== 0) { + currentDirection = 'reverse'; + } + } + if (currentDirection === 'normal') { + return simpleIterationProgress; + } + return 1 - simpleIterationProgress; } - function calculateTimeFraction(activeDuration, localTime, timing) { + function calculateIterationProgress(activeDuration, localTime, timing) { var phase = calculatePhase(activeDuration, localTime, timing); var activeTime = calculateActiveTime(activeDuration, timing.fill, localTime, phase, timing.delay); if (activeTime === null) return null; - if (activeDuration === 0) - return phase === PhaseBefore ? 0 : 1; - var startOffset = timing.iterationStart * timing.duration; - var scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing); - var iterationTime = calculateIterationTime(timing.duration, repeatedDuration(timing), scaledActiveTime, startOffset, timing); - var currentIteration = calculateCurrentIteration(timing.duration, iterationTime, scaledActiveTime, timing); - return calculateTransformedTime(currentIteration, timing.duration, iterationTime, timing) / timing.duration; + + var overallProgress = calculateOverallProgress(timing.duration, phase, timing.iterations, activeTime, timing.iterationStart); + var simpleIterationProgress = calculateSimpleIterationProgress(overallProgress, timing.iterationStart, phase, timing.iterations, activeTime, timing.duration); + var currentIteration = calculateCurrentIteration(phase, timing.iterations, simpleIterationProgress, overallProgress); + var directedProgress = calculateDirectedProgress(timing.direction, currentIteration, simpleIterationProgress); + + // https://drafts.csswg.org/web-animations/#calculating-the-transformed-progress + // https://drafts.csswg.org/web-animations/#calculating-the-iteration-progress + return timing._easingFunction(directedProgress); } + shared.cloneTimingInput = cloneTimingInput; shared.makeTiming = makeTiming; + shared.numericTimingToObject = numericTimingToObject; shared.normalizeTimingInput = normalizeTimingInput; shared.calculateActiveDuration = calculateActiveDuration; - shared.calculateTimeFraction = calculateTimeFraction; + shared.calculateIterationProgress = calculateIterationProgress; shared.calculatePhase = calculatePhase; - shared.toTimingFunction = toTimingFunction; + shared.normalizeEasing = normalizeEasing; + shared.parseEasingFunction = parseEasingFunction; if (WEB_ANIMATIONS_TESTING) { testing.normalizeTimingInput = normalizeTimingInput; - testing.toTimingFunction = toTimingFunction; + testing.normalizeEasing = normalizeEasing; + testing.parseEasingFunction = parseEasingFunction; testing.calculateActiveDuration = calculateActiveDuration; testing.calculatePhase = calculatePhase; testing.PhaseNone = PhaseNone; testing.PhaseBefore = PhaseBefore; testing.PhaseActive = PhaseActive; testing.PhaseAfter = PhaseAfter; - testing.calculateActiveTime = calculateActiveTime; - testing.calculateScaledActiveTime = calculateScaledActiveTime; - testing.calculateIterationTime = calculateIterationTime; - testing.calculateCurrentIteration = calculateCurrentIteration; - testing.calculateTransformedTime = calculateTransformedTime; } })(webAnimationsShared, webAnimationsTesting); diff --git a/src/transform-handler.js b/src/transform-handler.js index c4482961..c6b4d934 100644 --- a/src/transform-handler.js +++ b/src/transform-handler.js @@ -256,6 +256,19 @@ scope.addPropertiesHandler(parseTransform, mergeTransforms, ['transform']); + scope.transformToSvgMatrix = function(string) { + // matrix( ) + var mat = scope.transformListToMatrix(parseTransform(string)); + return 'matrix(' + + numberToLongString(mat[0]) + ' ' + // + numberToLongString(mat[1]) + ' ' + // + numberToLongString(mat[4]) + ' ' + // + numberToLongString(mat[5]) + ' ' + // + numberToLongString(mat[12]) + ' ' + // + numberToLongString(mat[13]) + // + ')'; + }; + if (WEB_ANIMATIONS_TESTING) testing.parseTransform = parseTransform; diff --git a/src/web-animations-bonus-cancel-events.js b/src/web-animations-bonus-cancel-events.js new file mode 100644 index 00000000..3905496f --- /dev/null +++ b/src/web-animations-bonus-cancel-events.js @@ -0,0 +1,83 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + + if (document.createElement('div').animate([]).oncancel !== undefined) { + return; + } + + if (WEB_ANIMATIONS_TESTING) { + var now = function() { return webAnimations1.timeline.currentTime; }; + } else if (window.performance && performance.now) { + var now = function() { return performance.now(); }; + } else { + var now = function() { return Date.now(); }; + } + + var AnimationCancelEvent = function(target, currentTime, timelineTime) { + this.target = target; + this.currentTime = currentTime; + this.timelineTime = timelineTime; + + this.type = 'cancel'; + this.bubbles = false; + this.cancelable = false; + this.currentTarget = target; + this.defaultPrevented = false; + this.eventPhase = Event.AT_TARGET; + this.timeStamp = Date.now(); + }; + + var originalElementAnimate = window.Element.prototype.animate; + window.Element.prototype.animate = function(effectInput, options) { + var animation = originalElementAnimate.call(this, effectInput, options); + + animation._cancelHandlers = []; + animation.oncancel = null; + + var originalCancel = animation.cancel; + animation.cancel = function() { + originalCancel.call(this); + var event = new AnimationCancelEvent(this, null, now()); + var handlers = this._cancelHandlers.concat(this.oncancel ? [this.oncancel] : []); + setTimeout(function() { + handlers.forEach(function(handler) { + handler.call(event.target, event); + }); + }, 0); + }; + + var originalAddEventListener = animation.addEventListener; + animation.addEventListener = function(type, handler) { + if (typeof handler == 'function' && type == 'cancel') + this._cancelHandlers.push(handler); + else + originalAddEventListener.call(this, type, handler); + }; + + var originalRemoveEventListener = animation.removeEventListener; + animation.removeEventListener = function(type, handler) { + if (type == 'cancel') { + var index = this._cancelHandlers.indexOf(handler); + if (index >= 0) + this._cancelHandlers.splice(index, 1); + } else { + originalRemoveEventListener.call(this, type, handler); + } + }; + + return animation; + }; +})(); diff --git a/src/web-animations-bonus-object-form-keyframes.js b/src/web-animations-bonus-object-form-keyframes.js new file mode 100644 index 00000000..c1b6ecdc --- /dev/null +++ b/src/web-animations-bonus-object-form-keyframes.js @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared) { + // If the polyfill is being loaded in a context where Element.animate is + // supported but object-form syntax is not, then creating an animation + // using the new syntax will either have no effect or will throw an exception. + // In either case, we want to proceed to load this part of the polyfill. + // + // The test animation uses an opacity other than the one the element already + // has, and doesn't need to change during the animation for the test to work. + // After the test, the element's opacity will be left how we found it: + // - If the animation is not created, the test will leave the element's + // opacity untouched at originalOpacity. + // - If the animation is created, it will be cancelled, and leave the + // element's opacity at originalOpacity. + // - If the animation is somehow created and runs without being cancelled, + // when it finishes after 1ms, it will cease to have any effect (because + // fill is not specified), and opacity will again be left at originalOpacity. + var element = document.documentElement; + var animation = null; + var animated = false; + try { + var originalOpacity = getComputedStyle(element).getPropertyValue('opacity'); + var testOpacity = originalOpacity == '0' ? '1' : '0'; + animation = element.animate({'opacity': [testOpacity, testOpacity]}, + {duration: 1}); + animation.currentTime = 0; + animated = getComputedStyle(element).getPropertyValue('opacity') == testOpacity; + } catch (error) { + } finally { + if (animation) + animation.cancel(); + } + if (animated) { + return; + } + + var originalElementAnimate = window.Element.prototype.animate; + window.Element.prototype.animate = function(effectInput, options) { + if (window.Symbol && Symbol.iterator && Array.prototype.from && effectInput[Symbol.iterator]) { + // Handle custom iterables in most browsers by converting to an array + effectInput = Array.from(effectInput); + } + + if (!Array.isArray(effectInput) && effectInput !== null) { + effectInput = shared.convertToArrayForm(effectInput); + } + + return originalElementAnimate.call(this, effectInput, options); + }; +})(webAnimationsShared); diff --git a/src/web-animations-next-animation.js b/src/web-animations-next-animation.js index 33fd3ffb..698532cd 100644 --- a/src/web-animations-next-animation.js +++ b/src/web-animations-next-animation.js @@ -13,26 +13,76 @@ // limitations under the License. (function(shared, scope, testing) { - scope.Animation = function(effect) { + scope.animationsWithPromises = []; + + scope.Animation = function(effect, timeline) { + this.id = ''; + if (effect && effect._id) { + this.id = effect._id; + } this.effect = effect; if (effect) { - // FIXME: detach existing animation. - effect.animation = this; + effect._animation = this; } + if (!timeline) { + throw new Error('Animation with null timeline is not supported'); + } + this._timeline = timeline; + this._sequenceNumber = shared.sequenceNumber++; + this._holdTime = 0; + this._paused = false; this._isGroup = false; this._animation = null; this._childAnimations = []; this._callback = null; + this._oldPlayState = 'idle'; this._rebuildUnderlyingAnimation(); // Animations are constructed in the idle state. this._animation.cancel(); + this._updatePromises(); }; - // TODO: add an effect getter/setter scope.Animation.prototype = { + _updatePromises: function() { + var oldPlayState = this._oldPlayState; + var newPlayState = this.playState; + if (this._readyPromise && newPlayState !== oldPlayState) { + if (newPlayState == 'idle') { + this._rejectReadyPromise(); + this._readyPromise = undefined; + } else if (oldPlayState == 'pending') { + this._resolveReadyPromise(); + } else if (newPlayState == 'pending') { + this._readyPromise = undefined; + } + } + if (this._finishedPromise && newPlayState !== oldPlayState) { + if (newPlayState == 'idle') { + this._rejectFinishedPromise(); + this._finishedPromise = undefined; + } else if (newPlayState == 'finished') { + this._resolveFinishedPromise(); + } else if (oldPlayState == 'finished') { + this._finishedPromise = undefined; + } + } + this._oldPlayState = this.playState; + return (this._readyPromise || this._finishedPromise); + }, _rebuildUnderlyingAnimation: function() { - if (this._animation) { + this._updatePromises(); + var oldPlaybackRate; + var oldPaused; + var oldStartTime; + var oldCurrentTime; + var hadUnderlying = this._animation ? true : false; + if (hadUnderlying) { + oldPlaybackRate = this.playbackRate; + oldPaused = this._paused; + oldStartTime = this.startTime; + oldCurrentTime = this.currentTime; this._animation.cancel(); + this._animation._wrapper = null; this._animation = null; } @@ -44,8 +94,25 @@ this._animation = scope.newUnderlyingAnimationForGroup(this.effect); scope.bindAnimationForGroup(this); } - - // FIXME: move existing currentTime/startTime/playState to new animation + if (this.effect && this.effect._onsample) { + scope.bindAnimationForCustomEffect(this); + } + if (hadUnderlying) { + if (oldPlaybackRate != 1) { + this.playbackRate = oldPlaybackRate; + } + if (oldStartTime !== null) { + this.startTime = oldStartTime; + } else if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } else if (this._holdTime !== null) { + this.currentTime = this._holdTime; + } + if (oldPaused) { + this.pause(); + } + } + this._updatePromises(); }, _updateChildren: function() { if (!this.effect || this.playState == 'idle') @@ -62,21 +129,22 @@ if (!this.effect || !this._isGroup) return; for (var i = 0; i < this.effect.children.length; i++) { - this.effect.children[i].animation = animation; + this.effect.children[i]._animation = animation; this._childAnimations[i]._setExternalAnimation(animation); } }, - _constructChildren: function() { + _constructChildAnimations: function() { if (!this.effect || !this._isGroup) return; var offset = this.effect._timing.delay; + this._removeChildAnimations(); this.effect.children.forEach(function(child) { - var childAnimation = window.document.timeline.play(child); + var childAnimation = scope.timeline._play(child); this._childAnimations.push(childAnimation); childAnimation.playbackRate = this.playbackRate; - if (this.paused) + if (this._paused) childAnimation.pause(); - child.animation = this.effect.animation; + child._animation = this.effect._animation; this._arrangeChildren(childAnimation, offset); @@ -87,77 +155,139 @@ _arrangeChildren: function(childAnimation, offset) { if (this.startTime === null) { childAnimation.currentTime = this.currentTime - offset / this.playbackRate; - childAnimation._startTime = null; } else if (childAnimation.startTime !== this.startTime + offset / this.playbackRate) { childAnimation.startTime = this.startTime + offset / this.playbackRate; } }, - get paused() { - return this._animation.paused; + get timeline() { + return this._timeline; }, get playState() { - return this._animation.playState; + return this._animation ? this._animation.playState : 'idle'; + }, + get finished() { + if (!window.Promise) { + console.warn('Animation Promises require JavaScript Promise constructor'); + return null; + } + if (!this._finishedPromise) { + if (scope.animationsWithPromises.indexOf(this) == -1) { + scope.animationsWithPromises.push(this); + } + this._finishedPromise = new Promise( + function(resolve, reject) { + this._resolveFinishedPromise = function() { + resolve(this); + }; + this._rejectFinishedPromise = function() { + reject({type: DOMException.ABORT_ERR, name: 'AbortError'}); + }; + }.bind(this)); + if (this.playState == 'finished') { + this._resolveFinishedPromise(); + } + } + return this._finishedPromise; + }, + get ready() { + if (!window.Promise) { + console.warn('Animation Promises require JavaScript Promise constructor'); + return null; + } + if (!this._readyPromise) { + if (scope.animationsWithPromises.indexOf(this) == -1) { + scope.animationsWithPromises.push(this); + } + this._readyPromise = new Promise( + function(resolve, reject) { + this._resolveReadyPromise = function() { + resolve(this); + }; + this._rejectReadyPromise = function() { + reject({type: DOMException.ABORT_ERR, name: 'AbortError'}); + }; + }.bind(this)); + if (this.playState !== 'pending') { + this._resolveReadyPromise(); + } + } + return this._readyPromise; }, get onfinish() { - return this._onfinish; + return this._animation.onfinish; }, set onfinish(v) { if (typeof v == 'function') { - this._onfinish = v; this._animation.onfinish = (function(e) { e.target = this; v.call(this, e); }).bind(this); } else { this._animation.onfinish = v; - this.onfinish = this._animation.onfinish; + } + }, + get oncancel() { + return this._animation.oncancel; + }, + set oncancel(v) { + if (typeof v == 'function') { + this._animation.oncancel = (function(e) { + e.target = this; + v.call(this, e); + }).bind(this); + } else { + this._animation.oncancel = v; } }, get currentTime() { - return this._animation.currentTime; + this._updatePromises(); + var currentTime = this._animation.currentTime; + this._updatePromises(); + return currentTime; }, set currentTime(v) { - this._animation.currentTime = v; + this._updatePromises(); + this._animation.currentTime = isFinite(v) ? v : Math.sign(v) * Number.MAX_VALUE; this._register(); this._forEachChild(function(child, offset) { child.currentTime = v - offset; }); + this._updatePromises(); }, get startTime() { return this._animation.startTime; }, set startTime(v) { - this._animation.startTime = v; + this._updatePromises(); + this._animation.startTime = isFinite(v) ? v : Math.sign(v) * Number.MAX_VALUE; this._register(); this._forEachChild(function(child, offset) { child.startTime = v + offset; }); + this._updatePromises(); }, get playbackRate() { return this._animation.playbackRate; }, set playbackRate(value) { + this._updatePromises(); var oldCurrentTime = this.currentTime; this._animation.playbackRate = value; this._forEachChild(function(childAnimation) { childAnimation.playbackRate = value; }); - if (this.playState != 'paused' && this.playState != 'idle') { - this.play(); - } if (oldCurrentTime !== null) { this.currentTime = oldCurrentTime; } - }, - get finished() { - return this._animation.finished; - }, - get source() { - shared.deprecated('Animation.source', '2015-03-23', 'Use Animation.effect instead.'); - return this.effect; + this._updatePromises(); }, play: function() { + this._updatePromises(); + this._paused = false; this._animation.play(); + if (this._timeline._animations.indexOf(this) == -1) { + this._timeline._animations.push(this); + } this._register(); scope.awaitStartTime(this); this._forEachChild(function(child) { @@ -165,25 +295,36 @@ child.play(); child.currentTime = time; }); + this._updatePromises(); }, pause: function() { + this._updatePromises(); + if (this.currentTime) { + this._holdTime = this.currentTime; + } this._animation.pause(); this._register(); this._forEachChild(function(child) { child.pause(); }); + this._paused = true; + this._updatePromises(); }, finish: function() { + this._updatePromises(); this._animation.finish(); this._register(); - // TODO: child animations?? + this._updatePromises(); }, cancel: function() { + this._updatePromises(); this._animation.cancel(); this._register(); - this._removeChildren(); + this._removeChildAnimations(); + this._updatePromises(); }, reverse: function() { + this._updatePromises(); var oldCurrentTime = this.currentTime; this._animation.reverse(); this._forEachChild(function(childAnimation) { @@ -192,6 +333,7 @@ if (oldCurrentTime !== null) { this.currentTime = oldCurrentTime; } + this._updatePromises(); }, addEventListener: function(type, handler) { var wrapped = handler; @@ -207,29 +349,35 @@ removeEventListener: function(type, handler) { this._animation.removeEventListener(type, (handler && handler._wrapper) || handler); }, - _removeChildren: function() { + _removeChildAnimations: function() { while (this._childAnimations.length) this._childAnimations.pop().cancel(); }, _forEachChild: function(f) { var offset = 0; if (this.effect.children && this._childAnimations.length < this.effect.children.length) - this._constructChildren(); + this._constructChildAnimations(); this._childAnimations.forEach(function(child) { f.call(this, child, offset); if (this.effect instanceof window.SequenceEffect) offset += child.effect.activeDuration; }.bind(this)); - if (this._animation.playState == 'pending') + if (this.playState == 'pending') return; var timing = this.effect._timing; - var t = this._animation.currentTime; + var t = this.currentTime; if (t !== null) - t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + t = shared.calculateIterationProgress(shared.calculateActiveDuration(timing), t, timing); if (t == null || isNaN(t)) - this._removeChildren(); + this._removeChildAnimations(); }, }; + window.Animation = scope.Animation; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimationsNextAnimation = scope.Animation; + } + })(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/target-config.js b/target-config.js index 47e3c230..49d2b94d 100644 --- a/target-config.js +++ b/target-config.js @@ -42,6 +42,11 @@ 'src/property-names.js', ]; + var webAnimations1BonusSrc = [ + 'src/web-animations-bonus-cancel-events.js', + 'src/web-animations-bonus-object-form-keyframes.js', + ]; + var liteWebAnimations1Src = [ 'src/keyframe-interpolations.js', 'src/property-interpolation.js', @@ -76,7 +81,8 @@ 'src/effect-callback.js', 'src/group-constructors.js']; - var webAnimations1Test = [ + var webAnimations1PolyfillTests = [ + 'test/js/animation-cancel-event.js', 'test/js/animation-finish-event.js', 'test/js/animation.js', 'test/js/apply-preserving-inline-style.js', @@ -91,15 +97,40 @@ 'test/js/tick.js', 'test/js/timing-utilities.js', 'test/js/timing.js', - 'test/js/transform-handler.js']; + 'test/js/transform-handler.js', + 'test/js/visibility-handler.js']; - var webAnimationsNextTest = webAnimations1Test.concat( + var webAnimationsNextPolyfillTests = webAnimations1PolyfillTests.concat( 'test/js/effect-callback.js', + 'test/js/group-animation-cancel-event.js', 'test/js/group-animation-finish-event.js', 'test/js/group-animation.js', 'test/js/group-constructors.js', 'test/js/keyframe-effect-constructor.js', - 'test/js/timeline.js'); + 'test/js/timeline.js', + 'test/js/web-animations-next-animation.js'); + + var webAnimations1WebPlatformTests = [ + 'test/web-platform-tests/web-animations/animation-model/animation-types/discrete-animation.html', + 'test/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html', + 'test/web-platform-tests/web-animations/animation-model/keyframe-effects/the-effect-value-of-a-keyframe-effect.html', + 'test/web-platform-tests/web-animations/interfaces/Animatable/animate-basic.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/cancel.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/id.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/pause.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/play.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/playState.html', + 'test/web-platform-tests/web-animations/interfaces/Animation/startTime.html', + 'test/web-platform-tests/web-animations/interfaces/KeyframeEffect/effect-easing.html', + 'test/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html', + 'test/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html', + ]; + + var webAnimationsNextWebPlatformTests = [ + // TODO: Bring web-animations-next back up to speed with the spec to reenable testing everything. + // 'test/web-platform-tests/web-animations/**/*.html', + ...webAnimations1WebPlatformTests, + ]; // This object specifies the source and test files for different Web Animation build targets. var targetConfig = { @@ -107,25 +138,31 @@ scopeSrc: scopeSrc, sharedSrc: sharedSrc, webAnimations1Src: webAnimations1Src, + webAnimations1BonusSrc: webAnimations1BonusSrc, webAnimationsNextSrc: [], - src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src), - test: webAnimations1Test, + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src).concat(webAnimations1BonusSrc), + polyfillTests: webAnimations1PolyfillTests, + webPlatformTests: webAnimations1WebPlatformTests, }, 'web-animations-next': { scopeSrc: scopeSrc, sharedSrc: sharedSrc, webAnimations1Src: webAnimations1Src, + webAnimations1BonusSrc: webAnimations1BonusSrc, webAnimationsNextSrc: webAnimationsNextSrc, - src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src).concat(webAnimationsNextSrc), - test: webAnimationsNextTest, + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src).concat(webAnimations1BonusSrc).concat(webAnimationsNextSrc), + polyfillTests: webAnimationsNextPolyfillTests, + webPlatformTests: webAnimationsNextWebPlatformTests, }, 'web-animations-next-lite': { scopeSrc: scopeSrc, sharedSrc: sharedSrc, webAnimations1Src: liteWebAnimations1Src, + webAnimations1BonusSrc: webAnimations1BonusSrc, webAnimationsNextSrc: webAnimationsNextSrc, - src: scopeSrc.concat(sharedSrc).concat(liteWebAnimations1Src).concat(webAnimationsNextSrc), - test: [], + src: scopeSrc.concat(sharedSrc).concat(liteWebAnimations1Src).concat(webAnimations1BonusSrc).concat(webAnimationsNextSrc), + polyfillTests: [], + webPlatformTests: [], }, }; diff --git a/test/blink/2-keyframes-with-offsets.html b/test/blink/2-keyframes-with-offsets.html index 248d1312..bf31189d 100644 --- a/test/blink/2-keyframes-with-offsets.html +++ b/test/blink/2-keyframes-with-offsets.html @@ -1,6 +1,6 @@ - - + + - + + - + +
- + + - + +
diff --git a/test/blink/get-css-animations.html b/test/blink/get-css-animations.html index 429a3370..40033336 100644 --- a/test/blink/get-css-animations.html +++ b/test/blink/get-css-animations.html @@ -1,6 +1,6 @@ - - + + - - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + +
- + + - + +
- + + - + + \n'; + '*/<\/script>\n'; return source; }, @@ -373,23 +377,46 @@ var metadata_generator = { add_completion_callback( function (tests, harness_status) { metadata_generator.process(tests, harness_status); + dump_test_results(tests, harness_status); }); } }; -var url = document.URL; -var path = url.slice(0, url.lastIndexOf('/')); -if (path.slice(-13).indexOf('interpolation') != -1) { - document.write(''); -} else { - document.write(''); +function dump_test_results(tests, status) { + var results_element = document.createElement("script"); + results_element.type = "text/json"; + results_element.id = "__testharness__results__"; + var test_results = tests.map(function(x) { + return {name:x.name, status:x.status, message:x.message, stack:x.stack} + }); + var data = {test:window.location.href, + tests:test_results, + status: status.status, + message: status.message, + stack: status.stack}; + results_element.textContent = JSON.stringify(data); + + // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' + // is inserted at a location that results in a valid document. + var parent = document.body + ? document.body // is required in XHTML documents + : document.documentElement; // fallback for optional in HTML5, SVG, etc. + + parent.appendChild(results_element); } -if (window.parent && parent.window.initTestHarness) { - parent.window.initTestHarness(window); -} else { - metadata_generator.setup(); +/* BEGIN WEB ANIMATIONS POLYFILL EXTRAS */ + +// This must be run under a Karma server via "grunt test". +var config = window.parent.__karma__.config.testharnessTests; +if (!config.withNativeFallback) { + // Disable native Web Animations fallback. + Element.prototype.animate = null; } +document.write(''); +parent.window.onTestharnessLoaded(window); + +/* END WEB ANIMATIONS POLYFILL EXTRAS */ /* If the parent window has a testharness_properties object, * we use this to provide the test settings. This is used by the diff --git a/test/web-platform-tests b/test/web-platform-tests new file mode 160000 index 00000000..f9f56630 --- /dev/null +++ b/test/web-platform-tests @@ -0,0 +1 @@ +Subproject commit f9f566304cb595c12c82cbe7a7cbba72e83bb28f diff --git a/test/web-platform-tests-expectations.js b/test/web-platform-tests-expectations.js new file mode 100644 index 00000000..a5764b15 --- /dev/null +++ b/test/web-platform-tests-expectations.js @@ -0,0 +1,703 @@ +// Expectations to be used by karma-testharness-adapter.js. +module.exports = { + skip: { + 'test/web-platform-tests/web-animations/interfaces/Animation/constructor.html': + 'KeyframeEffectReadOnly is not defined causing the test to timeout.', + }, + + flakyTestIndicator: 'FLAKY_TEST_RESULT', + + // Schema for failureConfigurations: + // failureConfigurations := [ ] + // failureConfiguration := { configuration: ?, failures: } + // configuration := { target: ?, withNativeFallback: ? } + // failures := { : { : } } + failureConfigurations: [ + { + configuration: { + target: 'web-animations', + withNativeFallback: true, + }, + failures: { + }, + }, + { + configuration: { + target: 'web-animations', + withNativeFallback: false, + }, + failures: { + 'test/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html': { + 'Effect values reflect changes to font-size from reparenting': + 'animation.ready is undefined', + + 'Effect values reflect changes to font-size when computed style is not immediately flushed': + 'animation.ready is undefined', + + 'Effect values reflect changes to target element': + 'animation.effect is undefined', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/cancel.html': { + 'After cancelling an animation, it can still be re-used': + 'animation.ready is undefined', + + 'After cancelling an animation, it can still be seeked': + 'animation.effect is undefined', + + 'Animated style is cleared after calling Animation.cancel()': + 'animation.ready is undefined', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/pause.html': { + 'pause() a running animation': + 'animation.ready is undefined', + + 'pause() from idle': + 'assert_true: initially pause-pending expected true got undefined', + + 'pause() from idle with a negative playbackRate': + 'animation.ready is undefined', + + 'pause() on a finished animation': + 'animation.ready is undefined', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/play.html': { + 'play() throws when seeking an infinite-duration animation played in reverse': + 'animation.ready is undefined', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/startTime.html': { + 'startTime is resolved when running': + 'animation.ready is undefined', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html': { + 'Active time in active phase and negative start delay is the local time minus the start delay': + 'anim.effect is undefined', + + 'Active time in active phase and no start delay is the local time': + 'anim.effect is undefined', + + 'Active time in active phase and positive start delay is the local time minus the start delay': + 'anim.effect is undefined', + + 'Active time in after phase with \'both\' fill is the active duration': + 'anim.effect is undefined', + + 'Active time in after phase with backwards-only fill is unresolved': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the active duration is zero': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the sum of the active duration and start delay is zero': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill and negative end delay is the active duration + end delay': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill and positive end delay is the active duration': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill is the active duration': + 'anim.effect is undefined', + + 'Active time in after phase with forwards fill, zero-duration, and infinite iteration count is the active duration': + 'anim.effect is undefined', + + 'Active time in after phase with no fill is unresolved': + 'anim.effect is undefined', + + 'Active time in before phase': + 'anim.effect is undefined', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html': { + 'Test end delay: duration:100 delay:1 fill:both endDelay:-100': + 'effect is undefined', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-200': + 'effect is undefined', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-50': + 'effect is undefined', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:50': + 'effect is undefined', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-100': + 'effect is undefined', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-50': + 'effect is undefined', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:50': + 'effect is undefined', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect is undefined', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-50': + 'effect is undefined', + + 'Test end delay: iterations:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test negative playback rate: duration:0 delay:1 fill:both playbackRate:-1': + 'effect is undefined', + + 'Test negative playback rate: duration:0 iterations:0 delay:1 fill:both playbackRate:-1': + 'effect is undefined', + + 'Test negative playback rate: duration:1 delay:1 fill:both playbackRate:-1': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:0 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:100 delay:1 fill:both': + 'effect is undefined', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect is undefined', + }, + }, + }, + { + configuration: { + target: 'web-animations-next', + withNativeFallback: true, + }, + failures: { + 'test/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html': { + 'Effect values reflect changes to target element': + 'assert_equals: Effect value after updating target element expected "300px" but got "0px"', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/cancel.html': { + 'After cancelling an animation, it can still be seeked': + 'animation.effect.updateTiming is not a function', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/pause.html': { + 'pause() from idle': + 'assert_true: initially pause-pending expected true got undefined', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/startTime.html': { + 'startTime is resolved when running': + 'assert_greater_than: startTime when running expected a number but got a "object"', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html': { + 'Active time in active phase and negative start delay is the local time minus the start delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in active phase and no start delay is the local time': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in active phase and positive start delay is the local time minus the start delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with \'both\' fill is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with backwards-only fill is unresolved': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the active duration is zero': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the sum of the active duration and start delay is zero': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay is the active duration + end delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and positive end delay is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill, zero-duration, and infinite iteration count is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with no fill is unresolved': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in before phase': + 'anim.effect.getComputedTiming is not a function', + + 'Active time when the local time is unresolved, is unresolved': + 'effect.getComputedTiming is not a function', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html': { + 'Test end delay: duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-200': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:0 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:0 iterations:0 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:1 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + }, + }, + }, + { + configuration: { + target: 'web-animations-next', + withNativeFallback: false, + }, + failures: { + 'test/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html': { + 'Effect values reflect changes to target element': + 'assert_equals: Effect value after updating target element expected "300px" but got "0px"', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/cancel.html': { + 'After cancelling an animation, it can still be seeked': + 'animation.effect.updateTiming is not a function', + }, + + 'test/web-platform-tests/web-animations/interfaces/Animation/pause.html': { + 'pause() from idle': + 'assert_true: initially pause-pending expected true got undefined', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html': { + 'Active time in active phase and negative start delay is the local time minus the start delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in active phase and no start delay is the local time': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in active phase and positive start delay is the local time minus the start delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with \'both\' fill is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with backwards-only fill is unresolved': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the active duration is zero': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay greater in magnitude than the sum of the active duration and start delay is zero': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and negative end delay is the active duration + end delay': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill and positive end delay is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with forwards fill, zero-duration, and infinite iteration count is the active duration': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in after phase with no fill is unresolved': + 'anim.effect.getComputedTiming is not a function', + + 'Active time in before phase': + 'anim.effect.getComputedTiming is not a function', + + 'Active time when the local time is unresolved, is unresolved': + 'effect.getComputedTiming is not a function', + }, + + 'test/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html': { + 'Test end delay: duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-200': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: duration:100 delay:1 fill:both endDelay:50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-50': + 'effect.getComputedTiming is not a function', + + 'Test end delay: iterations:2 duration:100 delay:1 fill:both endDelay:-100': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test fractional iterations: iterations:3.5 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test infinity iterations: iterations:Infinity iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test integer iterations: iterations:3 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:0 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:0 iterations:0 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test negative playback rate: duration:1 delay:1 fill:both playbackRate:-1': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:0 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:2.5 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:0 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:100 delay:1 fill:both': + 'effect.getComputedTiming is not a function', + + 'Test zero iterations: iterations:0 iterationStart:3 duration:Infinity delay:1 fill:both': + 'effect.getComputedTiming is not a function', + }, + }, + }, + ], +}; diff --git a/web-animations-next-lite.dev.html b/web-animations-next-lite.dev.html index f367348c..bdcf3e0d 100644 --- a/web-animations-next-lite.dev.html +++ b/web-animations-next-lite.dev.html @@ -35,6 +35,8 @@ + + diff --git a/web-animations-next-lite.min.html b/web-animations-next-lite.min.html new file mode 100644 index 00000000..3580355a --- /dev/null +++ b/web-animations-next-lite.min.html @@ -0,0 +1 @@ + diff --git a/web-animations-next.dev.html b/web-animations-next.dev.html index af2a29b0..b03f08cf 100644 --- a/web-animations-next.dev.html +++ b/web-animations-next.dev.html @@ -40,6 +40,8 @@ + + diff --git a/web-animations-next.min.html b/web-animations-next.min.html new file mode 100644 index 00000000..536e092d --- /dev/null +++ b/web-animations-next.min.html @@ -0,0 +1 @@ + diff --git a/web-animations.dev.html b/web-animations.dev.html index b4eb5b90..5583c9c4 100644 --- a/web-animations.dev.html +++ b/web-animations.dev.html @@ -40,4 +40,6 @@ + + diff --git a/web-animations.min.html b/web-animations.min.html new file mode 100644 index 00000000..b36940d3 --- /dev/null +++ b/web-animations.min.html @@ -0,0 +1 @@ +