diff options
author | Ulrich-Matthias Schäfer <ulima.ums@googlemail.com> | 2018-10-18 11:29:49 +0200 |
---|---|---|
committer | Ulrich-Matthias Schäfer <ulima.ums@googlemail.com> | 2018-10-18 11:29:49 +0200 |
commit | fb34ed0894b0e4fc4c2a8488ad7375f357e02989 (patch) | |
tree | 129e790ba81a1a1cf9c0d6dbaae556a9ea6a3653 | |
parent | 6175adf23ddd6587954b20dc2700458d27ccaf69 (diff) | |
parent | 8ca3341952c2979520b349ce754bc98d8bb5f1d3 (diff) | |
download | svg.js-fb34ed0894b0e4fc4c2a8488ad7375f357e02989.tar.gz svg.js-fb34ed0894b0e4fc4c2a8488ad7375f357e02989.zip |
Merge branch '776-new-fx' into 3.0.0
80 files changed, 16449 insertions, 10598 deletions
diff --git a/.config/karma.conf.js b/.config/karma.conf.js index 42ceb39..9ea2a89 100644 --- a/.config/karma.conf.js +++ b/.config/karma.conf.js @@ -16,6 +16,7 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ '.config/pretest.js', + 'spec/lib/RAFPlugin.js', { pattern: 'spec/fixtures/fixture.css', included: false, @@ -34,7 +35,7 @@ module.exports = function(config) { 'dist/svg.js', 'spec/spec/**/*.js' ], - + proxies: { '/fixtures/': '/base/spec/fixtures/' }, diff --git a/CHANGELOG.md b/CHANGELOG.md index ecdc100..f99f749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http: - added `isRoot()` on `SVG.Doc` (#809) - added `random` option and `randomize()` method to `SVG.Color` -> __TODO!__ - added `precision()` method to round numeric element attributes -> __TODO!__ +- added a linter during the npm build process +- added `npm build:dev` to let you develop without getting too annoyed ### Removed - removed `SVG.Array.split()` function @@ -31,6 +33,7 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http: - removed `SVG.Nested` (#809) - removed `show()` from `SVG.A` to avoid name clash (#802) - removed `size()` from `SVG.Text` to avoid name clash (#799) +- removed `move(), dmove()` etc for groups to avoid inconsistencies, we will expect users to use transforms to move around groups as they should (especially since they are much simpler now). ### Changed - gradients now have there corresponding node as type and not only radial/linear @@ -63,8 +66,11 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http: - default constructor now has an optional `node` argument which is used to consruct the object e.g. `new SVG.Rect(rectNode)` - SVG.Elements constructor now tries to import svgjs:data from the node - `SVG.on()` calls the listener in the context of the passed object. el.on always uses the svg.js object as context -- `SVG.on()/off()` and `el.on()/off()` now accepts multiple comma or space seperated events e.g. "mousedown, foo bar" (#727) +- `SVG.on()/off()` and `el.on()/off()` now accepts multiple comma or space separated events e.g. "mousedown, foo bar" (#727) +- Matrices now apply transformations like `scale`, `translate`, etc... by left multiplying them to simplify transformations +- The way `transform()` works is now completely different. See the docs for more as soon as they are updated. - merged `SVG.Doc` and `SVG.Nested`, added `isRoot()` on `SVG.Doc()` (#809) +- The fx module was completely reworked to be faster and less error prone. For more information on how to use it refer to the docs ### Fixed - fixed a bug in clipping and masking where empty nodes persists after removal -> __TODO!__ @@ -27,3 +27,49 @@ SVG.js is licensed under the terms of the MIT License. Check [https://svgdotjs.github.io](https://svgdotjs.github.io/) to learn more. [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=pay%40woutfierens.com&lc=US&item_name=SVG.JS¤cy_code=EUR&bn=PP-DonationsBF%3Abtn_donate_74x21.png%3ANonHostedGuest) + +## Development + +To develop svg.js, you have a few commands available to you. Firstly, you should clone this repo, then cd into the folder with this README and run: + + npm install + +You'll now have all the dev dependencies installed, and you'll be ready to build the bundle. Once you've made your changes just run: + + npm run build + +This will build svg.js and make a distribution in the `/dist` folder. While developing, this may not be so convenient as the build will fail if you have any linting errors, refer to the [standard coding styleguide](https://standardjs.com/) for style we use, linters are available for most popular text editors as well. + +However, because we were too nice to put you through the pain of always having to work with a linter, we added a gentle mode that you can use by running: + + npm run build:dev + +This will only warn you about linting errors and give you useful feedback about possible errors you may have in your code (but this is no substitute for tests). Please make sure that **before making any pull requests**, you pass all of our tests and can build with `npm run build` first. + +> ⚠️⚠️⚠️ WARNING ⚠️⚠️⚠️ +> This library still uses es5, so if you do anything like using `let`, it will +> probably break, and you probably won't be able to figure out why. This is +> only a temporary trouble 🙃 We will fix it as soon as we can! +> +> The linter is ready for es6, but the build process is not, so if you get an +> error and the linter says nothing; check for es6iness 😍 + +### Testing + +This will set up everything. While you are working, you should make sure your changes pass all of our tests, so just run: + + npm run test + +Or just launch the jasmine test runner from `/spec/SpecRunner.html`. Its good to try the spec runner on a few different browsers. + +### Performance + +You can run performance tests by making a new benchmarks, look in the `/bench` folder and just add a new js file with the test you want to make. We include a few examples in the repo to make it easy for you to make your own. + +### Playgrounds + +If you would like a simple sandbox that you can use + +## Pull Requests + +We welcome any pull requests and will try our hardest to review them as soon as possible. If you need any help or would like to chat, check out our [gitter group](https://gitter.im/svgdotjs/svg.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge), we are always happy to see new users! diff --git a/bench/runner.html b/bench/runner.html index 965a884..b39c1df 100644 --- a/bench/runner.html +++ b/bench/runner.html @@ -38,16 +38,25 @@ <div id="draw"></div> <svg id="native" width="100" height="100" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs"></svg> <script src="../dist/svg.js"></script> + <script type="text/javascript" src="../src/helpers.js"></script> + <script type="text/javascript" src="../src/transform.js"></script> + <script type="text/javascript" src="../src/matrix.js"></script> + <script type="text/javascript" src="../src/morph.js"></script> + <script type="text/javascript" src="../src/runner.js"></script> + <script type="text/javascript" src="../src/timeline.js"></script> + <script type="text/javascript" src="../src/controller.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script> <script src="svg.bench.js"></script> <!--<script src="tests/10000-each.js"></script> --> - <script src="tests/10000-rects.js"></script> + <!-- <script src="tests/10000-rects.js"></script> <script src="tests/10000-circles.js"></script> <script src="tests/10000-paths.js"></script> <script src="tests/10000-boxes.js"></script> <script src="tests/10000-pointArray-bbox.js"></script> + <script src="tests/10000-accesses.js"></script> --> + <script src="tests/10000-transform.js"></script> <script> SVG.bench.run() </script> </body> -</html>
\ No newline at end of file +</html> diff --git a/bench/svg.bench.js b/bench/svg.bench.js index 5b9541e..50ef547 100644 --- a/bench/svg.bench.js +++ b/bench/svg.bench.js @@ -1,56 +1,55 @@ -;( function() { +/* global Snap */ +;(function () { SVG.bench = { // Initalize test store - _chain: [] - , _before: function() {} - , _after: function() {} - , draw: SVG().addTo('#draw') - , snap: Snap(100, 100) - , raw: document.getElementById('native') + _chain: [], + _before: function () {}, + _after: function () {}, + draw: SVG().addTo('#draw'), + snap: Snap(100, 100), + raw: document.getElementById('native'), // Add descriptor - , describe: function(name, closure) { + describe: function (name, closure) { this._chain.push({ - name: name - , run: closure + name: name, + run: closure }) return this - } + }, // Add test - , test: function(name, run) { + test: function (name, run) { // run test - var start = ( new Date ).getTime() + var start = (new Date()).getTime() run() - this.write( name, ( new Date ).getTime() - start ) + this.write(name, (new Date()).getTime() - start) // clear everything this.clear() - } + }, // Skip test - , skip: function(name, run) { - this.write( name, false ) - } + skip: function (name, run) { + this.write(name, false) + }, // Run tests - , run: function() { + run: function () { this.pad() - + for (var h, i = 0, il = this._chain.length; i < il; i++) { - var h = document.createElement('h1') + h = document.createElement('h1') h.innerHTML = this._chain[i].name - this.pad().appendChild(h) - this._chain[i].run(this) } - } - + }, + // Write result - , write: function(name, ms) { + write: function (name, ms) { var test = document.createElement('div') if (typeof ms === 'number') { @@ -60,14 +59,14 @@ test.className = 'test skipped' test.innerHTML = name + ' (skipped)' } - + this.pad().appendChild(test) return this - } + }, // Reference writable element - , pad: function() { + pad: function () { var pad = document.getElementById('pad') if (!pad) { @@ -76,15 +75,15 @@ } return pad - } + }, // Clear canvasses - , clear: function() { - while(this.raw.hasChildNodes()) + clear: function () { + while (this.raw.hasChildNodes()) { this.raw.removeChild(this.raw.lastChild) + } this.draw.clear() this.snap.clear() } } - -})();
\ No newline at end of file +})() diff --git a/bench/tests/10000-accesses.js b/bench/tests/10000-accesses.js new file mode 100644 index 0000000..4c7dfea --- /dev/null +++ b/bench/tests/10000-accesses.js @@ -0,0 +1,35 @@ + +SVG.bench.describe('Access a dom attribues vs dom properties vs object properties', function(bench) { + bench.test('using an object', function() { + var sum = 0 + var obj = {x: "30"} + for (var i = 0; i < 1000000; i++) { + sum += obj.x * i + } + console.log(sum) + }) + + bench.test('figure out what the overhead is', function () { + var obj = bench.draw.rect(100, 100).move(0, 0) + }) + + bench.test('using dom attriutes', function () { + var sum = 0 + var obj = bench.draw.rect(100, 100).move(0, 0) + var node = obj.node + for (var i = 0; i < 1000000; i++) { + sum += node.getAttribute('x') * i + } + console.log(sum, node.getAttribute('x')) + }) + + bench.test('using dom properties', function () { + var sum = 0 + var obj = bench.draw.rect(100, 100).move(0, 0) + var node = obj.node + for (var i = 0; i < 1000000; i++) { + sum += node.x.baseVal * i + } + console.log(sum, node.x) + }) +}) diff --git a/bench/tests/10000-transform.js b/bench/tests/10000-transform.js new file mode 100644 index 0000000..0fcc162 --- /dev/null +++ b/bench/tests/10000-transform.js @@ -0,0 +1,32 @@ +SVG.bench.describe('Transform 1000000 rects', function(bench) { + let parameters = { + translate: [20, 30], + origin: [100, 100], + rotate: 25, + skew: [10, 30], + scale: 0.5 + } + + let matrixLike = {a:2, b:3, c:1, d:2, e:49, f:100} + let matrix = new SVG.Matrix(matrixLike) + + let worker = new SVG.Matrix() + bench.test('with parameters', function() { + for (var i = 0; i < 1000000; i++) + worker.transform(parameters) + }) + + worker = new SVG.Matrix() + bench.test('with matrix like', function() { + for (var i = 0; i < 1000000; i++) { + worker.transform(matrixLike) + } + }) + + worker = new SVG.Matrix() + bench.test('with SVG.Matrix', function() { + for (var i = 0; i < 1000000; i++) + worker.transform(matrix) + }) +}) + diff --git a/dirty.html b/dirty.html new file mode 100644 index 0000000..f3e739a --- /dev/null +++ b/dirty.html @@ -0,0 +1,405 @@ + +<!DOCTYPE html> +<html lang="en" dir="ltr"> +<head> + <meta charset="utf-8"> + <title></title> + <script type="text/javascript" src="dist/svg.js"></script> + <script type="text/javascript" src="src/helpers.js"></script> + <script type="text/javascript" src="src/transform.js"></script> + <script type="text/javascript" src="src/matrix.js"></script> + <script type="text/javascript" src="src/morph.js"></script> + <script type="text/javascript" src="src/runner.js"></script> + <script type="text/javascript" src="src/timeline.js"></script> + <script type="text/javascript" src="src/controller.js"></script> + + + + + + +</head> +<body style="background-color: #c7c7ff"> + +<div id="absolute"><label>Absolute: <input type="range" min="0" max="1" step="0.01"></slider></label><span></span></div> +<div id="position"><label>Position: <input type="range" min="0" max="5" step="0.01"></slider></label><span></span></div> + +<!-- Making the svg --> +<svg width=1000px height=1000px id="canvas" viewbox="-1000 -2000 5000 5000"> + <rect x=50 y=100 width=200 height=100 stroke=none stroke-width=2 /> +</svg> + +<!-- Modifying the svg --> +<script> + +let rect = SVG('rect').hide() +let {sin, PI: pi, round, sqrt} = Math + +function getColor(t) { + let a = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150) + let b = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200) + let c = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150) + let color = `rgb(${a}, ${b}, ${c})` + return color +} + +// var rect1 = SVG('<rect>').addTo('svg').size(50, 50).move(100, 100) +// var rect2 = SVG('<rect>').addTo('svg').size(50, 50).move(100, 200) +// +// var anim1 = new SVG.Runner(1000).element(rect1).loop(5, true, 1000).move(200, 100) +// var anim2 = new SVG.Runner(1000).element(rect2).loop(5, true, 1000).move(200, 200) +// +// SVG('#absolute').on('input slide', function (e) { +// var val = e.target.value +// document.querySelector('#absolute span').textContent = val +// anim1.absolute(val) +// }) +// +// SVG('#position').on('input slide', function (e) { +// var val = e.target.value +// document.querySelector('#position span').textContent = val +// anim2.position(val) +// }) + + +// rect.animate(4000) +// .during(t => rect.transform({scale: sqrt(1 + t), rotate: 720 * t})) +// .after(500, ()=> {rect.attr('stroke', 'white')}) +// .queue(() => rect.attr('fill', getColor(0))) +// .animate(1500, 500, true) +// .queue(()=> {}, t => rect.attr('fill', getColor(t))) +// .animate(1000, true) +// .move(200, 200) +// .size(300, 300) + +// SVG.Animator.timeout(()=> { rect.animate().pause() }, 1000 - 10) +// SVG.Animator.timeout(()=> { rect.animate().play() }, 2000 - 10) + + + +// SVG('rect') +// .clone().show() +// .animate() +// .move(300, 200) + +// +// for (let i = 0 ; i < 15; i++) { +// for (let j = 0 ; j < 10; j++) { +// +// // Make the rect +// let o = i + j +// let rect = SVG('rect').clone().show() +// .width(40).height(40) +// .x(50 * i).y(50 * j) +// .attr('fill', getColor(o * 0.1)) +// +// // Move the rect +// let {cx, cy} = rect.bbox() +// +// // Animate the rect +// rect.animate(3000, Math.random() * 2000) +// // .during(t => rect.transform({rotate: 700 * t, origin: [cx, cy]})) +// .transform({rotate: 720}, true) +// // .during(t => rect.attr('transform', `rotate(${700 * t})`)) +// .during(t => rect.attr('fill', getColor(o * 0.1 + t))) +// } +// } + +//SVG.defaults.timeline.ease = '-' +// +// var r = new SVG.Runner(1000) +// var t = new SVG.Timeline() +// r.schedule(t, 200) +// .animate(500).loop(5, true, 100) +// .animate(600, 200, 'absolute') +// .animate(600, 300) +// .animate(600, 300, 'now') +// .animate(1000, 0, 'absolute').loop(6, true) +// +// var canvas = SVG('svg') +// var schedule = t.schedule() +// +// schedule.forEach((s, i) => { +// var rect = canvas.rect(s.duration / 10, 25) +// .move(100 + s.start/10, 100 + i*30) +// .attr('fill', '#777') +// +// s.runner.element(rect) +// .attr('fill', getColor(i*0.1)) +// +// // if (i===0) +// // s.runner.during(console.log) +// }) +// +// var mover = canvas.line(100, 100, 100, 300).attr('stroke', 'black').clone() +// canvas.line(100, 300, 800, 300).attr('stroke', 'black') +// +// t.on('time', function (e) { +// mover.x(100 + e.detail/10) +// }) +// +// +// console.log(schedule) + +// var bla = SVG('<rect>').size(0, 0).move(200, 200).addTo('svg') +// bla.animate().size(220, 200).queue(null, console.log) + +// var randPoint = (x = 50, y = 50) => [ +// Math.random() * 100 - 50 + x, +// Math.random() * 100 - 50 + y +// ] +// +// var poly = SVG('<polygon>').plot([ +// randPoint(), +// randPoint(), +// randPoint(), +// randPoint(), +// randPoint() +// ]).attr({fill: 'none', stroke: 'black'}).addTo('svg') +// var polyAni = poly.animate(new SVG.Spring(3000, 0)) +// +// SVG.on(document, 'click', function (e) { +// polyAni.plot([ +// randPoint(e.pageX-50, e.pageY-50), +// randPoint(e.pageX+50, e.pageY-50), +// randPoint(e.pageX+50, e.pageY), +// randPoint(e.pageX+50, e.pageY+50), +// randPoint(e.pageX-50, e.pageY+50) +// ]) +// }) + +// var mover = SVG('<ellipse>').size(50, 50).center(100, 100).addTo('svg') +// var anim = mover.animate(new SVG.Spring(500, 10)) +// +// let date = +new Date +// SVG.on(document, 'mousemove', function (e) { +// // if (+new Date - date > 50) { +// // date = +new Date +// // } else { +// // return +// // } +// +// //var p = mover.point(e.pageX, e.pageY) +// var p = mover.doc().point(e.clientX, e.clientY) +// //var p = {x: e.pageX, y: e.pageY} +// //console.log(p) +// anim.transform({px: p.x - 100, py: p.y - 100}) +// //anim.center(p.x, p.y) +// }) +/* +let canvas = SVG('#canvas') + +let rectangle = canvas.rect(100, 200).move(100, 0) + +let bbox = rectangle.bbox() + +var timer = 0 +rectangle.timeline().source(() => { + timer += 2 + document.querySelector('#absolute span').textContent = timer + return timer +}) +rectangle.animate().transform({ + rotate: 90, + origin: [bbox.cx, bbox.cy] +})*/ + +// +let canvas = SVG('#canvas') + +// SVG('#absolute').on('input slide', function (e) { +// var val = e.target.value +// +// canvas.clear() + // canvas.ellipse(20, 20) + // let re = canvas.rect(300, 150).move(100, 150).attr('opacity', 0.5) + // re.clone() + // .transform({rotate: 45, skew: 30}, true) + // + // re.clone() + // .transform({ + // rotate: 45, skew: 30, /*translate: [150, 140], */ + // }, true) + // .transform({rotate: val, origin: 'bottom-right'}, true) + // + // re.clone() + // .transform({rotate: 45, skew: 30}, true) + // .transform({rotate: val, origin: 'bottom-right'}, true) + // .transform({skew}, true) +// let a = canvas.rect(200, 400).move(500, 400) +// .attr('opacity', 0.3) +// .addClass('pink') +// //.transform({ px: 100, py: 500, origin: 'top-left' }) +// +// +// var timer = 0 +// a.timeline().source(() => { +// timer += 1 +// document.querySelector('#absolute span').textContent = timer +// return timer +// }) +// +// let obj = { rotate: val * 180, origin: 'top-left' } +// let obj2 = { rotate: val * 280, origin: 'center' } +// +// a.clone() // startPosition +// a.clone().transform(obj, true).transform(obj2, true) // endPosition +// }) + + +// let a = canvas.rect(200, 400).move(500, 400) +// +// a.animate(1000, 500).move(100, 100).animate(1000, 500).move(500, 400) + +let gradient = canvas.gradient('radial', function(gradient) { + gradient.stop(0, '#f00') + gradient.stop(1, '#ff0') +}) + +let gradientEarth = canvas.gradient('linear', function(gradient) { + gradient.stop(0, '#00f') + gradient.stop(1, '#0f0') +}) + +let sun = canvas.circle(200).center(500, 300).attr({ fill: gradient }) + +let earth = canvas.circle(100).center(1000, 300).attr({fill: gradientEarth}) + +let moon = canvas.circle(50).center(1200, 300).attr({fill: '#ffa'}) + +earth.animate(10000).loop().ease('-') + .transform({rotate: 360, origin: [500, 300]}, true) + .transform({rotate: 720, origin: 'center'}, true) + +moon.animate(10000).loop().ease('-') + .transform({rotate: 360, origin: [500, 300]}, true) + .transform({rotate: 1080, origin: [1000, 300]}, true) +/** + * FUZZYS EXAMPLE + */ +// let a = canvas.rect(200, 400).move(500, 400) +// .attr('opacity', 0.3) +// .addClass('pink') +// .transform({ tx: 300, ty: 500, origin: 'top-left' }) +// +// let obj = { rotate: 100, origin: 'top-left'} +// let obj2 = { rotate: 280, origin: 'center' } +// let obj3 = { rotate: 1000, origin: 'center', translate: [300, 200]} +// +// +// var c = a.clone() +// +// c.animate(3000) +// .transform(obj) +// .transform(obj2, true) // animation +// +// a.clone().attr('fill', 'blue') +// .transform(obj) +// .transform(obj2, true) // endPosition + + +// SAIVANS EXAMPLE + + +// canvas.ellipse(20, 20).center(100, 100) +// let r = canvas.rect(200, 400).move(100, 100) +// .attr('opacity', 0.3) +// //.transform({ tx: 300, ty: 500, origin: 'top-left' }) +// +// // Normal usage +// let wait = 3000 +// let rAnim = r.clone().attr('fill', '#f00').animate(wait).attr('fill', '#0f0') +// let rDecl = r.clone().attr('fill', 'blue').animate(new SVG.Spring(wait, 15)) +// //let rDecl = r.clone().attr('fill', 'blue').animate(new SVG.PID(0.01, 0.001, 1, 10)) +// +// // var timer = 0 +// // rDecl.timeline().source(() => { +// // timer += 100 +// // return timer +// // }) +// +// let runTransformation = (transform) => { +// return () => { +// //transform = new SVG.Matrix(transform) +// let relative = true +// let affine = true +// r.transform(transform, relative) +// rAnim.animate(wait).transform(transform, relative, affine) +// rDecl.transform(transform, relative, affine) +// } +// } +// +// setTimeout(runTransformation({ +// origin: 'top-left', +// translate: [530, 250], +// rotate: 300, +// scale: 2, +// shear: 1, +// }), 0.1 * wait ) +// +// +// +// setTimeout(runTransformation({ +// origin: 'top-left', +// translate: [530, 250], +// rotate: 100, +// scale: 2, +// shear: 1, +// }), 0.4 * wait) +// +// setTimeout(runTransformation({ +// origin: 'top-left', +// translate: [530, 250], +// rotate: 100, +// scale: 2, +// shear: 1, +// }), 0.6 * wait) + + +// canvas.circle(50).center(100, 0).attr('fill', 'gray') +// +// setTimeout(runTransformation({ +// rotate: 360, +// origin: [100, 0] +// }), 0.1 * wait ) +// +// +// setTimeout(runTransformation({ +// rotate: 360, +// }), 0.4 * wait) + +// const getConsole = (time) => { +// return () => { +// console.group(time) +// console.log(0, rAnim.element()._transformationRunners[0] && rAnim.element()._transformationRunners[0].transforms.decompose().rotate) +// console.log(1, rAnim.element()._transformationRunners[1] && rAnim.element()._transformationRunners[1].transforms.decompose().rotate) +// console.log(2, rAnim.element()._transformationRunners[2] && rAnim.element()._transformationRunners[2].transforms.decompose().rotate) +// console.log(3, rAnim.element()._transformationRunners[3] && rAnim.element()._transformationRunners[3].transforms.decompose().rotate) +// console.log(4, rAnim.element()._transformationRunners[4] && rAnim.element()._transformationRunners[4].transforms.decompose().rotate) +// console.groupEnd(time) +// } +// } +// +// logCall = (time) => { +// setTimeout(getConsole(time), time) +// } +// +// logCall(0.2 * wait) +// logCall(0.3 * wait) +// logCall(0.4 * wait) +// logCall(0.5 * wait) +// logCall(0.6 * wait) +// logCall(0.7 * wait) +// logCall(0.8 * wait) +// logCall(0.9 * wait) +// logCall(1 * wait) +// logCall(1.1 * wait) +// logCall(1.2 * wait) +// logCall(1.3 * wait) +// logCall(1.4 * wait) +// logCall(1.5 * wait) + +</script> + +</body> +</html> diff --git a/dist/svg.js b/dist/svg.js index 01c2c45..0858996 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -6,7 +6,7 @@ * @copyright Wout Fierens <wout@mick-wout.com> * @license MIT * -* BUILT: Sat Mar 03 2018 11:57:42 GMT+0100 (Mitteleuropäische Zeit) +* BUILT: Thu Oct 18 2018 11:19:30 GMT+0200 (GMT+02:00) */; (function(root, factory) {
@@ -31,3095 +31,1027 @@ if (!supported) return {supported: false}
// Otherwise, the library will be here
-/* global createElement, capitalize */
-/* eslint-disable new-cap */
-
-// The main wrapping element
-var SVG = this.SVG = function (element) {
- if (SVG.supported) {
- element = createElement(element)
- return element
- }
-}
-
-// Svg must be supported if we reached this stage
-SVG.supported = true
-
-// Default namespaces
-SVG.ns = 'http://www.w3.org/2000/svg'
-SVG.xmlns = 'http://www.w3.org/2000/xmlns/'
-SVG.xlink = 'http://www.w3.org/1999/xlink'
-SVG.svgjs = 'http://svgjs.com/svgjs'
-
-// Element id sequence
-SVG.did = 1000
-
-// Get next named element id
-SVG.eid = function (name) {
- return 'Svgjs' + capitalize(name) + (SVG.did++)
-}
-
-// Method for element creation
-SVG.create = function (name) {
- // create element
- return document.createElementNS(this.ns, name)
-}
-
-// Method for extending objects
-SVG.extend = function (modules, methods) {
- var key, i
-
- modules = Array.isArray(modules) ? modules : [modules]
-
- for (i = modules.length - 1; i >= 0; i--) {
- if (modules[i]) {
- for (key in methods) {
- modules[i].prototype[key] = methods[key]
- }
- }
- }
-}
-
-// Invent new element
-SVG.invent = function (config) {
- // Create element initializer
- var initializer = typeof config.create === 'function' ? config.create
- : function (node) {
- this.constructor(node || SVG.create(config.create))
- }
-
- // Inherit prototype
- if (config.inherit) {
- initializer.prototype = new config.inherit()
- }
-
- // Extend with methods
- if (config.extend) {
- SVG.extend(initializer, config.extend)
- }
-
- // Attach construct method to parent
- if (config.construct) { SVG.extend(config.parent || SVG.Container, config.construct) }
-
- return initializer
-}
-
-// Adopt existing svg elements
-SVG.adopt = function (node) {
- // check for presence of node
- if (!node) return null
-
- // make sure a node isn't already adopted
- if (node.instance instanceof SVG.Element) return node.instance
-
- if (!(node instanceof window.SVGElement)) {
- return new SVG.HtmlNode(node)
- }
-
- // initialize variables
- var element
-
- // adopt with element-specific settings
- if (node.nodeName === 'svg') {
- element = new SVG.Doc(node)
- } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') {
- element = new SVG.Gradient(node)
- } else if (SVG[capitalize(node.nodeName)]) {
- element = new SVG[capitalize(node.nodeName)](node)
- } else {
- element = new SVG.Parent(node)
- }
-
- return element
-}
+"use strict"; -// Storage for regular expressions
-SVG.regex = {
- // Parse unit value
- numberAndUnit: /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,
-
- // Parse hex value
- hex: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
-
- // Parse rgb value
- rgb: /rgb\((\d+),(\d+),(\d+)\)/,
-
- // Parse reference id
- reference: /#([a-z0-9\-_]+)/i,
-
- // splits a transformation chain
- transforms: /\)\s*,?\s*/,
-
- // Whitespace
- whitespace: /\s/g,
-
- // Test hex value
- isHex: /^#[a-f0-9]{3,6}$/i,
-
- // Test rgb value
- isRgb: /^rgb\(/,
-
- // Test css declaration
- isCss: /[^:]+:[^;]+;?/,
-
- // Test for blank string
- isBlank: /^(\s+)?$/,
-
- // Test for numeric string
- isNumber: /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
-
- // Test for percent value
- isPercent: /^-?[\d.]+%$/,
-
- // Test for image url
- isImage: /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,
-
- // split at whitespace and comma
- delimiter: /[\s,]+/,
-
- // The following regex are used to parse the d attribute of a path
-
- // Matches all hyphens which are not after an exponent
- hyphen: /([^e])-/gi,
-
- // Replaces and tests for all path letters
- pathLetters: /[MLHVCSQTAZ]/gi,
-
- // yes we need this one, too
- isPathLetter: /[MLHVCSQTAZ]/i,
-
- // matches 0.154.23.45
- numbersWithDots: /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,
-
- // matches .
- dots: /\./g
-}
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } -SVG.utils = {
- // Map function
- map: function (array, block) {
- var i
- var il = array.length
- var result = []
-
- for (i = 0; i < il; i++) {
- result.push(block(array[i]))
- }
-
- return result
- },
-
- // Filter function
- filter: function (array, block) {
- var i
- var il = array.length
- var result = []
-
- for (i = 0; i < il; i++) {
- if (block(array[i])) { result.push(array[i]) }
- }
-
- return result
- },
-
- // Degrees to radians
- radians: function (d) {
- return d % 360 * Math.PI / 180
- },
-
- // Radians to degrees
- degrees: function (r) {
- return r * 180 / Math.PI % 360
- },
-
- filterSVGElements: function (nodes) {
- return this.filter(nodes, function (el) { return el instanceof window.SVGElement })
- }
-
-}
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } -
-SVG.defaults = {
-
- // Default attribute values
- attrs: {
-
- // fill and stroke
- 'fill-opacity': 1,
- 'stroke-opacity': 1,
- 'stroke-width': 0,
- 'stroke-linejoin': 'miter',
- 'stroke-linecap': 'butt',
- fill: '#000000',
- stroke: '#000000',
- opacity: 1,
-
- // position
- x: 0,
- y: 0,
- cx: 0,
- cy: 0,
-
- // size
- width: 0,
- height: 0,
-
- // radius
- r: 0,
- rx: 0,
- ry: 0,
-
- // gradient
- offset: 0,
- 'stop-opacity': 1,
- 'stop-color': '#000000',
-
- // text
- 'font-size': 16,
- 'font-family': 'Helvetica, Arial, sans-serif',
- 'text-anchor': 'start'
- }
-}
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } -/* globals fullHex, compToHex */
-
-// Module for color convertions
-SVG.Color = function (color) {
- var match
-
- // initialize defaults
- this.r = 0
- this.g = 0
- this.b = 0
-
- if (!color) return
-
- // parse color
- if (typeof color === 'string') {
- if (SVG.regex.isRgb.test(color)) {
- // get rgb values
- match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, ''))
-
- // parse numeric values
- this.r = parseInt(match[1])
- this.g = parseInt(match[2])
- this.b = parseInt(match[3])
- } else if (SVG.regex.isHex.test(color)) {
- // get hex values
- match = SVG.regex.hex.exec(fullHex(color))
-
- // parse numeric values
- this.r = parseInt(match[1], 16)
- this.g = parseInt(match[2], 16)
- this.b = parseInt(match[3], 16)
- }
- } else if (typeof color === 'object') {
- this.r = color.r
- this.g = color.g
- this.b = color.b
- }
-}
-
-SVG.extend(SVG.Color, {
- // Default to hex conversion
- toString: function () {
- return this.toHex()
- },
- // Build hex value
- toHex: function () {
- return '#' +
- compToHex(this.r) +
- compToHex(this.g) +
- compToHex(this.b)
- },
- // Build rgb value
- toRgb: function () {
- return 'rgb(' + [this.r, this.g, this.b].join() + ')'
- },
- // Calculate true brightness
- brightness: function () {
- return (this.r / 255 * 0.30) +
- (this.g / 255 * 0.59) +
- (this.b / 255 * 0.11)
- },
- // Make color morphable
- morph: function (color) {
- this.destination = new SVG.Color(color)
-
- return this
- },
- // Get morphed color at given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- // normalise pos
- pos = pos < 0 ? 0 : pos > 1 ? 1 : pos
-
- // generate morphed color
- return new SVG.Color({
- r: ~~(this.r + (this.destination.r - this.r) * pos),
- g: ~~(this.g + (this.destination.g - this.g) * pos),
- b: ~~(this.b + (this.destination.b - this.b) * pos)
- })
- }
-
-})
-
-// Testers
-
-// Test if given value is a color string
-SVG.Color.test = function (color) {
- color += ''
- return SVG.regex.isHex.test(color) ||
- SVG.regex.isRgb.test(color)
-}
-
-// Test if given value is a rgb object
-SVG.Color.isRgb = function (color) {
- return color && typeof color.r === 'number' &&
- typeof color.g === 'number' &&
- typeof color.b === 'number'
-}
-
-// Test if given value is a color
-SVG.Color.isColor = function (color) {
- return SVG.Color.isRgb(color) || SVG.Color.test(color)
-}
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } -/* global arrayClone */
-
-// Module for array conversion
-SVG.Array = function (array, fallback) {
- array = (array || []).valueOf()
-
- // if array is empty and fallback is provided, use fallback
- if (array.length === 0 && fallback) {
- array = fallback.valueOf()
- }
-
- // parse array
- this.value = this.parse(array)
-}
-
-SVG.extend(SVG.Array, {
- // Make array morphable
- morph: function (array) {
- this.destination = this.parse(array)
-
- // normalize length of arrays
- if (this.value.length !== this.destination.length) {
- var lastValue = this.value[this.value.length - 1]
- var lastDestination = this.destination[this.destination.length - 1]
-
- while (this.value.length > this.destination.length) {
- this.destination.push(lastDestination)
- }
- while (this.value.length < this.destination.length) {
- this.value.push(lastValue)
- }
- }
-
- return this
- },
- // Clean up any duplicate points
- settle: function () {
- // find all unique values
- for (var i = 0, il = this.value.length, seen = []; i < il; i++) {
- if (seen.indexOf(this.value[i]) === -1) {
- seen.push(this.value[i])
- }
- }
-
- // set new value
- this.value = seen
- return seen
- },
- // Get morphed array at given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- // generate morphed array
- for (var i = 0, il = this.value.length, array = []; i < il; i++) {
- array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos)
- }
-
- return new SVG.Array(array)
- },
- // Convert array to string
- toString: function () {
- return this.value.join(' ')
- },
- // Real value
- valueOf: function () {
- return this.value
- },
- // Parse whitespace separated string
- parse: function (array) {
- array = array.valueOf()
-
- // if already is an array, no need to parse it
- if (Array.isArray(array)) return array
-
- return array.trim().split(SVG.regex.delimiter).map(parseFloat)
- },
- // Reverse array
- reverse: function () {
- this.value.reverse()
-
- return this
- },
- clone: function () {
- var clone = new this.constructor()
- clone.value = arrayClone(this.value)
- return clone
- }
-})
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } -
-// Poly points array
-SVG.PointArray = function (array, fallback) {
- SVG.Array.call(this, array, fallback || [[0, 0]])
-}
-
-// Inherit from SVG.Array
-SVG.PointArray.prototype = new SVG.Array()
-SVG.PointArray.prototype.constructor = SVG.PointArray
-
-SVG.extend(SVG.PointArray, {
- // Convert array to string
- toString: function () {
- // convert to a poly point string
- for (var i = 0, il = this.value.length, array = []; i < il; i++) {
- array.push(this.value[i].join(','))
- }
-
- return array.join(' ')
- },
-
- // Convert array to line object
- toLine: function () {
- return {
- x1: this.value[0][0],
- y1: this.value[0][1],
- x2: this.value[1][0],
- y2: this.value[1][1]
- }
- },
-
- // Get morphed array at given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- // generate morphed point string
- for (var i = 0, il = this.value.length, array = []; i < il; i++) {
- array.push([
- this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos,
- this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos
- ])
- }
-
- return new SVG.PointArray(array)
- },
-
- // Parse point string and flat array
- parse: function (array) {
- var points = []
-
- array = array.valueOf()
-
- // if it is an array
- if (Array.isArray(array)) {
- // and it is not flat, there is no need to parse it
- if (Array.isArray(array[0])) {
- return array
- }
- } else { // Else, it is considered as a string
- // parse points
- array = array.trim().split(SVG.regex.delimiter).map(parseFloat)
- }
-
- // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints
- // Odd number of coordinates is an error. In such cases, drop the last odd coordinate.
- if (array.length % 2 !== 0) array.pop()
-
- // wrap points in two-tuples and parse points as floats
- for (var i = 0, len = array.length; i < len; i = i + 2) {
- points.push([ array[i], array[i + 1] ])
- }
-
- return points
- },
-
- // Move point string
- move: function (x, y) {
- var box = this.bbox()
-
- // get relative offset
- x -= box.x
- y -= box.y
-
- // move every point
- if (!isNaN(x) && !isNaN(y)) {
- for (var i = this.value.length - 1; i >= 0; i--) {
- this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]
- }
- }
-
- return this
- },
- // Resize poly string
- size: function (width, height) {
- var i
- var box = this.bbox()
-
- // recalculate position of all points according to new size
- for (i = this.value.length - 1; i >= 0; i--) {
- if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x
- if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y
- }
-
- return this
- },
-
- // Get bounding box of points
- bbox: function () {
- var maxX = -Infinity
- var maxY = -Infinity
- var minX = Infinity
- var minY = Infinity
- this.value.forEach(function (el) {
- maxX = Math.max(el[0], maxX)
- maxY = Math.max(el[1], maxY)
- minX = Math.min(el[0], minX)
- minY = Math.min(el[1], minY)
- })
- return {x: minX, y: minY, width: maxX - minX, height: maxY - minY}
- }
-})
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } -/* globals arrayToString, pathRegReplace */
-
-var pathHandlers = {
- M: function (c, p, p0) {
- p.x = p0.x = c[0]
- p.y = p0.y = c[1]
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +/* global createElement, capitalize */ + +/* eslint-disable new-cap */ +// The main wrapping element +var SVG = window.SVG = function (element) { + if (SVG.supported) { + element = createElement(element); + return element; + } +}; // Svg must be supported if we reached this stage + + +SVG.supported = true; // Default namespaces + +SVG.ns = 'http://www.w3.org/2000/svg'; +SVG.xmlns = 'http://www.w3.org/2000/xmlns/'; +SVG.xlink = 'http://www.w3.org/1999/xlink'; +SVG.svgjs = 'http://svgjs.com/svgjs'; // Element id sequence + +SVG.did = 1000; // Get next named element id + +SVG.eid = function (name) { + return 'Svgjs' + capitalize(name) + SVG.did++; +}; // Method for element creation + + +SVG.create = function (name) { + // create element + return document.createElementNS(this.ns, name); +}; // Method for extending objects + + +SVG.extend = function (modules, methods) { + var key, i; + modules = Array.isArray(modules) ? modules : [modules]; + + for (i = modules.length - 1; i >= 0; i--) { + if (modules[i]) { + for (key in methods) { + modules[i].prototype[key] = methods[key]; + } + } + } +}; // Invent new element + + +SVG.invent = function (config) { + // Create element initializer + var initializer = typeof config.create === 'function' ? config.create : function (node) { + config.inherit.call(this, node || SVG.create(config.create)); + }; // Inherit prototype + + if (config.inherit) { + initializer.prototype = new config.inherit(); + initializer.prototype.constructor = initializer; + } // Extend with methods + + + if (config.extend) { + SVG.extend(initializer, config.extend); + } // Attach construct method to parent + + + if (config.construct) { + SVG.extend(config.parent || SVG.Container, config.construct); + } + + return initializer; +}; // Adopt existing svg elements + + +SVG.adopt = function (node) { + // check for presence of node + if (!node) return null; // make sure a node isn't already adopted + + if (node.instance instanceof SVG.Element) return node.instance; + + if (!(node instanceof window.SVGElement)) { + return new SVG.HtmlNode(node); + } // initialize variables + + + var element; // adopt with element-specific settings + + if (node.nodeName === 'svg') { + element = new SVG.Doc(node); + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new SVG.Gradient(node); + } else if (SVG[capitalize(node.nodeName)]) { + element = new SVG[capitalize(node.nodeName)](node); + } else { + element = new SVG.Parent(node); + } + + return element; +}; // Storage for regular expressions + + +SVG.regex = { + // Parse unit value + numberAndUnit: /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i, + // Parse hex value + hex: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i, + // Parse rgb value + rgb: /rgb\((\d+),(\d+),(\d+)\)/, + // Parse reference id + reference: /#([a-z0-9\-_]+)/i, + // splits a transformation chain + transforms: /\)\s*,?\s*/, + // Whitespace + whitespace: /\s/g, + // Test hex value + isHex: /^#[a-f0-9]{3,6}$/i, + // Test rgb value + isRgb: /^rgb\(/, + // Test css declaration + isCss: /[^:]+:[^;]+;?/, + // Test for blank string + isBlank: /^(\s+)?$/, + // Test for numeric string + isNumber: /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, + // Test for percent value + isPercent: /^-?[\d.]+%$/, + // Test for image url + isImage: /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i, + // split at whitespace and comma + delimiter: /[\s,]+/, + // The following regex are used to parse the d attribute of a path + // Matches all hyphens which are not after an exponent + hyphen: /([^e])-/gi, + // Replaces and tests for all path letters + pathLetters: /[MLHVCSQTAZ]/gi, + // yes we need this one, too + isPathLetter: /[MLHVCSQTAZ]/i, + // matches 0.154.23.45 + numbersWithDots: /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi, + // matches . + dots: /\./g +}; +SVG.utils = { + // Map function + map: function map(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + result.push(block(array[i])); + } + + return result; + }, + // Filter function + filter: function filter(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]); + } + } + + return result; + }, + // Degrees to radians + radians: function radians(d) { + return d % 360 * Math.PI / 180; + }, + // Radians to degrees + degrees: function degrees(r) { + return r * 180 / Math.PI % 360; + }, + filterSVGElements: function filterSVGElements(nodes) { + return this.filter(nodes, function (el) { + return el instanceof window.SVGElement; + }); + } +}; + +SVG.void = function () {}; + +SVG.defaults = { + // Default animation values + timeline: { + duration: 400, + ease: '>', + delay: 0 + }, + // Default attribute values + attrs: { + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + // size + width: 0, + height: 0, + // radius + r: 0, + rx: 0, + ry: 0, + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' + } +}; +SVG.Queue = SVG.invent({ + create: function create() { + this._first = null; + this._last = null; + }, + extend: { + push: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated + + }; + + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { + this._last = item; + this._first = item; + } // Update the length and return the current item + + + return item; + }, + shift: function shift() { + // Check if we have a value + var remove = this._first; + if (!remove) return null; // If we do, remove it and relink things + + this._first = remove.next; + if (this._first) this._first.prev = null; + this._last = this._first ? this._last : null; + return remove.value; + }, + // Shows us the first item in the list + first: function first() { + return this._first && this._first.value; + }, + // Shows us the last item in the list + last: function last() { + return this._last && this._last.value; + }, + // Removes the item that was returned from the push + remove: function remove(item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next; + if (item.next) item.next.prev = item.prev; + if (item === this._last) this._last = item.prev; + if (item === this._first) this._first = item.next; // Invalidate item + + item.prev = null; + item.next = null; + } + } +}); +/* globals fullHex, compToHex */ + +/*
- return ['M', p.x, p.y]
- },
- L: function (c, p) {
- p.x = c[0]
- p.y = c[1]
- return ['L', c[0], c[1]]
- },
- H: function (c, p) {
- p.x = c[0]
- return ['H', c[0]]
+Color {
+ constructor (a, b, c, space) {
+ space: 'hsl'
+ a: 30
+ b: 20
+ c: 10
},
- V: function (c, p) {
- p.y = c[0]
- return ['V', c[0]]
- },
- C: function (c, p) {
- p.x = c[4]
- p.y = c[5]
- return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]
- },
- S: function (c, p) {
- p.x = c[2]
- p.y = c[3]
- return ['S', c[0], c[1], c[2], c[3]]
- },
- Q: function (c, p) {
- p.x = c[2]
- p.y = c[3]
- return ['Q', c[0], c[1], c[2], c[3]]
- },
- T: function (c, p) {
- p.x = c[0]
- p.y = c[1]
- return ['T', c[0], c[1]]
- },
- Z: function (c, p, p0) {
- p.x = p0.x
- p.y = p0.y
- return ['Z']
- },
- A: function (c, p) {
- p.x = c[5]
- p.y = c[6]
- return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]
- }
-}
-
-var mlhvqtcsaz = 'mlhvqtcsaz'.split('')
-for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) {
- pathHandlers[mlhvqtcsaz[i]] = (function (i) {
- return function (c, p, p0) {
- if (i === 'H') c[0] = c[0] + p.x
- else if (i === 'V') c[0] = c[0] + p.y
- else if (i === 'A') {
- c[5] = c[5] + p.x
- c[6] = c[6] + p.y
- } else {
- for (var j = 0, jl = c.length; j < jl; ++j) {
- c[j] = c[j] + (j % 2 ? p.y : p.x)
- }
- }
-
- return pathHandlers[i](c, p, p0)
- }
- })(mlhvqtcsaz[i].toUpperCase())
-}
+ toRgb () { return new Color in rgb space }
+ toHsl () { return new Color in hsl space }
+ toLab () { return new Color in lab space }
-// Path points array
-SVG.PathArray = function (array, fallback) {
- SVG.Array.call(this, array, fallback || [['M', 0, 0]])
+ toArray () { [space, a, b, c] }
+ fromArray () { convert it back }
}
-// Inherit from SVG.Array
-SVG.PathArray.prototype = new SVG.Array()
-SVG.PathArray.prototype.constructor = SVG.PathArray
-
-SVG.extend(SVG.PathArray, {
- // Convert array to string
- toString: function () {
- return arrayToString(this.value)
- },
- // Move path string
- move: function (x, y) {
- // get bounding box of current situation
- var box = this.bbox()
-
- // get relative offset
- x -= box.x
- y -= box.y
-
- if (!isNaN(x) && !isNaN(y)) {
- // move every point
- for (var l, i = this.value.length - 1; i >= 0; i--) {
- l = this.value[i][0]
-
- if (l === 'M' || l === 'L' || l === 'T') {
- this.value[i][1] += x
- this.value[i][2] += y
- } else if (l === 'H') {
- this.value[i][1] += x
- } else if (l === 'V') {
- this.value[i][1] += y
- } else if (l === 'C' || l === 'S' || l === 'Q') {
- this.value[i][1] += x
- this.value[i][2] += y
- this.value[i][3] += x
- this.value[i][4] += y
-
- if (l === 'C') {
- this.value[i][5] += x
- this.value[i][6] += y
- }
- } else if (l === 'A') {
- this.value[i][6] += x
- this.value[i][7] += y
- }
- }
- }
-
- return this
- },
- // Resize path string
- size: function (width, height) {
- // get bounding box of current situation
- var box = this.bbox()
- var i, l
-
- // recalculate position of all points according to new size
- for (i = this.value.length - 1; i >= 0; i--) {
- l = this.value[i][0]
-
- if (l === 'M' || l === 'L' || l === 'T') {
- this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x
- this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y
- } else if (l === 'H') {
- this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x
- } else if (l === 'V') {
- this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y
- } else if (l === 'C' || l === 'S' || l === 'Q') {
- this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x
- this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y
- this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x
- this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y
-
- if (l === 'C') {
- this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x
- this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y
- }
- } else if (l === 'A') {
- // resize radii
- this.value[i][1] = (this.value[i][1] * width) / box.width
- this.value[i][2] = (this.value[i][2] * height) / box.height
-
- // move position values
- this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x
- this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y
- }
- }
-
- return this
- },
- // Test if the passed path array use the same path data commands as this path array
- equalCommands: function (pathArray) {
- var i, il, equalCommands
-
- pathArray = new SVG.PathArray(pathArray)
-
- equalCommands = this.value.length === pathArray.value.length
- for (i = 0, il = this.value.length; equalCommands && i < il; i++) {
- equalCommands = this.value[i][0] === pathArray.value[i][0]
- }
-
- return equalCommands
- },
- // Make path array morphable
- morph: function (pathArray) {
- pathArray = new SVG.PathArray(pathArray)
-
- if (this.equalCommands(pathArray)) {
- this.destination = pathArray
- } else {
- this.destination = null
- }
-
- return this
- },
- // Get morphed path array at given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- var sourceArray = this.value
- var destinationArray = this.destination.value
- var array = []
- var pathArray = new SVG.PathArray()
- var i, il, j, jl
-
- // Animate has specified in the SVG spec
- // See: https://www.w3.org/TR/SVG11/paths.html#PathElement
- for (i = 0, il = sourceArray.length; i < il; i++) {
- array[i] = [sourceArray[i][0]]
- for (j = 1, jl = sourceArray[i].length; j < jl; j++) {
- array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos
- }
- // For the two flags of the elliptical arc command, the SVG spec say:
- // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true
- // Elliptical arc command as an array followed by corresponding indexes:
- // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
- // 0 1 2 3 4 5 6 7
- if (array[i][0] === 'A') {
- array[i][4] = +(array[i][4] !== 0)
- array[i][5] = +(array[i][5] !== 0)
- }
- }
-
- // Directly modify the value of a path array, this is done this way for performance
- pathArray.value = array
- return pathArray
- },
- // Absolutize and parse path to array
- parse: function (array) {
- // if it's already a patharray, no need to parse it
- if (array instanceof SVG.PathArray) return array.valueOf()
-
- // prepare for parsing
- var s
- var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 }
-
- if (typeof array === 'string') {
- array = array
- .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123
- .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers
- .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen
- .trim() // trim
- .split(SVG.regex.delimiter) // split into array
- } else {
- array = array.reduce(function (prev, curr) {
- return [].concat.call(prev, curr)
- }, [])
- }
-
- // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...]
- var result = []
- var p = new SVG.Point()
- var p0 = new SVG.Point()
- var index = 0
- var len = array.length
-
- do {
- // Test if we have a path letter
- if (SVG.regex.isPathLetter.test(array[index])) {
- s = array[index]
- ++index
- // If last letter was a move command and we got no new, it defaults to [L]ine
- } else if (s === 'M') {
- s = 'L'
- } else if (s === 'm') {
- s = 'l'
- }
-
- result.push(pathHandlers[s].call(null,
- array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat),
- p, p0
- )
- )
- } while (len > index)
-
- return result
- },
- // Get bounding box of path
- bbox: function () {
- SVG.parser().path.setAttribute('d', this.toString())
- return SVG.parser.nodes.path.getBBox()
- }
-
-})
+// Conversions aren't always exact because of monitor profiles etc...
+new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl()
+new Color(100, 100, 100, [space])
+new Color('hsl(30, 20, 10)')
+
+// Sugar
+SVG.rgb(30, 20, 50).lab()
+SVG.hsl()
+SVG.lab('rgb(100, 100, 100)')
+*/ +// Module for color convertions -
-// Module for unit convertions
-SVG.Number = SVG.invent({
- // Initialize
- create: function (value, unit) {
- // initialize defaults
- this.value = 0
- this.unit = unit || ''
-
- // parse value
- if (typeof value === 'number') {
- // ensure a valid numeric value
- this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value
- } else if (typeof value === 'string') {
- unit = value.match(SVG.regex.numberAndUnit)
-
- if (unit) {
- // make value numeric
- this.value = parseFloat(unit[1])
-
- // normalize
- if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') {
- this.value *= 1000
- }
-
- // store unit
- this.unit = unit[5]
- }
- } else {
- if (value instanceof SVG.Number) {
- this.value = value.valueOf()
- this.unit = value.unit
- }
- }
- },
- // Add methods
- extend: {
- // Stringalize
- toString: function () {
- return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6
- : this.unit === 's' ? this.value / 1e3
- : this.value
- ) + this.unit
- },
- toJSON: function () {
- return this.toString()
- }, // Convert to primitive
- valueOf: function () {
- return this.value
- },
- // Add number
- plus: function (number) {
- number = new SVG.Number(number)
- return new SVG.Number(this + number, this.unit || number.unit)
- },
- // Subtract number
- minus: function (number) {
- number = new SVG.Number(number)
- return new SVG.Number(this - number, this.unit || number.unit)
- },
- // Multiply number
- times: function (number) {
- number = new SVG.Number(number)
- return new SVG.Number(this * number, this.unit || number.unit)
- },
- // Divide number
- divide: function (number) {
- number = new SVG.Number(number)
- return new SVG.Number(this / number, this.unit || number.unit)
- },
- // Convert to different unit
- to: function (unit) {
- var number = new SVG.Number(this)
-
- if (typeof unit === 'string') {
- number.unit = unit
- }
-
- return number
- },
- // Make number morphable
- morph: function (number) {
- this.destination = new SVG.Number(number)
-
- if (number.relative) {
- this.destination.value += this.value
- }
-
- return this
- },
- // Get morphed number at given position
- at: function (pos) {
- // Make sure a destination is defined
- if (!this.destination) return this
-
- // Generate new morphed number
- return new SVG.Number(this.destination)
- .minus(this)
- .times(pos)
- .plus(this)
- }
-
- }
-})
+SVG.Color = function (color, g, b) { + var match; // initialize defaults -/* global createElement */
-
-SVG.HtmlNode = SVG.invent({
- create: function (element) {
- this.node = element
- },
-
- extend: {
- add: function (element, i) {
- element = createElement(element)
-
- if (element.node !== this.node.children[i]) {
- this.node.insertBefore(element.node, this.node.children[i] || null)
- }
-
- return this
- },
-
- put: function (element, i) {
- this.add(element, i)
- return element
- }
- }
-})
+ this.r = 0; + this.g = 0; + this.b = 0; + if (!color) return; // parse color -/* global proportionalSize, assignNewId, createElement, matches, is */
-
-SVG.Element = SVG.invent({
- // Initialize node
- create: function (node) {
- // event listener
- this.events = {}
-
- // initialize data object
- this.dom = {}
-
- // create circular reference
- this.node = node
- if (this.node) {
- this.type = node.nodeName
- this.node.instance = this
- this.events = node.events || {}
-
- if (node.hasAttribute('svgjs:data')) {
- // pull svgjs data from the dom (getAttributeNS doesn't work in html5)
- this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {})
- }
- }
- },
-
- // Add class methods
- extend: {
- // Move over x-axis
- x: function (x) {
- return this.attr('x', x)
- },
-
- // Move over y-axis
- y: function (y) {
- return this.attr('y', y)
- },
-
- // Move by center over x-axis
- cx: function (x) {
- return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)
- },
-
- // Move by center over y-axis
- cy: function (y) {
- return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2)
- },
-
- // Move element to given x and y values
- move: function (x, y) {
- return this.x(x).y(y)
- },
-
- // Move element by its center
- center: function (x, y) {
- return this.cx(x).cy(y)
- },
-
- // Set width of element
- width: function (width) {
- return this.attr('width', width)
- },
-
- // Set height of element
- height: function (height) {
- return this.attr('height', height)
- },
-
- // Set element size to given width and height
- size: function (width, height) {
- var p = proportionalSize(this, width, height)
-
- return this
- .width(new SVG.Number(p.width))
- .height(new SVG.Number(p.height))
- },
-
- // Clone element
- clone: function (parent) {
- // write dom data to the dom so the clone can pickup the data
- this.writeDataToDom()
-
- // clone element and assign new id
- var clone = assignNewId(this.node.cloneNode(true))
-
- // insert the clone in the given parent or after myself
- if (parent) parent.add(clone)
- else this.after(clone)
-
- return clone
- },
-
- // Remove element
- remove: function () {
- if (this.parent()) { this.parent().removeElement(this) }
-
- return this
- },
-
- // Replace element
- replace: function (element) {
- this.after(element).remove()
-
- return element
- },
-
- // Add element to given container and return self
- addTo: function (parent) {
- return createElement(parent).put(this)
- },
-
- // Add element to given container and return container
- putIn: function (parent) {
- return createElement(parent).add(this)
- },
-
- // Get / set id
- id: function (id) {
- // generate new id if no id set
- if (typeof id === 'undefined' && !this.node.id) {
- this.node.id = SVG.eid(this.type)
- }
-
- // dont't set directly width this.node.id to make `null` work correctly
- return this.attr('id', id)
- },
-
- // Checks whether the given point inside the bounding box of the element
- inside: function (x, y) {
- var box = this.bbox()
-
- return x > box.x &&
- y > box.y &&
- x < box.x + box.width &&
- y < box.y + box.height
- },
-
- // Show element
- show: function () {
- return this.css('display', '')
- },
-
- // Hide element
- hide: function () {
- return this.css('display', 'none')
- },
-
- // Is element visible?
- visible: function () {
- return this.css('display') !== 'none'
- },
-
- // Return id on string conversion
- toString: function () {
- return this.id()
- },
-
- // Return array of classes on the node
- classes: function () {
- var attr = this.attr('class')
- return attr == null ? [] : attr.trim().split(SVG.regex.delimiter)
- },
-
- // Return true if class exists on the node, false otherwise
- hasClass: function (name) {
- return this.classes().indexOf(name) !== -1
- },
-
- // Add class to the node
- addClass: function (name) {
- if (!this.hasClass(name)) {
- var array = this.classes()
- array.push(name)
- this.attr('class', array.join(' '))
- }
-
- return this
- },
-
- // Remove class from the node
- removeClass: function (name) {
- if (this.hasClass(name)) {
- this.attr('class', this.classes().filter(function (c) {
- return c !== name
- }).join(' '))
- }
-
- return this
- },
-
- // Toggle the presence of a class on the node
- toggleClass: function (name) {
- return this.hasClass(name) ? this.removeClass(name) : this.addClass(name)
- },
-
- // Get referenced element form attribute value
- reference: function (attr) {
- return SVG.get(this.attr(attr))
- },
-
- // Returns the parent element instance
- parent: function (type) {
- var parent = this
-
- // check for parent
- if (!parent.node.parentNode) return null
-
- // get parent element
- parent = SVG.adopt(parent.node.parentNode)
-
- if (!type) return parent
-
- // loop trough ancestors if type is given
- while (parent && parent.node instanceof window.SVGElement) {
- if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent
- parent = SVG.adopt(parent.node.parentNode)
- }
- },
-
- // Get parent document
- doc: function () {
- var p = this.parent(SVG.Doc)
- return p && p.doc()
- },
-
- // Get defs
- defs: function () {
- return this.doc().defs()
- },
-
- // return array of all ancestors of given type up to the root svg
- parents: function (type) {
- var parents = []
- var parent = this
-
- do {
- parent = parent.parent(type)
- if (!parent || !parent.node) break
-
- parents.push(parent)
- } while (parent.parent)
-
- return parents
- },
-
- // matches the element vs a css selector
- matches: function (selector) {
- return matches(this.node, selector)
- },
-
- // Returns the svg node to call native svg methods on it
- native: function () {
- return this.node
- },
-
- // Import raw svg
- svg: function (svg) {
- var well, len
-
- // act as a setter if svg is given
- if (svg && this instanceof SVG.Parent) {
- // create temporary holder
- well = document.createElementNS(SVG.ns, 'svg')
- // dump raw svg
- well.innerHTML = svg
-
- // transplant nodes
- for (len = well.children.length; len--;) {
- this.node.appendChild(well.firstElementChild)
- }
-
- // otherwise act as a getter
- } else {
- // write svgjs data to the dom
- this.writeDataToDom()
-
- return this.node.outerHTML
- }
-
- return this
- },
-
- // write svgjs data to the dom
- writeDataToDom: function () {
- // dump variables recursively
- if (this.is(SVG.Parent)) {
- this.each(function () {
- this.writeDataToDom()
- })
- }
-
- // remove previously set data
- this.node.removeAttribute('svgjs:data')
-
- if (Object.keys(this.dom).length) {
- this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428
- }
- return this
- },
-
- // set given data to the elements data property
- setData: function (o) {
- this.dom = o
- return this
- },
- is: function (obj) {
- return is(this, obj)
- }
- }
-})
+ if (typeof color === 'string') { + if (SVG.regex.isRgb.test(color)) { + // get rgb values + match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, '')); // parse numeric values -SVG.easing = {
- '-': function (pos) { return pos },
- '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 },
- '>': function (pos) { return Math.sin(pos * Math.PI / 2) },
- '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }
-}
-
-SVG.morph = function (pos) {
- return function (from, to) {
- return new SVG.MorphObj(from, to).at(pos)
- }
-}
-
-SVG.Situation = SVG.invent({
-
- create: function (o) {
- this.init = false
- this.reversed = false
- this.reversing = false
-
- this.duration = new SVG.Number(o.duration).valueOf()
- this.delay = new SVG.Number(o.delay).valueOf()
-
- this.start = +new Date() + this.delay
- this.finish = this.start + this.duration
- this.ease = o.ease
-
- // this.loop is incremented from 0 to this.loops
- // it is also incremented when in an infinite loop (when this.loops is true)
- this.loop = 0
- this.loops = false
-
- this.animations = {
- // functionToCall: [list of morphable objects]
- // e.g. move: [SVG.Number, SVG.Number]
- }
-
- this.attrs = {
- // holds all attributes which are not represented from a function svg.js provides
- // e.g. someAttr: SVG.Number
- }
-
- this.styles = {
- // holds all styles which should be animated
- // e.g. fill-color: SVG.Color
- }
-
- this.transforms = [
- // holds all transformations as transformation objects
- // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix]
- ]
-
- this.once = {
- // functions to fire at a specific position
- // e.g. "0.5": function foo(){}
- }
- }
-
-})
-
-SVG.FX = SVG.invent({
-
- create: function (element) {
- this._target = element
- this.situations = []
- this.active = false
- this.situation = null
- this.paused = false
- this.lastPos = 0
- this.pos = 0
- // The absolute position of an animation is its position in the context of its complete duration (including delay and loops)
- // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1
- this.absPos = 0
- this._speed = 1
- },
-
- extend: {
-
- /**
- * sets or returns the target of this animation
- * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation
- * @param ease function || string Function which should be used for easing or easing keyword
- * @param delay Number indicating the delay before the animation starts
- * @return target || this
- */
- animate: function (o, ease, delay) {
- if (typeof o === 'object') {
- ease = o.ease
- delay = o.delay
- o = o.duration
- }
-
- var situation = new SVG.Situation({
- duration: o || 1000,
- delay: delay || 0,
- ease: SVG.easing[ease || '-'] || ease
- })
-
- this.queue(situation)
-
- return this
- },
-
- /**
- * sets a delay before the next element of the queue is called
- * @param delay Duration of delay in milliseconds
- * @return this.target()
- */
- delay: function (delay) {
- // The delay is performed by an empty situation with its duration
- // attribute set to the duration of the delay
- var situation = new SVG.Situation({
- duration: delay,
- delay: 0,
- ease: SVG.easing['-']
- })
-
- return this.queue(situation)
- },
-
- /**
- * sets or returns the target of this animation
- * @param null || target SVG.Element which should be set as new target
- * @return target || this
- */
- target: function (target) {
- if (target && target instanceof SVG.Element) {
- this._target = target
- return this
- }
-
- return this._target
- },
-
- // returns the absolute position at a given time
- timeToAbsPos: function (timestamp) {
- return (timestamp - this.situation.start) / (this.situation.duration / this._speed)
- },
-
- // returns the timestamp from a given absolute positon
- absPosToTime: function (absPos) {
- return this.situation.duration / this._speed * absPos + this.situation.start
- },
-
- // starts the animationloop
- startAnimFrame: function () {
- this.stopAnimFrame()
- this.animationFrame = window.requestAnimationFrame(function () { this.step() }.bind(this))
- },
-
- // cancels the animationframe
- stopAnimFrame: function () {
- window.cancelAnimationFrame(this.animationFrame)
- },
-
- // kicks off the animation - only does something when the queue is currently not active and at least one situation is set
- start: function () {
- // dont start if already started
- if (!this.active && this.situation) {
- this.active = true
- this.startCurrent()
- }
-
- return this
- },
-
- // start the current situation
- startCurrent: function () {
- this.situation.start = +new Date() + this.situation.delay / this._speed
- this.situation.finish = this.situation.start + this.situation.duration / this._speed
- return this.initAnimations().step()
- },
-
- /**
- * adds a function / Situation to the animation queue
- * @param fn function / situation to add
- * @return this
- */
- queue: function (fn) {
- if (typeof fn === 'function' || fn instanceof SVG.Situation) {
- this.situations.push(fn)
- }
-
- if (!this.situation) this.situation = this.situations.shift()
-
- return this
- },
-
- /**
- * pulls next element from the queue and execute it
- * @return this
- */
- dequeue: function () {
- // stop current animation
- this.stop()
-
- // get next animation from queue
- this.situation = this.situations.shift()
-
- if (this.situation) {
- if (this.situation instanceof SVG.Situation) {
- this.start()
- } else {
- // If it is not a SVG.Situation, then it is a function, we execute it
- this.situation(this)
- }
- }
-
- return this
- },
-
- // updates all animations to the current state of the element
- // this is important when one property could be changed from another property
- initAnimations: function () {
- var i, j, source
- var s = this.situation
-
- if (s.init) return this
-
- for (i in s.animations) {
- source = this.target()[i]()
-
- if (!Array.isArray(source)) {
- source = [source]
- }
-
- if (!Array.isArray(s.animations[i])) {
- s.animations[i] = [s.animations[i]]
- }
-
- // if(s.animations[i].length > source.length) {
- // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length))
- // }
-
- for (j = source.length; j--;) {
- // The condition is because some methods return a normal number instead
- // of a SVG.Number
- if (s.animations[i][j] instanceof SVG.Number) {
- source[j] = new SVG.Number(source[j])
- }
-
- s.animations[i][j] = source[j].morph(s.animations[i][j])
- }
- }
-
- for (i in s.attrs) {
- s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i])
- }
-
- for (i in s.styles) {
- s.styles[i] = new SVG.MorphObj(this.target().css(i), s.styles[i])
- }
-
- s.initialTransformation = this.target().matrixify()
-
- s.init = true
- return this
- },
-
- clearQueue: function () {
- this.situations = []
- return this
- },
-
- clearCurrent: function () {
- this.situation = null
- return this
- },
-
- /** stops the animation immediately
- * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately.
- * @param clearQueue A Boolean indicating whether to remove queued animation as well.
- * @return this
- */
- stop: function (jumpToEnd, clearQueue) {
- var active = this.active
- this.active = false
-
- if (clearQueue) {
- this.clearQueue()
- }
-
- if (jumpToEnd && this.situation) {
- // initialize the situation if it was not
- !active && this.startCurrent()
- this.atEnd()
- }
-
- this.stopAnimFrame()
-
- return this.clearCurrent()
- },
-
- /** resets the element to the state where the current element has started
- * @return this
- */
- reset: function () {
- if (this.situation) {
- var temp = this.situation
- this.stop()
- this.situation = temp
- this.atStart()
- }
- return this
- },
-
- // Stop the currently-running animation, remove all queued animations, and complete all animations for the element.
- finish: function () {
- this.stop(true, false)
-
- while (this.dequeue().situation && this.stop(true, false));
-
- this.clearQueue().clearCurrent()
-
- return this
- },
-
- // set the internal animation pointer at the start position, before any loops, and updates the visualisation
- atStart: function () {
- return this.at(0, true)
- },
-
- // set the internal animation pointer at the end position, after all the loops, and updates the visualisation
- atEnd: function () {
- if (this.situation.loops === true) {
- // If in a infinite loop, we end the current iteration
- this.situation.loops = this.situation.loop + 1
- }
-
- if (typeof this.situation.loops === 'number') {
- // If performing a finite number of loops, we go after all the loops
- return this.at(this.situation.loops, true)
- } else {
- // If no loops, we just go at the end
- return this.at(1, true)
- }
- },
-
- // set the internal animation pointer to the specified position and updates the visualisation
- // if isAbsPos is true, pos is treated as an absolute position
- at: function (pos, isAbsPos) {
- var durDivSpd = this.situation.duration / this._speed
-
- this.absPos = pos
- // If pos is not an absolute position, we convert it into one
- if (!isAbsPos) {
- if (this.situation.reversed) this.absPos = 1 - this.absPos
- this.absPos += this.situation.loop
- }
-
- this.situation.start = +new Date() - this.absPos * durDivSpd
- this.situation.finish = this.situation.start + durDivSpd
-
- return this.step(true)
- },
-
- /**
- * sets or returns the speed of the animations
- * @param speed null || Number The new speed of the animations
- * @return Number || this
- */
- speed: function (speed) {
- if (speed === 0) return this.pause()
-
- if (speed) {
- this._speed = speed
- // We use an absolute position here so that speed can affect the delay before the animation
- return this.at(this.absPos, true)
- } else return this._speed
- },
-
- // Make loopable
- loop: function (times, reverse) {
- var c = this.last()
-
- // store total loops
- c.loops = (times != null) ? times : true
- c.loop = 0
-
- if (reverse) c.reversing = true
- return this
- },
-
- // pauses the animation
- pause: function () {
- this.paused = true
- this.stopAnimFrame()
-
- return this
- },
-
- // unpause the animation
- play: function () {
- if (!this.paused) return this
- this.paused = false
- // We use an absolute position here so that the delay before the animation can be paused
- return this.at(this.absPos, true)
- },
-
- /**
- * toggle or set the direction of the animation
- * true sets direction to backwards while false sets it to forwards
- * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status)
- * @return this
- */
- reverse: function (reversed) {
- var c = this.last()
-
- if (typeof reversed === 'undefined') c.reversed = !c.reversed
- else c.reversed = reversed
-
- return this
- },
-
- /**
- * returns a float from 0-1 indicating the progress of the current animation
- * @param eased Boolean indicating whether the returned position should be eased or not
- * @return number
- */
- progress: function (easeIt) {
- return easeIt ? this.situation.ease(this.pos) : this.pos
- },
-
- /**
- * adds a callback function which is called when the current animation is finished
- * @param fn Function which should be executed as callback
- * @return number
- */
- after: function (fn) {
- var c = this.last()
- function wrapper (e) {
- if (e.detail.situation === c) {
- fn.call(this, c)
- this.off('finished.fx', wrapper) // prevent memory leak
- }
- }
-
- this.target().on('finished.fx', wrapper)
-
- return this._callStart()
- },
-
- // adds a callback which is called whenever one animation step is performed
- during: function (fn) {
- var c = this.last()
- function wrapper (e) {
- if (e.detail.situation === c) {
- fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c)
- }
- }
-
- // see above
- this.target().off('during.fx', wrapper).on('during.fx', wrapper)
-
- this.after(function () {
- this.off('during.fx', wrapper)
- })
-
- return this._callStart()
- },
-
- // calls after ALL animations in the queue are finished
- afterAll: function (fn) {
- var wrapper = function wrapper (e) {
- fn.call(this)
- this.off('allfinished.fx', wrapper)
- }
-
- // see above
- this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper)
-
- return this._callStart()
- },
-
- // calls on every animation step for all animations
- duringAll: function (fn) {
- var wrapper = function (e) {
- fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation)
- }
-
- this.target().off('during.fx', wrapper).on('during.fx', wrapper)
-
- this.afterAll(function () {
- this.off('during.fx', wrapper)
- })
-
- return this._callStart()
- },
-
- last: function () {
- return this.situations.length ? this.situations[this.situations.length - 1] : this.situation
- },
-
- // adds one property to the animations
- add: function (method, args, type) {
- this.last()[type || 'animations'][method] = args
- return this._callStart()
- },
-
- /** perform one step of the animation
- * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time
- * @return this
- */
- step: function (ignoreTime) {
- // convert current time to an absolute position
- if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date())
-
- // This part convert an absolute position to a position
- if (this.situation.loops !== false) {
- var absPos, absPosInt, lastLoop
-
- // If the absolute position is below 0, we just treat it as if it was 0
- absPos = Math.max(this.absPos, 0)
- absPosInt = Math.floor(absPos)
-
- if (this.situation.loops === true || absPosInt < this.situation.loops) {
- this.pos = absPos - absPosInt
- lastLoop = this.situation.loop
- this.situation.loop = absPosInt
- } else {
- this.absPos = this.situation.loops
- this.pos = 1
- // The -1 here is because we don't want to toggle reversed when all the loops have been completed
- lastLoop = this.situation.loop - 1
- this.situation.loop = this.situation.loops
- }
-
- if (this.situation.reversing) {
- // Toggle reversed if an odd number of loops as occured since the last call of step
- this.situation.reversed = this.situation.reversed !== Boolean((this.situation.loop - lastLoop) % 2)
- }
- } else {
- // If there are no loop, the absolute position must not be above 1
- this.absPos = Math.min(this.absPos, 1)
- this.pos = this.absPos
- }
-
- // while the absolute position can be below 0, the position must not be below 0
- if (this.pos < 0) this.pos = 0
-
- if (this.situation.reversed) this.pos = 1 - this.pos
-
- // apply easing
- var eased = this.situation.ease(this.pos)
-
- // call once-callbacks
- for (var i in this.situation.once) {
- if (i > this.lastPos && i <= eased) {
- this.situation.once[i].call(this.target(), this.pos, eased)
- delete this.situation.once[i]
- }
- }
-
- // fire during callback with position, eased position and current situation as parameter
- if (this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation})
-
- // the user may call stop or finish in the during callback
- // so make sure that we still have a valid situation
- if (!this.situation) {
- return this
- }
-
- // apply the actual animation to every property
- this.eachAt()
-
- // do final code when situation is finished
- if ((this.pos === 1 && !this.situation.reversed) || (this.situation.reversed && this.pos === 0)) {
- // stop animation callback
- this.stopAnimFrame()
-
- // fire finished callback with current situation as parameter
- this.target().fire('finished', {fx: this, situation: this.situation})
-
- if (!this.situations.length) {
- this.target().fire('allfinished')
-
- // Recheck the length since the user may call animate in the afterAll callback
- if (!this.situations.length) {
- this.target().off('.fx') // there shouldnt be any binding left, but to make sure...
- this.active = false
- }
- }
-
- // start next animation
- if (this.active) this.dequeue()
- else this.clearCurrent()
- } else if (!this.paused && this.active) {
- // we continue animating when we are not at the end
- this.startAnimFrame()
- }
-
- // save last eased position for once callback triggering
- this.lastPos = eased
- return this
- },
-
- // calculates the step for every property and calls block with it
- eachAt: function () {
- var i, len, at
- var self = this
- var target = this.target()
- var s = this.situation
-
- // apply animations which can be called trough a method
- for (i in s.animations) {
- at = [].concat(s.animations[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
-
- target[i].apply(target, at)
- }
-
- // apply animation which has to be applied with attr()
- for (i in s.attrs) {
- at = [i].concat(s.attrs[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
-
- target.attr.apply(target, at)
- }
-
- // apply animation which has to be applied with css()
- for (i in s.styles) {
- at = [i].concat(s.styles[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
-
- target.css.apply(target, at)
- }
-
- // animate initialTransformation which has to be chained
- if (s.transforms.length) {
- // get initial initialTransformation
- at = s.initialTransformation
- for (i = 0, len = s.transforms.length; i < len; i++) {
- // get next transformation in chain
- var a = s.transforms[i]
-
- // multiply matrix directly
- if (a instanceof SVG.Matrix) {
- if (a.relative) {
- at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos)))
- } else {
- at = at.morph(a).at(s.ease(this.pos))
- }
- continue
- }
-
- // when transformation is absolute we have to reset the needed transformation first
- if (!a.relative) {
- a.undo(at.extract())
- }
-
- // and reapply it after
- at = at.multiply(a.at(s.ease(this.pos)))
- }
-
- // set new matrix on element
- target.matrix(at)
- }
-
- return this
- },
-
- // adds an once-callback which is called at a specific position and never again
- once: function (pos, fn, isEased) {
- var c = this.last()
- if (!isEased) pos = c.ease(pos)
-
- c.once[pos] = fn
-
- return this
- },
-
- _callStart: function () {
- setTimeout(function () { this.start() }.bind(this), 0)
- return this
- }
-
- },
-
- parent: SVG.Element,
-
- // Add method to parent elements
- construct: {
- // Get fx module or create a new one, then animate with given duration and ease
- animate: function (o, ease, delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay)
- },
- delay: function (delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).delay(delay)
- },
- stop: function (jumpToEnd, clearQueue) {
- if (this.fx) {
- this.fx.stop(jumpToEnd, clearQueue)
- }
-
- return this
- },
- finish: function () {
- if (this.fx) {
- this.fx.finish()
- }
-
- return this
- },
- // Pause current animation
- pause: function () {
- if (this.fx) {
- this.fx.pause()
- }
-
- return this
- },
- // Play paused current animation
- play: function () {
- if (this.fx) { this.fx.play() }
-
- return this
- },
- // Set/Get the speed of the animations
- speed: function (speed) {
- if (this.fx) {
- if (speed == null) { return this.fx.speed() } else { this.fx.speed(speed) }
- }
-
- return this
- }
- }
-
-})
-
-// MorphObj is used whenever no morphable object is given
-SVG.MorphObj = SVG.invent({
-
- create: function (from, to) {
- // prepare color for morphing
- if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
- // prepare value list for morphing
- if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
- // prepare number for morphing
- if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
-
- // prepare for plain morphing
- this.value = from
- this.destination = to
- },
-
- extend: {
- at: function (pos, real) {
- return real < 1 ? this.value : this.destination
- },
-
- valueOf: function () {
- return this.value
- }
- }
-
-})
-
-SVG.extend(SVG.FX, {
- // Add animatable attributes
- attr: function (a, v, relative) {
- // apply attributes individually
- if (typeof a === 'object') {
- for (var key in a) {
- this.attr(key, a[key])
- }
- } else {
- this.add(a, v, 'attrs')
- }
-
- return this
- },
- // Add animatable styles
- css: function (s, v) {
- if (typeof s === 'object') {
- for (var key in s) {
- this.css(key, s[key])
- }
- } else {
- this.add(s, v, 'styles')
- }
-
- return this
- },
- // Animatable x-axis
- x: function (x, relative) {
- if (this.target() instanceof SVG.G) {
- this.transform({x: x}, relative)
- return this
- }
-
- var num = new SVG.Number(x)
- num.relative = relative
- return this.add('x', num)
- },
- // Animatable y-axis
- y: function (y, relative) {
- if (this.target() instanceof SVG.G) {
- this.transform({y: y}, relative)
- return this
- }
-
- var num = new SVG.Number(y)
- num.relative = relative
- return this.add('y', num)
- },
- // Animatable center x-axis
- cx: function (x) {
- return this.add('cx', new SVG.Number(x))
- },
- // Animatable center y-axis
- cy: function (y) {
- return this.add('cy', new SVG.Number(y))
- },
- // Add animatable move
- move: function (x, y) {
- return this.x(x).y(y)
- },
- // Add animatable center
- center: function (x, y) {
- return this.cx(x).cy(y)
- },
- // Add animatable size
- size: function (width, height) {
- if (this.target() instanceof SVG.Text) {
- // animate font size for Text elements
- this.attr('font-size', width)
- } else {
- // animate bbox based size for all other elements
- var box
-
- if (!width || !height) {
- box = this.target().bbox()
- }
-
- if (!width) {
- width = box.width / box.height * height
- }
-
- if (!height) {
- height = box.height / box.width * width
- }
-
- this.add('width', new SVG.Number(width))
- .add('height', new SVG.Number(height))
- }
-
- return this
- },
- // Add animatable width
- width: function (width) {
- return this.add('width', new SVG.Number(width))
- },
- // Add animatable height
- height: function (height) {
- return this.add('height', new SVG.Number(height))
- },
- // Add animatable plot
- plot: function (a, b, c, d) {
- // Lines can be plotted with 4 arguments
- if (arguments.length === 4) {
- return this.plot([a, b, c, d])
- }
-
- return this.add('plot', new (this.target().MorphArray)(a))
- },
- // Add leading method
- leading: function (value) {
- return this.target().leading
- ? this.add('leading', new SVG.Number(value))
- : this
- },
- // Add animatable viewbox
- viewbox: function (x, y, width, height) {
- if (this.target() instanceof SVG.Container) {
- this.add('viewbox', new SVG.Box(x, y, width, height))
- }
-
- return this
- },
- update: function (o) {
- if (this.target() instanceof SVG.Stop) {
- if (typeof o === 'number' || o instanceof SVG.Number) {
- return this.update({
- offset: arguments[0],
- color: arguments[1],
- opacity: arguments[2]
- })
- }
-
- if (o.opacity != null) this.attr('stop-opacity', o.opacity)
- if (o.color != null) this.attr('stop-color', o.color)
- if (o.offset != null) this.attr('offset', o.offset)
- }
-
- return this
- }
-})
+ this.r = parseInt(match[1]); + this.g = parseInt(match[2]); + this.b = parseInt(match[3]); + } else if (SVG.regex.isHex.test(color)) { + // get hex values + match = SVG.regex.hex.exec(fullHex(color)); // parse numeric values -/* global abcdef, arrayToMatrix, deltaTransformPoint, parseMatrix */
-
-SVG.Matrix = SVG.invent({
- // Initialize
- create: function (source) {
- var base = arrayToMatrix([1, 0, 0, 1, 0, 0])
- var i
-
- // ensure source as object
- source = source instanceof SVG.Element ? source.matrixify()
- : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat))
- : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments))
- : Array.isArray(source) ? arrayToMatrix(source)
- : typeof source === 'object' ? source
- : base
-
- // merge source
- for (i = abcdef.length - 1; i >= 0; --i) {
- this[abcdef[i]] = source[abcdef[i]] != null
- ? source[abcdef[i]]
- : base[abcdef[i]]
- }
- },
-
- // Add methods
- extend: {
- // Extract individual transformations
- extract: function () {
- // find delta transform points
- var px = deltaTransformPoint(this, 0, 1)
- var py = deltaTransformPoint(this, 1, 0)
- var skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90
-
- return {
- // translation
- x: this.e,
- y: this.f,
- transformedX: (this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b),
- transformedY: (this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d),
- // skew
- skewX: -skewX,
- skewY: 180 / Math.PI * Math.atan2(py.y, py.x),
- // scale
- scaleX: Math.sqrt(this.a * this.a + this.b * this.b),
- scaleY: Math.sqrt(this.c * this.c + this.d * this.d),
- // rotation
- rotation: skewX,
- a: this.a,
- b: this.b,
- c: this.c,
- d: this.d,
- e: this.e,
- f: this.f,
- matrix: new SVG.Matrix(this)
- }
- },
- // Clone matrix
- clone: function () {
- return new SVG.Matrix(this)
- },
- // Morph one matrix into another
- morph: function (matrix) {
- // store new destination
- this.destination = new SVG.Matrix(matrix)
-
- return this
- },
- // Get morphed matrix at a given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- // calculate morphed matrix at a given position
- var matrix = new SVG.Matrix({
- a: this.a + (this.destination.a - this.a) * pos,
- b: this.b + (this.destination.b - this.b) * pos,
- c: this.c + (this.destination.c - this.c) * pos,
- d: this.d + (this.destination.d - this.d) * pos,
- e: this.e + (this.destination.e - this.e) * pos,
- f: this.f + (this.destination.f - this.f) * pos
- })
-
- return matrix
- },
- // Multiplies by given matrix
- multiply: function (matrix) {
- return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
- },
- // Inverses matrix
- inverse: function () {
- return new SVG.Matrix(this.native().inverse())
- },
- // Translate matrix
- translate: function (x, y) {
- return new SVG.Matrix(this.native().translate(x || 0, y || 0))
- },
- // Scale matrix
- scale: function (x, y, cx, cy) {
- // support uniformal scale
- if (arguments.length === 1) {
- y = x
- } else if (arguments.length === 3) {
- cy = cx
- cx = y
- y = x
- }
-
- return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0))
- },
- // Rotate matrix
- rotate: function (r, cx, cy) {
- // convert degrees to radians
- r = SVG.utils.radians(r)
-
- return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0))
- },
- // Flip matrix on x or y, at a given offset
- flip: function (a, o) {
- return a === 'x' ? this.scale(-1, 1, o, 0)
- : a === 'y' ? this.scale(1, -1, 0, o)
- : this.scale(-1, -1, a, o != null ? o : a)
- },
- // Skew
- skew: function (x, y, cx, cy) {
- // support uniformal skew
- if (arguments.length === 1) {
- y = x
- } else if (arguments.length === 3) {
- cy = cx
- cx = y
- y = x
- }
-
- // convert degrees to radians
- x = SVG.utils.radians(x)
- y = SVG.utils.radians(y)
-
- return this.around(cx, cy, new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0))
- },
- // SkewX
- skewX: function (x, cx, cy) {
- return this.skew(x, 0, cx, cy)
- },
- // SkewY
- skewY: function (y, cx, cy) {
- return this.skew(0, y, cx, cy)
- },
- // Transform around a center point
- around: function (cx, cy, matrix) {
- return this
- .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
- .multiply(matrix)
- .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
- },
- // Convert to native SVGMatrix
- native: function () {
- // create new matrix
- var matrix = SVG.parser.nodes.svg.node.createSVGMatrix()
-
- // update with current values
- for (var i = abcdef.length - 1; i >= 0; i--) {
- matrix[abcdef[i]] = this[abcdef[i]]
- }
-
- return matrix
- },
- // Convert matrix to string
- toString: function () {
- return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
- }
- },
-
- // Define parent
- parent: SVG.Element,
-
- // Add parent method
- construct: {
- // Get current matrix
- ctm: function () {
- return new SVG.Matrix(this.node.getCTM())
- },
- // Get current screen matrix
- screenCTM: function () {
- /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537
- This is needed because FF does not return the transformation matrix
- for the inner coordinate system when getScreenCTM() is called on nested svgs.
- However all other Browsers do that */
- if (this instanceof SVG.Doc && !this.isRoot()) {
- var rect = this.rect(1, 1)
- var m = rect.node.getScreenCTM()
- rect.remove()
- return new SVG.Matrix(m)
- }
- return new SVG.Matrix(this.node.getScreenCTM())
- }
- }
-})
+ this.r = parseInt(match[1], 16); + this.g = parseInt(match[2], 16); + this.b = parseInt(match[3], 16); + } + } else if (Array.isArray(color)) { + this.r = color[0]; + this.g = color[1]; + this.b = color[2]; + } else if (_typeof(color) === 'object') { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } else if (arguments.length === 3) { + this.r = color; + this.g = g; + this.b = b; + } +}; -
-SVG.Point = SVG.invent({
- // Initialize
- create: function (x, y) {
- var base = {x: 0, y: 0}
- var source
-
- // ensure source as object
- source = Array.isArray(x) ? {x: x[0], y: x[1]}
- : typeof x === 'object' ? {x: x.x, y: x.y}
- : x != null ? {x: x, y: (y != null ? y : x)}
- : base // If y has no value, then x is used has its value
-
- // merge source
- this.x = source.x
- this.y = source.y
- },
-
- // Add methods
- extend: {
- // Clone point
- clone: function () {
- return new SVG.Point(this)
- },
- // Morph one point into another
- morph: function (x, y) {
- // store new destination
- this.destination = new SVG.Point(x, y)
-
- return this
- },
- // Get morphed point at a given position
- at: function (pos) {
- // make sure a destination is defined
- if (!this.destination) return this
-
- // calculate morphed matrix at a given position
- var point = new SVG.Point({
- x: this.x + (this.destination.x - this.x) * pos,
- y: this.y + (this.destination.y - this.y) * pos
- })
-
- return point
- },
- // Convert to native SVGPoint
- native: function () {
- // create new point
- var point = SVG.parser.nodes.svg.node.createSVGPoint()
-
- // update with current values
- point.x = this.x
- point.y = this.y
-
- return point
- },
- // transform point with matrix
- transform: function (matrix) {
- return new SVG.Point(this.native().matrixTransform(matrix.native()))
- }
- }
-})
-
-SVG.extend(SVG.Element, {
-
- // Get point
- point: function (x, y) {
- return new SVG.Point(x, y).transform(this.screenCTM().inverse())
- }
-
-})
- -SVG.extend(SVG.Element, {
- // Set svg element attribute
- attr: function (a, v, n) {
- // act as full getter
- if (a == null) {
- // get an object of attributes
- a = {}
- v = this.node.attributes
- for (n = v.length - 1; n >= 0; n--) {
- a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue)
- ? parseFloat(v[n].nodeValue)
- : v[n].nodeValue
- }
- return a
- } else if (typeof a === 'object') {
- // apply every attribute individually if an object is passed
- for (v in a) this.attr(v, a[v])
- } else if (v === null) {
- // remove value
- this.node.removeAttribute(a)
- } else if (v == null) {
- // act as a getter if the first and only argument is not an object
- v = this.node.getAttribute(a)
- return v == null ? SVG.defaults.attrs[a]
- : SVG.regex.isNumber.test(v) ? parseFloat(v)
- : v
- } else {
- // convert image fill and stroke to patterns
- if (a === 'fill' || a === 'stroke') {
- if (SVG.regex.isImage.test(v)) {
- v = this.doc().defs().image(v)
- }
-
- if (v instanceof SVG.Image) {
- v = this.doc().defs().pattern(0, 0, function () {
- this.add(v)
- })
- }
- }
-
- // ensure correct numeric values (also accepts NaN and Infinity)
- if (typeof v === 'number') {
- v = new SVG.Number(v)
- } else if (SVG.Color.isColor(v)) {
- // ensure full hex color
- v = new SVG.Color(v)
- } else if (Array.isArray(v)) {
- // parse array values
- v = new SVG.Array(v)
- }
-
- // if the passed attribute is leading...
- if (a === 'leading') {
- // ... call the leading method instead
- if (this.leading) {
- this.leading(v)
- }
- } else {
- // set given attribute on node
- typeof n === 'string' ? this.node.setAttributeNS(n, a, v.toString())
- : this.node.setAttribute(a, v.toString())
- }
-
- // rebuild if required
- if (this.rebuild && (a === 'font-size' || a === 'x')) {
- this.rebuild(a, v)
- }
- }
-
- return this
- }
-})
+SVG.extend(SVG.Color, { + // Default to hex conversion + toString: function toString() { + return this.toHex(); + }, + toArray: function toArray() { + return [this.r, this.g, this.b]; + }, + fromArray: function fromArray(a) { + return new SVG.Color(a); + }, + // Build hex value + toHex: function toHex() { + return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); + }, + // Build rgb value + toRgb: function toRgb() { + return 'rgb(' + [this.r, this.g, this.b].join() + ')'; + }, + // Calculate true brightness + brightness: function brightness() { + return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; + }, + // Make color morphable + morph: function morph(color) { + this.destination = new SVG.Color(color); + return this; + }, + // Get morphed color at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // normalise pos -/* global ensureCentre, capitalize, arrayToMatrix */
-
-SVG.extend(SVG.Element, {
- // Add transformations
- transform: function (o, relative) {
- // get target in case of the fx module, otherwise reference this
- var target = this
- var matrix, bbox
-
- // act as a getter
- if (typeof o !== 'object') {
- // get current matrix
- matrix = new SVG.Matrix(target).extract()
-
- return typeof o === 'string' ? matrix[o] : matrix
- }
-
- // get current matrix
- matrix = new SVG.Matrix(target)
-
- // ensure relative flag
- relative = !!relative || !!o.relative
-
- // act on matrix
- if (o.a != null) {
- matrix = relative
- ? matrix.multiply(new SVG.Matrix(o))
- : new SVG.Matrix(o)
-
- // act on rotation
- } else if (o.rotation != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // apply transformation
- matrix = relative
- ? matrix.rotate(o.rotation, o.cx, o.cy)
- : matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy)
-
- // act on scale
- } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // ensure scale values on both axes
- o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
- o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1
-
- if (!relative) {
- // absolute; multiply inversed values
- var e = matrix.extract()
- o.scaleX = o.scaleX * 1 / e.scaleX
- o.scaleY = o.scaleY * 1 / e.scaleY
- }
-
- matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy)
-
- // act on skew
- } else if (o.skew != null || o.skewX != null || o.skewY != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // ensure skew values on both axes
- o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0
- o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0
-
- if (!relative) {
- // absolute; reset skew values
- var el = matrix.extract()
- matrix = matrix.multiply(new SVG.Matrix().skew(el.skewX, el.skewY, el.cx, el.cy).inverse())
- }
-
- matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy)
-
- // act on flip
- } else if (o.flip) {
- if (o.flip === 'x' || o.flip === 'y') {
- o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset
- } else {
- if (o.offset == null) {
- bbox = target.bbox()
- o.flip = bbox.cx
- o.offset = bbox.cy
- } else {
- o.flip = o.offset
- }
- }
-
- matrix = new SVG.Matrix().flip(o.flip, o.offset)
-
- // act on translate
- } else if (o.x != null || o.y != null) {
- if (relative) {
- // relative
- matrix = matrix.translate(o.x, o.y)
- } else {
- // absolute
- if (o.x != null) matrix.e = o.x
- if (o.y != null) matrix.f = o.y
- }
- }
-
- return this.attr('transform', matrix)
- }
-})
-
-SVG.extend(SVG.FX, {
- transform: function (o, relative) {
- // get target in case of the fx module, otherwise reference this
- var target = this.target()
- var matrix, bbox
-
- // act as a getter
- if (typeof o !== 'object') {
- // get current matrix
- matrix = new SVG.Matrix(target).extract()
- return typeof o === 'string' ? matrix[o] : matrix
- }
-
- // ensure relative flag
- relative = !!relative || !!o.relative
-
- // act on matrix
- if (o.a != null) {
- matrix = new SVG.Matrix(o)
-
- // act on rotation
- } else if (o.rotation != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // apply transformation
- matrix = new SVG.Rotate(o.rotation, o.cx, o.cy)
-
- // act on scale
- } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // ensure scale values on both axes
- o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
- o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1
-
- matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)
-
- // act on skew
- } else if (o.skewX != null || o.skewY != null) {
- // ensure centre point
- ensureCentre(o, target)
-
- // ensure skew values on both axes
- o.skewX = o.skewX != null ? o.skewX : 0
- o.skewY = o.skewY != null ? o.skewY : 0
-
- matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)
-
- // act on flip
- } else if (o.flip) {
- if (o.flip === 'x' || o.flip === 'y') {
- o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset
- } else {
- if (o.offset == null) {
- bbox = target.bbox()
- o.flip = bbox.cx
- o.offset = bbox.cy
- } else {
- o.flip = o.offset
- }
- }
-
- matrix = new SVG.Matrix().flip(o.flip, o.offset)
-
- // act on translate
- } else if (o.x != null || o.y != null) {
- matrix = new SVG.Translate(o.x, o.y)
- }
-
- if (!matrix) return this
-
- matrix.relative = relative
-
- this.last().transforms.push(matrix)
-
- return this._callStart()
- }
-})
-
-SVG.extend(SVG.Element, {
- // Reset all transformations
- untransform: function () {
- return this.attr('transform', null)
- },
- // merge the whole transformation chain into one matrix and returns it
- matrixify: function () {
- var matrix = (this.attr('transform') || '')
- // split transformations
- .split(SVG.regex.transforms).slice(0, -1).map(function (str) {
- // generate key => value pairs
- var kv = str.trim().split('(')
- return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })]
- })
- // merge every transformation into one matrix
- .reduce(function (matrix, transform) {
- if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
- return matrix[transform[0]].apply(matrix, transform[1])
- }, new SVG.Matrix())
-
- return matrix
- },
- // add an element to another parent without changing the visual representation on the screen
- toParent: function (parent) {
- if (this === parent) return this
- var ctm = this.screenCTM()
- var pCtm = parent.screenCTM().inverse()
-
- this.addTo(parent).untransform().transform(pCtm.multiply(ctm))
-
- return this
- },
- // same as above with parent equals root-svg
- toDoc: function () {
- return this.toParent(this.doc())
- }
-
-})
-
-SVG.Transformation = SVG.invent({
-
- create: function (source, inversed) {
- if (arguments.length > 1 && typeof inversed !== 'boolean') {
- return this.constructor.bind(this)([].slice.call(arguments))
- }
-
- var i, len
- if (Array.isArray(source)) {
- for (i = 0, len = this.arguments.length; i < len; ++i) {
- this[this.arguments[i]] = source[i]
- }
- } else if (typeof source === 'object') {
- for (i = 0, len = this.arguments.length; i < len; ++i) {
- this[this.arguments[i]] = source[this.arguments[i]]
- }
- }
-
- this.inversed = false
-
- if (inversed === true) {
- this.inversed = true
- }
- },
-
- extend: {
-
- arguments: [],
- method: '',
-
- at: function (pos) {
- var params = []
-
- for (var i = 0, len = this.arguments.length; i < len; ++i) {
- params.push(this[this.arguments[i]])
- }
-
- var m = this._undo || new SVG.Matrix()
-
- m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)
-
- return this.inversed ? m.inverse() : m
- },
-
- undo: function (o) {
- for (var i = 0, len = this.arguments.length; i < len; ++i) {
- o[this.arguments[i]] = typeof this[this.arguments[i]] === 'undefined' ? 0 : o[this.arguments[i]]
- }
-
- // The method SVG.Matrix.extract which was used before calling this
- // method to obtain a value for the parameter o doesn't return a cx and
- // a cy so we use the ones that were provided to this object at its creation
- o.cx = this.cx
- o.cy = this.cy
-
- this._undo = new SVG[capitalize(this.method)](o, true).at(1)
- return this
- }
-
- }
-
-})
-
-SVG.Translate = SVG.invent({
-
- parent: SVG.Matrix,
- inherit: SVG.Transformation,
-
- create: function (source, inversed) {
- this.constructor.apply(this, [].slice.call(arguments))
- },
-
- extend: {
- arguments: ['transformedX', 'transformedY'],
- method: 'translate'
- }
-
-})
-
-SVG.Rotate = SVG.invent({
-
- parent: SVG.Matrix,
- inherit: SVG.Transformation,
-
- create: function (source, inversed) {
- this.constructor.apply(this, [].slice.call(arguments))
- },
-
- extend: {
- arguments: ['rotation', 'cx', 'cy'],
- method: 'rotate',
- at: function (pos) {
- var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)
- return this.inversed ? m.inverse() : m
- },
- undo: function (o) {
- this._undo = o
- return this
- }
- }
-
-})
-
-SVG.Scale = SVG.invent({
-
- parent: SVG.Matrix,
- inherit: SVG.Transformation,
-
- create: function (source, inversed) {
- this.constructor.apply(this, [].slice.call(arguments))
- },
-
- extend: {
- arguments: ['scaleX', 'scaleY', 'cx', 'cy'],
- method: 'scale'
- }
-
-})
-
-SVG.Skew = SVG.invent({
-
- parent: SVG.Matrix,
- inherit: SVG.Transformation,
-
- create: function (source, inversed) {
- this.constructor.apply(this, [].slice.call(arguments))
- },
-
- extend: {
- arguments: ['skewX', 'skewY', 'cx', 'cy'],
- method: 'skew'
- }
-})
+ pos = pos < 0 ? 0 : pos > 1 ? 1 : pos; // generate morphed color -/* global camelCase */
-
-SVG.extend(SVG.Element, {
- // Dynamic style generator
- css: function (s, v) {
- var ret = {}
- var t, i
- if (arguments.length === 0) {
- // get full style as object
- this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { return !!el.length }).forEach(function (el) {
- t = el.split(/\s*:\s*/)
- ret[t[0]] = t[1]
- })
- return ret
- }
-
- if (arguments.length < 2) {
- // get style properties in the array
- if (Array.isArray(s)) {
- for (i = s.length; i--;) {
- ret[camelCase(s[i])] = this.node.style[camelCase(s[i])]
- }
- return ret
- }
-
- // get style for property
- if (typeof s === 'string') {
- return this.node.style[camelCase(s)]
- }
-
- // set styles in object
- if (typeof s === 'object') {
- for (i in s) {
- // set empty string if null/undefined/'' was given
- this.node.style[camelCase(i)] = (s[i] == null || SVG.regex.isBlank.test(s[i])) ? '' : s[i]
- }
- }
- }
-
- // set style for property
- if (arguments.length === 2) {
- this.node.style[camelCase(s)] = (v == null || SVG.regex.isBlank.test(v)) ? '' : v
- }
-
- return this
- }
-})
+ return new SVG.Color({ + r: ~~(this.r + (this.destination.r - this.r) * pos), + g: ~~(this.g + (this.destination.g - this.g) * pos), + b: ~~(this.b + (this.destination.b - this.b) * pos) + }); + } +}); // Testers +// Test if given value is a color string -/* global createElement */
-
-SVG.Parent = SVG.invent({
- // Initialize node
- create: function (node) {
- this.constructor(node)
- },
-
- // Inherit from
- inherit: SVG.Element,
-
- // Add class methods
- extend: {
- // Returns all child elements
- children: function () {
- return SVG.utils.map(this.node.children, function (node) {
- return SVG.adopt(node)
- })
- },
- // Add given element at a position
- add: function (element, i) {
- element = createElement(element)
-
- if (element.node !== this.node.children[i]) {
- this.node.insertBefore(element.node, this.node.children[i] || null)
- }
-
- return this
- },
- // Basically does the same as `add()` but returns the added element instead
- put: function (element, i) {
- this.add(element, i)
- return element.instance || element
- },
- // Checks if the given element is a child
- has: function (element) {
- return this.index(element) >= 0
- },
- // Gets index of given element
- index: function (element) {
- return [].slice.call(this.node.children).indexOf(element.node)
- },
- // Get a element at the given index
- get: function (i) {
- return SVG.adopt(this.node.children[i])
- },
- // Get first child
- first: function () {
- return this.get(0)
- },
- // Get the last child
- last: function () {
- return this.get(this.node.children.length - 1)
- },
- // Iterates over all children and invokes a given block
- each: function (block, deep) {
- var children = this.children()
- var i, il
-
- for (i = 0, il = children.length; i < il; i++) {
- if (children[i] instanceof SVG.Element) {
- block.apply(children[i], [i, children])
- }
-
- if (deep && (children[i] instanceof SVG.Parent)) {
- children[i].each(block, deep)
- }
- }
-
- return this
- },
- // Remove a given child
- removeElement: function (element) {
- this.node.removeChild(element.node)
-
- return this
- },
- // Remove all elements in this container
- clear: function () {
- // remove children
- while (this.node.hasChildNodes()) {
- this.node.removeChild(this.node.lastChild)
- }
-
- // remove defs reference
- delete this._defs
-
- return this
- }
- }
-
-})
+SVG.Color.test = function (color) { + color += ''; + return SVG.regex.isHex.test(color) || SVG.regex.isRgb.test(color); +}; // Test if given value is a rgb object -SVG.extend(SVG.Parent, {
- flatten: function (parent) {
- // flattens is only possible for nested svgs and groups
- if (!(this instanceof SVG.G || this instanceof SVG.Doc)) {
- return this
- }
-
- parent = parent || (this instanceof SVG.Doc && this.isRoot() ? this : this.parent(SVG.Parent))
-
- this.each(function () {
- if (this instanceof SVG.Defs) return this
- if (this instanceof SVG.Parent) return this.flatten(parent)
- return this.toParent(parent)
- })
-
- // we need this so that SVG.Doc does not get removed
- this.node.firstElementChild || this.remove()
-
- return this
- },
- ungroup: function (parent) {
- // ungroup is only possible for nested svgs and groups
- if (!(this instanceof SVG.G || (this instanceof SVG.Doc && !this.isRoot()))) {
- return this
- }
-
- parent = parent || this.parent(SVG.Parent)
-
- this.each(function () {
- return this.toParent(parent)
- })
-
- // we need this so that SVG.Doc does not get removed
- this.remove()
-
- return this
- }
-})
-SVG.Container = SVG.invent({
- // Initialize node
- create: function (node) {
- this.constructor(node)
- },
-
- // Inherit from
- inherit: SVG.Parent
-})
+SVG.Color.isRgb = function (color) { + return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; +}; // Test if given value is a color -// Add events to elements
-
+ +SVG.Color.isColor = function (color) { + return SVG.Color.isRgb(color) || SVG.Color.test(color); +}; +/* global arrayClone */ +// Module for array conversion + + +SVG.Array = function (array, fallback) { + array = (array || []).valueOf(); // if array is empty and fallback is provided, use fallback + + if (array.length === 0 && fallback) { + array = fallback.valueOf(); + } // parse array + + + this.value = this.parse(array); +}; + +SVG.extend(SVG.Array, { + // Make array morphable + morph: function morph(array) { + this.destination = this.parse(array); // normalize length of arrays + + if (this.value.length !== this.destination.length) { + var lastValue = this.value[this.value.length - 1]; + var lastDestination = this.destination[this.destination.length - 1]; + + while (this.value.length > this.destination.length) { + this.destination.push(lastDestination); + } + + while (this.value.length < this.destination.length) { + this.value.push(lastValue); + } + } + + return this; + }, + // Clean up any duplicate points + settle: function settle() { + // find all unique values + for (var i = 0, il = this.value.length, seen = []; i < il; i++) { + if (seen.indexOf(this.value[i]) === -1) { + seen.push(this.value[i]); + } + } // set new value + + + this.value = seen; + return seen; + }, + // Get morphed array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // generate morphed array + + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos); + } + + return new SVG.Array(array); + }, + toArray: function toArray() { + return this.value; + }, + // Convert array to string + toString: function toString() { + return this.value.join(' '); + }, + // Real value + valueOf: function valueOf() { + return this.value; + }, + // Parse whitespace separated string + parse: function parse(array) { + array = array.valueOf(); // if already is an array, no need to parse it + + if (Array.isArray(array)) return array; + return array.trim().split(SVG.regex.delimiter).map(parseFloat); + }, + // Reverse array + reverse: function reverse() { + this.value.reverse(); + return this; + }, + clone: function clone() { + var clone = new this.constructor(); + clone.value = arrayClone(this.value); + return clone; + } +}); // Poly points array + +SVG.PointArray = function (array, fallback) { + SVG.Array.call(this, array, fallback || [[0, 0]]); +}; // Inherit from SVG.Array + + +SVG.PointArray.prototype = new SVG.Array(); +SVG.PointArray.prototype.constructor = SVG.PointArray; +SVG.extend(SVG.PointArray, { + // Convert array to string + toString: function toString() { + // convert to a poly point string + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push(this.value[i].join(',')); + } + + return array.join(' '); + }, + toArray: function toArray() { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + }, + // Convert array to line object + toLine: function toLine() { + return { + x1: this.value[0][0], + y1: this.value[0][1], + x2: this.value[1][0], + y2: this.value[1][1] + }; + }, + // Get morphed array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // generate morphed point string + + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push([this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos, this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos]); + } + + return new SVG.PointArray(array); + }, + // Parse point string and flat array + parse: function parse(array) { + var points = []; + array = array.valueOf(); // if it is an array + + if (Array.isArray(array)) { + // and it is not flat, there is no need to parse it + if (Array.isArray(array[0])) { + return array; + } + } else { + // Else, it is considered as a string + // parse points + array = array.trim().split(SVG.regex.delimiter).map(parseFloat); + } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + + + if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats + + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([array[i], array[i + 1]]); + } + + return points; + }, + // Move point string + move: function move(x, y) { + var box = this.bbox(); // get relative offset + + x -= box.x; + y -= box.y; // move every point + + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.value.length - 1; i >= 0; i--) { + this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]; + } + } + + return this; + }, + // Resize poly string + size: function size(width, height) { + var i; + var box = this.bbox(); // recalculate position of all points according to new size + + for (i = this.value.length - 1; i >= 0; i--) { + if (box.width) this.value[i][0] = (this.value[i][0] - box.x) * width / box.width + box.x; + if (box.height) this.value[i][1] = (this.value[i][1] - box.y) * height / box.height + box.y; + } + + return this; + }, + // Get bounding box of points + bbox: function bbox() { + var maxX = -Infinity; + var maxY = -Infinity; + var minX = Infinity; + var minY = Infinity; + this.value.forEach(function (el) { + maxX = Math.max(el[0], maxX); + maxY = Math.max(el[1], maxY); + minX = Math.min(el[0], minX); + minY = Math.min(el[1], minY); + }); + return { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + } +}); +/* globals arrayToString, pathRegReplace */ + +var pathHandlers = { + M: function M(c, p, p0) { + p.x = p0.x = c[0]; + p.y = p0.y = c[1]; + return ['M', p.x, p.y]; + }, + L: function L(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['L', c[0], c[1]]; + }, + H: function H(c, p) { + p.x = c[0]; + return ['H', c[0]]; + }, + V: function V(c, p) { + p.y = c[0]; + return ['V', c[0]]; + }, + C: function C(c, p) { + p.x = c[4]; + p.y = c[5]; + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; + }, + S: function S(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['S', c[0], c[1], c[2], c[3]]; + }, + Q: function Q(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['Q', c[0], c[1], c[2], c[3]]; + }, + T: function T(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['T', c[0], c[1]]; + }, + Z: function Z(c, p, p0) { + p.x = p0.x; + p.y = p0.y; + return ['Z']; + }, + A: function A(c, p) { + p.x = c[5]; + p.y = c[6]; + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; + } +}; +var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); + +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { + c[5] = c[5] + p.x; + c[6] = c[6] + p.y; + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x); + } + } + return pathHandlers[i](c, p, p0); + }; + }(mlhvqtcsaz[i].toUpperCase()); +} // Path points array + + +SVG.PathArray = function (array, fallback) { + SVG.Array.call(this, array, fallback || [['M', 0, 0]]); +}; // Inherit from SVG.Array + + +SVG.PathArray.prototype = new SVG.Array(); +SVG.PathArray.prototype.constructor = SVG.PathArray; +SVG.extend(SVG.PathArray, { + // Convert array to string + toString: function toString() { + return arrayToString(this.value); + }, + toArray: function toArray() { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + }, + // Move path string + move: function move(x, y) { + // get bounding box of current situation + var box = this.bbox(); // get relative offset + + x -= box.x; + y -= box.y; + + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this.value[i][1] += x; + this.value[i][2] += y; + } else if (l === 'H') { + this.value[i][1] += x; + } else if (l === 'V') { + this.value[i][1] += y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this.value[i][1] += x; + this.value[i][2] += y; + this.value[i][3] += x; + this.value[i][4] += y; + + if (l === 'C') { + this.value[i][5] += x; + this.value[i][6] += y; + } + } else if (l === 'A') { + this.value[i][6] += x; + this.value[i][7] += y; + } + } + } + + return this; + }, + // Resize path string + size: function size(width, height) { + // get bounding box of current situation + var box = this.bbox(); + var i, l; // recalculate position of all points according to new size + + for (i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this.value[i][1] = (this.value[i][1] - box.x) * width / box.width + box.x; + this.value[i][2] = (this.value[i][2] - box.y) * height / box.height + box.y; + } else if (l === 'H') { + this.value[i][1] = (this.value[i][1] - box.x) * width / box.width + box.x; + } else if (l === 'V') { + this.value[i][1] = (this.value[i][1] - box.y) * height / box.height + box.y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this.value[i][1] = (this.value[i][1] - box.x) * width / box.width + box.x; + this.value[i][2] = (this.value[i][2] - box.y) * height / box.height + box.y; + this.value[i][3] = (this.value[i][3] - box.x) * width / box.width + box.x; + this.value[i][4] = (this.value[i][4] - box.y) * height / box.height + box.y; + + if (l === 'C') { + this.value[i][5] = (this.value[i][5] - box.x) * width / box.width + box.x; + this.value[i][6] = (this.value[i][6] - box.y) * height / box.height + box.y; + } + } else if (l === 'A') { + // resize radii + this.value[i][1] = this.value[i][1] * width / box.width; + this.value[i][2] = this.value[i][2] * height / box.height; // move position values + + this.value[i][6] = (this.value[i][6] - box.x) * width / box.width + box.x; + this.value[i][7] = (this.value[i][7] - box.y) * height / box.height + box.y; + } + } + + return this; + }, + // Test if the passed path array use the same path data commands as this path array + equalCommands: function equalCommands(pathArray) { + var i, il, equalCommands; + pathArray = new SVG.PathArray(pathArray); + equalCommands = this.value.length === pathArray.value.length; + + for (i = 0, il = this.value.length; equalCommands && i < il; i++) { + equalCommands = this.value[i][0] === pathArray.value[i][0]; + } + + return equalCommands; + }, + // Make path array morphable + morph: function morph(pathArray) { + pathArray = new SVG.PathArray(pathArray); + + if (this.equalCommands(pathArray)) { + this.destination = pathArray; + } else { + this.destination = null; + } + + return this; + }, + // Get morphed path array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; + var sourceArray = this.value; + var destinationArray = this.destination.value; + var array = []; + var pathArray = new SVG.PathArray(); + var i, il, j, jl; // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]]; + + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; + } // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 + + + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0); + array[i][5] = +(array[i][5] !== 0); + } + } // Directly modify the value of a path array, this is done this way for performance + + + pathArray.value = array; + return pathArray; + }, + // Absolutize and parse path to array + parse: function parse(array) { + // if it's already a patharray, no need to parse it + if (array instanceof SVG.PathArray) return array.valueOf(); // prepare for parsing + + var s; + var paramCnt = { + 'M': 2, + 'L': 2, + 'H': 1, + 'V': 1, + 'C': 6, + 'S': 4, + 'Q': 4, + 'T': 2, + 'A': 7, + 'Z': 0 + }; + + if (typeof array === 'string') { + array = array.replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers + .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(SVG.regex.delimiter); // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + + + var result = []; + var p = new SVG.Point(); + var p0 = new SVG.Point(); + var index = 0; + var len = array.length; + + do { + // Test if we have a path letter + if (SVG.regex.isPathLetter.test(array[index])) { + s = array[index]; + ++index; // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L'; + } else if (s === 'm') { + s = 'l'; + } + + result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); + } while (len > index); + + return result; + }, + // Get bounding box of path + bbox: function bbox() { + SVG.parser().path.setAttribute('d', this.toString()); + return SVG.parser.nodes.path.getBBox(); + } +}); // Module for unit convertions + +SVG.Number = SVG.invent({ + // Initialize + create: function create(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults + + this.value = 0; + this.unit = unit || ''; // parse value + + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(SVG.regex.numberAndUnit); + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize + + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit + + + this.unit = unit[5]; + } + } else { + if (value instanceof SVG.Number) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + }, + // Add methods + extend: { + // Stringalize + toString: function toString() { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + }, + toJSON: function toJSON() { + return this.toString(); + }, + // Convert to primitive + toArray: function toArray() { + return [this.value, this.unit]; + }, + valueOf: function valueOf() { + return this.value; + }, + // Add number + plus: function plus(number) { + number = new SVG.Number(number); + return new SVG.Number(this + number, this.unit || number.unit); + }, + // Subtract number + minus: function minus(number) { + number = new SVG.Number(number); + return new SVG.Number(this - number, this.unit || number.unit); + }, + // Multiply number + times: function times(number) { + number = new SVG.Number(number); + return new SVG.Number(this * number, this.unit || number.unit); + }, + // Divide number + divide: function divide(number) { + number = new SVG.Number(number); + return new SVG.Number(this / number, this.unit || number.unit); + }, + // Convert to different unit + to: function to(unit) { + var number = new SVG.Number(this); + + if (typeof unit === 'string') { + number.unit = unit; + } + + return number; + }, + // Make number morphable + morph: function morph(number) { + this.destination = new SVG.Number(number); + + if (number.relative) { + this.destination.value += this.value; + } + + return this; + }, + // Get morphed number at given position + at: function at(pos) { + // Make sure a destination is defined + if (!this.destination) return this; // Generate new morphed number + + return new SVG.Number(this.destination).minus(this).times(pos).plus(this); + } + } +}); // Add events to elements + +/*
;[ 'click',
'dblclick',
'mousedown',
@@ -3141,2131 +1073,4667 @@ SVG.Container = SVG.invent({ return this
}
})
-
-SVG.listenerId = 0
-
-// Add event binder in the SVG namespace
-SVG.on = function (node, events, listener, binding, options) {
- var l = listener.bind(binding || node)
- var n = node instanceof SVG.Element ? node.node : node
-
- // ensure instance object for nodes which are not adopted
- n.instance = n.instance || {events: {}}
-
- var bag = n.instance.events
-
- // add id to listener
- if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++SVG.listenerId }
-
- events.split(SVG.regex.delimiter).forEach(function (event) {
- var ev = event.split('.')[0]
- var ns = event.split('.')[1] || '*'
-
- // ensure valid object
- bag[ev] = bag[ev] || {}
- bag[ev][ns] = bag[ev][ns] || {}
-
- // reference listener
- bag[ev][ns][listener._svgjsListenerId] = l
-
- // add listener
- n.addEventListener(ev, l, options || false)
- })
-}
-
-// Add event unbinder in the SVG namespace
-SVG.off = function (node, events, listener, options) {
- var n = node instanceof SVG.Element ? node.node : node
- if (!n.instance) return
-
- // listener can be a function or a number
- if (typeof listener === 'function') {
- listener = listener._svgjsListenerId
- if (!listener) return
- }
-
- var bag = n.instance.events
-
- ;(events || '').split(SVG.regex.delimiter).forEach(function (event) {
- var ev = event && event.split('.')[0]
- var ns = event && event.split('.')[1]
- var namespace, l
-
- if (listener) {
- // remove listener reference
- if (bag[ev] && bag[ev][ns || '*']) {
- // removeListener
- n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false)
-
- delete bag[ev][ns || '*'][listener]
- }
- } else if (ev && ns) {
- // remove all listeners for a namespaced event
- if (bag[ev] && bag[ev][ns]) {
- for (l in bag[ev][ns]) { SVG.off(n, [ev, ns].join('.'), l) }
-
- delete bag[ev][ns]
- }
- } else if (ns) {
- // remove all listeners for a specific namespace
- for (event in bag) {
- for (namespace in bag[event]) {
- if (ns === namespace) { SVG.off(n, [event, ns].join('.')) }
- }
- }
- } else if (ev) {
- // remove all listeners for the event
- if (bag[ev]) {
- for (namespace in bag[ev]) { SVG.off(n, [ev, namespace].join('.')) }
-
- delete bag[ev]
- }
- } else {
- // remove all listeners on a given node
- for (event in bag) { SVG.off(n, event) }
-
- n.instance.events = {}
- }
- })
-}
-
-SVG.extend(SVG.Element, {
- // Bind given event to listener
- on: function (event, listener, binding, options) {
- SVG.on(this, event, listener, binding, options)
- return this
- },
- // Unbind event from listener
- off: function (event, listener) {
- SVG.off(this.node, event, listener)
- return this
- },
- dispatch: function (event, data) {
- // Dispatch event
- if (event instanceof window.Event) {
- this.node.dispatchEvent(event)
- } else {
- this.node.dispatchEvent(event = new window.CustomEvent(event, {detail: data, cancelable: true}))
- }
- return event
- },
- // Fire given event
- fire: function (event, data) {
- this.dispatch(event, data)
- return this
- }
-})
+*/ -SVG.Defs = SVG.invent({
- // Initialize node
- create: 'defs',
-
- // Inherit from
- inherit: SVG.Container
-})
+SVG.listenerId = 0; // Add event binder in the SVG namespace -SVG.G = SVG.invent({
- // Initialize node
- create: 'g',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Move over x-axis
- x: function (x) {
- return x == null ? this.transform('x') : this.transform({ x: x - this.x() }, true)
- },
- // Move over y-axis
- y: function (y) {
- return y == null ? this.transform('y') : this.transform({ y: y - this.y() }, true)
- },
- // Move by center over x-axis
- cx: function (x) {
- return x == null ? this.gbox().cx : this.x(x - this.gbox().width / 2)
- },
- // Move by center over y-axis
- cy: function (y) {
- return y == null ? this.gbox().cy : this.y(y - this.gbox().height / 2)
- },
- gbox: function () {
- var bbox = this.bbox()
- var trans = this.transform()
-
- bbox.x += trans.x
- bbox.x2 += trans.x
- bbox.cx += trans.x
-
- bbox.y += trans.y
- bbox.y2 += trans.y
- bbox.cy += trans.y
-
- return bbox
- }
- },
-
- // Add parent method
- construct: {
- // Create a group element
- group: function () {
- return this.put(new SVG.G())
- }
- }
-})
+SVG.on = function (node, events, listener, binding, options) { + var l = listener.bind(binding || node); + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node; // events can be an array of events or a string of events -// ### This module adds backward / forward functionality to elements.
-
-//
-SVG.extend(SVG.Element, {
- // Get all siblings, including myself
- siblings: function () {
- return this.parent().children()
- },
-
- // Get the curent position siblings
- position: function () {
- return this.parent().index(this)
- },
-
- // Get the next element (will return null if there is none)
- next: function () {
- return this.siblings()[this.position() + 1]
- },
-
- // Get the next element (will return null if there is none)
- prev: function () {
- return this.siblings()[this.position() - 1]
- },
-
- // Send given element one step forward
- forward: function () {
- var i = this.position() + 1
- var p = this.parent()
-
- // move node one step forward
- p.removeElement(this).add(this, i)
-
- // make sure defs node is always at the top
- if (p instanceof SVG.Doc) {
- p.node.appendChild(p.defs().node)
- }
-
- return this
- },
-
- // Send given element one step backward
- backward: function () {
- var i = this.position()
-
- if (i > 0) {
- this.parent().removeElement(this).add(this, i - 1)
- }
-
- return this
- },
-
- // Send given element all the way to the front
- front: function () {
- var p = this.parent()
-
- // Move node forward
- p.node.appendChild(this.node)
-
- // Make sure defs node is always at the top
- if (p instanceof SVG.Doc) {
- p.node.appendChild(p.defs().node)
- }
-
- return this
- },
-
- // Send given element all the way to the back
- back: function () {
- if (this.position() > 0) {
- this.parent().removeElement(this).add(this, 0)
- }
-
- return this
- },
-
- // Inserts a given element before the targeted element
- before: function (element) {
- element.remove()
-
- var i = this.position()
-
- this.parent().add(element, i)
-
- return this
- },
-
- // Insters a given element after the targeted element
- after: function (element) {
- element.remove()
-
- var i = this.position()
-
- this.parent().add(element, i + 1)
-
- return this
- }
-})
+ events = Array.isArray(events) ? events : events.split(SVG.regex.delimiter); // ensure instance object for nodes which are not adopted -SVG.Mask = SVG.invent({
- // Initialize node
- create: 'mask',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Unmask all masked elements and remove itself
- remove: function () {
- // unmask all targets
- this.targets().forEach(function (el) {
- el.unmask()
- })
-
- // remove mask from parent
- return SVG.Element.prototype.remove.call(this)
- },
-
- targets: function () {
- return SVG.select('svg [mask*="' + this.id() + '"]')
- }
- },
-
- // Add parent method
- construct: {
- // Create masking element
- mask: function () {
- return this.defs().put(new SVG.Mask())
- }
- }
-})
-
-SVG.extend(SVG.Element, {
- // Distribute mask to svg element
- maskWith: function (element) {
- // use given mask or create a new one
- var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)
-
- // apply mask
- return this.attr('mask', 'url("#' + masker.id() + '")')
- },
- // Unmask element
- unmask: function () {
- return this.attr('mask', null)
- },
- masker: function () {
- return this.reference('mask')
- }
-})
+ n.instance = n.instance || { + events: {} // pull event handlers from the element -SVG.ClipPath = SVG.invent({
- // Initialize node
- create: 'clipPath',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Unclip all clipped elements and remove itself
- remove: function () {
- // unclip all targets
- this.targets().forEach(function (el) {
- el.unclip()
- })
-
- // remove clipPath from parent
- return SVG.Element.prototype.remove.call(this)
- },
-
- targets: function () {
- return SVG.select('svg [clip-path*="' + this.id() + '"]')
- }
- },
-
- // Add parent method
- construct: {
- // Create clipping element
- clip: function () {
- return this.defs().put(new SVG.ClipPath())
- }
- }
-})
-
-//
-SVG.extend(SVG.Element, {
- // Distribute clipPath to svg element
- clipWith: function (element) {
- // use given clip or create a new one
- var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)
-
- // apply mask
- return this.attr('clip-path', 'url("#' + clipper.id() + '")')
- },
- // Unclip element
- unclip: function () {
- return this.attr('clip-path', null)
- },
- clipper: function () {
- return this.reference('clip-path')
- }
-
-})
+ }; + var bag = n.instance.events; // add id to listener -SVG.Gradient = SVG.invent({
- // Initialize node
- create: function (type) {
- this.constructor(typeof type === 'object' ? type : SVG.create(type + 'Gradient'))
- },
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Add a color stop
- stop: function (offset, color, opacity) {
- return this.put(new SVG.Stop()).update(offset, color, opacity)
- },
- // Update gradient
- update: function (block) {
- // remove all stops
- this.clear()
-
- // invoke passed block
- if (typeof block === 'function') {
- block.call(this, this)
- }
-
- return this
- },
- // Return the fill id
- url: function () {
- return 'url(#' + this.id() + ')'
- },
- // Alias string convertion to fill
- toString: function () {
- return this.url()
- },
- // custom attr to handle transform
- attr: function (a, b, c) {
- if (a === 'transform') a = 'gradientTransform'
- return SVG.Container.prototype.attr.call(this, a, b, c)
- }
- },
-
- // Add parent method
- construct: {
- // Create gradient element in defs
- gradient: function (type, block) {
- return this.defs().gradient(type, block)
- }
- }
-})
-
-// Add animatable methods to both gradient and fx module
-SVG.extend([SVG.Gradient, SVG.FX], {
- // From position
- from: function (x, y) {
- return (this._target || this).type === 'radialGradient'
- ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) })
- : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })
- },
- // To position
- to: function (x, y) {
- return (this._target || this).type === 'radialGradient'
- ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) })
- : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })
- }
-})
-
-// Base gradient generation
-SVG.extend(SVG.Defs, {
- // define gradient
- gradient: function (type, block) {
- return this.put(new SVG.Gradient(type)).update(block)
- }
-
-})
-
-SVG.Stop = SVG.invent({
- // Initialize node
- create: 'stop',
-
- // Inherit from
- inherit: SVG.Element,
-
- // Add class methods
- extend: {
- // add color stops
- update: function (o) {
- if (typeof o === 'number' || o instanceof SVG.Number) {
- o = {
- offset: arguments[0],
- color: arguments[1],
- opacity: arguments[2]
- }
- }
-
- // set attributes
- if (o.opacity != null) this.attr('stop-opacity', o.opacity)
- if (o.color != null) this.attr('stop-color', o.color)
- if (o.offset != null) this.attr('offset', new SVG.Number(o.offset))
-
- return this
- }
- }
-
-})
+ if (!listener._svgjsListenerId) { + listener._svgjsListenerId = ++SVG.listenerId; + } -SVG.Pattern = SVG.invent({
- // Initialize node
- create: 'pattern',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Return the fill id
- url: function () {
- return 'url(#' + this.id() + ')'
- },
- // Update pattern by rebuilding
- update: function (block) {
- // remove content
- this.clear()
-
- // invoke passed block
- if (typeof block === 'function') {
- block.call(this, this)
- }
-
- return this
- },
- // Alias string convertion to fill
- toString: function () {
- return this.url()
- },
- // custom attr to handle transform
- attr: function (a, b, c) {
- if (a === 'transform') a = 'patternTransform'
- return SVG.Container.prototype.attr.call(this, a, b, c)
- }
-
- },
-
- // Add parent method
- construct: {
- // Create pattern element in defs
- pattern: function (width, height, block) {
- return this.defs().pattern(width, height, block)
- }
- }
-})
-
-SVG.extend(SVG.Defs, {
- // Define gradient
- pattern: function (width, height, block) {
- return this.put(new SVG.Pattern()).update(block).attr({
- x: 0,
- y: 0,
- width: width,
- height: height,
- patternUnits: 'userSpaceOnUse'
- })
- }
-
-})
+ events.forEach(function (event) { + var ev = event.split('.')[0]; + var ns = event.split('.')[1] || '*'; // ensure valid object -SVG.Doc = SVG.invent({
- // Initialize node
- create: function (node) {
- this.constructor(node || SVG.create('svg'))
-
- // set svg element attributes and ensure defs node
- this.namespace()
- },
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- isRoot: function () {
- return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'
- },
- // Check if this is a root svg. If not, call docs from this element
- doc: function () {
- if (this.isRoot()) return this
- return SVG.Element.prototype.doc.call(this)
- },
- // Add namespaces
- namespace: function () {
- if (!this.isRoot()) return this.doc().namespace()
- return this
- .attr({ xmlns: SVG.ns, version: '1.1' })
- .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)
- .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns)
- },
- // Creates and returns defs element
- defs: function () {
- if (!this.isRoot()) return this.doc().defs()
- return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs())
- },
- // custom parent method
- parent: function (type) {
- if (this.isRoot()) {
- return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode
- }
-
- return SVG.Element.prototype.parent.call(this, type)
- },
- // Removes the doc from the DOM
- remove: function () {
- if (!this.isRoot()) {
- return SVG.Element.prototype.remove.call(this)
- }
-
- if (this.parent()) {
- this.parent().removeChild(this.node)
- }
-
- return this
- },
- clear: function () {
- // remove children
- while (this.node.hasChildNodes()) {
- this.node.removeChild(this.node.lastChild)
- }
- return this
- }
- },
- construct: {
- // Create nested svg document
- nested: function () {
- return this.put(new SVG.Doc())
- }
- }
-})
+ bag[ev] = bag[ev] || {}; + bag[ev][ns] = bag[ev][ns] || {}; // reference listener -
-SVG.Shape = SVG.invent({
- // Initialize node
- create: function (node) {
- this.constructor(node)
- },
-
- // Inherit from
- inherit: SVG.Element
-})
+ bag[ev][ns][listener._svgjsListenerId] = l; // add listener -
-SVG.Bare = SVG.invent({
- // Initialize
- create: function (element, inherit) {
- // construct element
- this.constructor(SVG.create(element))
-
- // inherit custom methods
- if (inherit) {
- for (var method in inherit.prototype) {
- if (typeof inherit.prototype[method] === 'function') {
- this[method] = inherit.prototype[method]
- }
- }
- }
- },
-
- // Inherit from
- inherit: SVG.Element,
-
- // Add methods
- extend: {
- // Insert some plain text
- words: function (text) {
- // remove contents
- while (this.node.hasChildNodes()) {
- this.node.removeChild(this.node.lastChild)
- }
-
- // create text node
- this.node.appendChild(document.createTextNode(text))
-
- return this
- }
- }
-})
-
-SVG.extend(SVG.Parent, {
- // Create an element that is not described by SVG.js
- element: function (element, inherit) {
- return this.put(new SVG.Bare(element, inherit))
- }
-})
+ n.addEventListener(ev, l, options || false); + }); +}; // Add event unbinder in the SVG namespace -
-SVG.Symbol = SVG.invent({
- // Initialize node
- create: 'symbol',
-
- // Inherit from
- inherit: SVG.Container,
-
- construct: {
- // create symbol
- symbol: function () {
- return this.put(new SVG.Symbol())
- }
- }
-})
-
-SVG.Use = SVG.invent({
- // Initialize node
- create: 'use',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add class methods
- extend: {
- // Use element as a reference
- element: function (element, file) {
- // Set lined element
- return this.attr('href', (file || '') + '#' + element, SVG.xlink)
- }
- },
-
- // Add parent method
- construct: {
- // Create a use element
- use: function (element, file) {
- return this.put(new SVG.Use()).element(element, file)
- }
- }
-})
+SVG.off = function (node, events, listener, options) { + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node; + if (!n.instance) return; // listener can be a function or a number -
-SVG.Rect = SVG.invent({
- // Initialize node
- create: 'rect',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add parent method
- construct: {
- // Create a rect element
- rect: function (width, height) {
- return this.put(new SVG.Rect()).size(width, height)
- }
- }
-})
+ if (typeof listener === 'function') { + listener = listener._svgjsListenerId; + if (!listener) return; + } // pull event handlers from the element -/* global proportionalSize */
-
-SVG.Circle = SVG.invent({
- // Initialize node
- create: 'circle',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add parent method
- construct: {
- // Create circle element, based on ellipse
- circle: function (size) {
- return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0)
- }
- }
-})
-
-SVG.extend([SVG.Circle, SVG.FX], {
- // Radius x value
- rx: function (rx) {
- return this.attr('r', rx)
- },
- // Alias radius x value
- ry: function (ry) {
- return this.rx(ry)
- }
-})
-
-SVG.Ellipse = SVG.invent({
- // Initialize node
- create: 'ellipse',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add parent method
- construct: {
- // Create an ellipse
- ellipse: function (width, height) {
- return this.put(new SVG.Ellipse()).size(width, height).move(0, 0)
- }
- }
-})
-
-SVG.extend([SVG.Ellipse, SVG.Rect, SVG.FX], {
- // Radius x value
- rx: function (rx) {
- return this.attr('rx', rx)
- },
- // Radius y value
- ry: function (ry) {
- return this.attr('ry', ry)
- }
-})
-
-// Add common method
-SVG.extend([SVG.Circle, SVG.Ellipse], {
- // Move over x-axis
- x: function (x) {
- return x == null ? this.cx() - this.rx() : this.cx(x + this.rx())
- },
- // Move over y-axis
- y: function (y) {
- return y == null ? this.cy() - this.ry() : this.cy(y + this.ry())
- },
- // Move by center over x-axis
- cx: function (x) {
- return x == null ? this.attr('cx') : this.attr('cx', x)
- },
- // Move by center over y-axis
- cy: function (y) {
- return y == null ? this.attr('cy') : this.attr('cy', y)
- },
- // Set width of element
- width: function (width) {
- return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2))
- },
- // Set height of element
- height: function (height) {
- return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2))
- },
- // Custom size function
- size: function (width, height) {
- var p = proportionalSize(this, width, height)
-
- return this
- .rx(new SVG.Number(p.width).divide(2))
- .ry(new SVG.Number(p.height).divide(2))
- }
-})
-/* global proportionalSize */
-
-SVG.Line = SVG.invent({
- // Initialize node
- create: 'line',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add class methods
- extend: {
- // Get array
- array: function () {
- return new SVG.PointArray([
- [ this.attr('x1'), this.attr('y1') ],
- [ this.attr('x2'), this.attr('y2') ]
- ])
- },
- // Overwrite native plot() method
- plot: function (x1, y1, x2, y2) {
- if (x1 == null) {
- return this.array()
- } else if (typeof y1 !== 'undefined') {
- x1 = { x1: x1, y1: y1, x2: x2, y2: y2 }
- } else {
- x1 = new SVG.PointArray(x1).toLine()
- }
-
- return this.attr(x1)
- },
- // Move by left top corner
- move: function (x, y) {
- return this.attr(this.array().move(x, y).toLine())
- },
- // Set element size to given width and height
- size: function (width, height) {
- var p = proportionalSize(this, width, height)
- return this.attr(this.array().size(p.width, p.height).toLine())
- }
- },
-
- // Add parent method
- construct: {
- // Create a line element
- line: function (x1, y1, x2, y2) {
- // make sure plot is called as a setter
- // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray
- return SVG.Line.prototype.plot.apply(
- this.put(new SVG.Line())
- , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]
- )
- }
- }
-})
+ var bag = n.instance.events; // events can be an array of events or a string or undefined -/* global proportionalSize */
-
-SVG.Polyline = SVG.invent({
- // Initialize node
- create: 'polyline',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add parent method
- construct: {
- // Create a wrapped polyline element
- polyline: function (p) {
- // make sure plot is called as a setter
- return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray())
- }
- }
-})
-
-SVG.Polygon = SVG.invent({
- // Initialize node
- create: 'polygon',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add parent method
- construct: {
- // Create a wrapped polygon element
- polygon: function (p) {
- // make sure plot is called as a setter
- return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray())
- }
- }
-})
-
-// Add polygon-specific functions
-SVG.extend([SVG.Polyline, SVG.Polygon], {
- // Get array
- array: function () {
- return this._array || (this._array = new SVG.PointArray(this.attr('points')))
- },
-
- // Plot new path
- plot: function (p) {
- return (p == null) ? this.array()
- : this.clear().attr('points', typeof p === 'string' ? p
- : (this._array = new SVG.PointArray(p)))
- },
-
- // Clear array cache
- clear: function () {
- delete this._array
- return this
- },
-
- // Move by left top corner
- move: function (x, y) {
- return this.attr('points', this.array().move(x, y))
- },
-
- // Set element size to given width and height
- size: function (width, height) {
- var p = proportionalSize(this, width, height)
- return this.attr('points', this.array().size(p.width, p.height))
- }
-})
- -// unify all point to point elements
-SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon], {
- // Define morphable array
- MorphArray: SVG.PointArray,
- // Move by left top corner over x-axis
- x: function (x) {
- return x == null ? this.bbox().x : this.move(x, this.bbox().y)
- },
- // Move by left top corner over y-axis
- y: function (y) {
- return y == null ? this.bbox().y : this.move(this.bbox().x, y)
- },
- // Set width of element
- width: function (width) {
- var b = this.bbox()
-
- return width == null ? b.width : this.size(width, b.height)
- },
- // Set height of element
- height: function (height) {
- var b = this.bbox()
-
- return height == null ? b.height : this.size(b.width, height)
- }
-})
+ events = Array.isArray(events) ? events : (events || '').split(SVG.regex.delimiter); + events.forEach(function (event) { + var ev = event && event.split('.')[0]; + var ns = event && event.split('.')[1]; + var namespace, l; -/* global proportionalSize */
-
-SVG.Path = SVG.invent({
- // Initialize node
- create: 'path',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add class methods
- extend: {
- // Define morphable array
- MorphArray: SVG.PathArray,
- // Get array
- array: function () {
- return this._array || (this._array = new SVG.PathArray(this.attr('d')))
- },
- // Plot new path
- plot: function (d) {
- return (d == null) ? this.array()
- : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new SVG.PathArray(d)))
- },
- // Clear array cache
- clear: function () {
- delete this._array
- return this
- },
- // Move by left top corner
- move: function (x, y) {
- return this.attr('d', this.array().move(x, y))
- },
- // Move by left top corner over x-axis
- x: function (x) {
- return x == null ? this.bbox().x : this.move(x, this.bbox().y)
- },
- // Move by left top corner over y-axis
- y: function (y) {
- return y == null ? this.bbox().y : this.move(this.bbox().x, y)
- },
- // Set element size to given width and height
- size: function (width, height) {
- var p = proportionalSize(this, width, height)
- return this.attr('d', this.array().size(p.width, p.height))
- },
- // Set width of element
- width: function (width) {
- return width == null ? this.bbox().width : this.size(width, this.bbox().height)
- },
- // Set height of element
- height: function (height) {
- return height == null ? this.bbox().height : this.size(this.bbox().width, height)
- }
- },
-
- // Add parent method
- construct: {
- // Create a wrapped path element
- path: function (d) {
- // make sure plot is called as a setter
- return this.put(new SVG.Path()).plot(d || new SVG.PathArray())
- }
- }
-})
+ if (listener) { + // remove listener reference + if (bag[ev] && bag[ev][ns || '*']) { + // removeListener + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false); + delete bag[ev][ns || '*'][listener]; + } + } else if (ev && ns) { + // remove all listeners for a namespaced event + if (bag[ev] && bag[ev][ns]) { + for (l in bag[ev][ns]) { + SVG.off(n, [ev, ns].join('.'), l); + } -SVG.Image = SVG.invent({
- // Initialize node
- create: 'image',
-
- // Inherit from
- inherit: SVG.Shape,
-
- // Add class methods
- extend: {
- // (re)load image
- load: function (url, callback) {
- if (!url) return this
-
- var img = new window.Image()
-
- SVG.on(img, 'load', function (e) {
- var p = this.parent(SVG.Pattern)
-
- // ensure image size
- if (this.width() === 0 && this.height() === 0) {
- this.size(img.width, img.height)
- }
-
- if (p instanceof SVG.Pattern) {
- // ensure pattern size if not set
- if (p.width() === 0 && p.height() === 0) {
- p.size(this.width(), this.height())
- }
- }
-
- if (typeof callback === 'function') {
- callback.call(this, {
- width: img.width,
- height: img.height,
- ratio: img.width / img.height,
- url: url
- })
- }
- }, this)
-
- SVG.on(img, 'load error', function () {
- // dont forget to unbind memory leaking events
- SVG.off(img)
- })
-
- return this.attr('href', (img.src = url), SVG.xlink)
- }
- },
-
- // Add parent method
- construct: {
- // create image element, load image and set its size
- image: function (source, callback) {
- return this.put(new SVG.Image()).size(0, 0).load(source, callback)
- }
- }
-})
- -SVG.Text = SVG.invent({
- // Initialize node
- create: function (node) {
- this.constructor(node || SVG.create('text'))
- this.dom.leading = new SVG.Number(1.3) // store leading value for rebuilding
- this._rebuild = true // enable automatic updating of dy values
- this._build = false // disable build mode for adding multiple lines
-
- // set default font
- this.attr('font-family', SVG.defaults.attrs['font-family'])
- },
-
- // Inherit from
- inherit: SVG.Parent,
-
- // Add class methods
- extend: {
- // Move over x-axis
- x: function (x) {
- // act as getter
- if (x == null) {
- return this.attr('x')
- }
-
- return this.attr('x', x)
- },
- // Move over y-axis
- y: function (y) {
- var oy = this.attr('y')
- var o = typeof oy === 'number' ? oy - this.bbox().y : 0
-
- // act as getter
- if (y == null) {
- return typeof oy === 'number' ? oy - o : oy
- }
-
- return this.attr('y', typeof y === 'number' ? y + o : y)
- },
- // Move center over x-axis
- cx: function (x) {
- return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
- },
- // Move center over y-axis
- cy: function (y) {
- return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)
- },
- // Set the text content
- text: function (text) {
- // act as getter
- if (text === undefined) {
- var children = this.node.childNodes
- var firstLine = 0
- text = ''
-
- for (var i = 0, len = children.length; i < len; ++i) {
- // skip textPaths - they are no lines
- if (children[i].nodeName === 'textPath') {
- if (i === 0) firstLine = 1
- continue
- }
-
- // add newline if its not the first child and newLined is set to true
- if (i !== firstLine && children[i].nodeType !== 3 && SVG.adopt(children[i]).dom.newLined === true) {
- text += '\n'
- }
-
- // add content of this node
- text += children[i].textContent
- }
-
- return text
- }
-
- // remove existing content
- this.clear().build(true)
-
- if (typeof text === 'function') {
- // call block
- text.call(this, this)
- } else {
- // store text and make sure text is not blank
- text = text.split('\n')
-
- // build new lines
- for (var j = 0, jl = text.length; j < jl; j++) {
- this.tspan(text[j]).newLine()
- }
- }
-
- // disable build mode and rebuild lines
- return this.build(false).rebuild()
- },
- // Set / get leading
- leading: function (value) {
- // act as getter
- if (value == null) {
- return this.dom.leading
- }
-
- // act as setter
- this.dom.leading = new SVG.Number(value)
-
- return this.rebuild()
- },
- // Rebuild appearance type
- rebuild: function (rebuild) {
- // store new rebuild flag if given
- if (typeof rebuild === 'boolean') {
- this._rebuild = rebuild
- }
-
- // define position of all lines
- if (this._rebuild) {
- var self = this
- var blankLineOffset = 0
- var dy = this.dom.leading * new SVG.Number(this.attr('font-size'))
-
- this.each(function () {
- if (this.dom.newLined) {
- this.attr('x', self.attr('x'))
-
- if (this.text() === '\n') {
- blankLineOffset += dy
- } else {
- this.attr('dy', dy + blankLineOffset)
- blankLineOffset = 0
- }
- }
- })
-
- this.fire('rebuild')
- }
-
- return this
- },
- // Enable / disable build mode
- build: function (build) {
- this._build = !!build
- return this
- },
- // overwrite method from parent to set data properly
- setData: function (o) {
- this.dom = o
- this.dom.leading = new SVG.Number(o.leading || 1.3)
- return this
- }
- },
-
- // Add parent method
- construct: {
- // Create text element
- text: function (text) {
- return this.put(new SVG.Text()).text(text)
- },
- // Create plain text element
- plain: function (text) {
- return this.put(new SVG.Text()).plain(text)
- }
- }
-
-})
-
-SVG.Tspan = SVG.invent({
- // Initialize node
- create: 'tspan',
-
- // Inherit from
- inherit: SVG.Parent,
-
- // Add class methods
- extend: {
- // Set text content
- text: function (text) {
- if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '')
-
- typeof text === 'function' ? text.call(this, this) : this.plain(text)
-
- return this
- },
- // Shortcut dx
- dx: function (dx) {
- return this.attr('dx', dx)
- },
- // Shortcut dy
- dy: function (dy) {
- return this.attr('dy', dy)
- },
- // Create new line
- newLine: function () {
- // fetch text parent
- var t = this.parent(SVG.Text)
-
- // mark new line
- this.dom.newLined = true
-
- // apply new position
- return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x())
- }
- }
-})
-
-SVG.extend([SVG.Text, SVG.Tspan], {
- // Create plain text node
- plain: function (text) {
- // clear if build mode is disabled
- if (this._build === false) {
- this.clear()
- }
-
- // create text node
- this.node.appendChild(document.createTextNode(text))
-
- return this
- },
- // Create a tspan
- tspan: function (text) {
- var tspan = new SVG.Tspan()
-
- // clear if build mode is disabled
- if (!this._build) {
- this.clear()
- }
-
- // add new tspan
- this.node.appendChild(tspan.node)
-
- return tspan.text(text)
- },
- // FIXME: Does this also work for textpath?
- // Get length of text element
- length: function () {
- return this.node.getComputedTextLength()
- }
-})
+ delete bag[ev][ns]; + } + } else if (ns) { + // remove all listeners for a specific namespace + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { + SVG.off(n, [event, ns].join('.')); + } + } + } + } else if (ev) { + // remove all listeners for the event + if (bag[ev]) { + for (namespace in bag[ev]) { + SVG.off(n, [ev, namespace].join('.')); + } -SVG.TextPath = SVG.invent({
- // Initialize node
- create: 'textPath',
-
- // Inherit from
- inherit: SVG.Text,
-
- // Define parent class
- parent: SVG.Parent,
-
- // Add parent method
- extend: {
- MorphArray: SVG.PathArray,
- // return the array of the path track element
- array: function () {
- var track = this.track()
-
- return track ? track.array() : null
- },
- // Plot path if any
- plot: function (d) {
- var track = this.track()
- var pathArray = null
-
- if (track) {
- pathArray = track.plot(d)
- }
-
- return (d == null) ? pathArray : this
- },
- // Get the path element
- track: function () {
- return this.reference('href')
- }
- },
- construct: {
- textPath: function (text, path) {
- return this.defs().path(path).text(text).addTo(this)
- }
- }
-})
-
-SVG.extend([SVG.Text], {
- // Create path for text to run on
- path: function (track) {
- var path = new SVG.TextPath()
-
- // if d is a path, reuse it
- if (!(track instanceof SVG.Path)) {
- // create path element
- track = this.doc().defs().path(track)
- }
-
- // link textPath to path and add content
- path.attr('href', '#' + track, SVG.xlink)
-
- // add textPath element as child node and return textPath
- return this.put(path)
- },
- // Todo: make this plural?
- // Get the textPath children
- textPath: function () {
- return this.select('textPath')
- }
-})
-
-SVG.extend([SVG.Path], {
- // creates a textPath from this path
- text: function (text) {
- if (text instanceof SVG.Text) {
- var txt = text.text()
- return text.clear().path(this).text(txt)
- }
- return this.parent().put(new SVG.Text()).path(this).text(text)
- }
- // TODO: Maybe add `targets` to get all textPaths associated with this path
-})
+ delete bag[ev]; + } + } else { + // remove all listeners on a given node + for (event in bag) { + SVG.off(n, event); + } -SVG.A = SVG.invent({
- // Initialize node
- create: 'a',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Link url
- to: function (url) {
- return this.attr('href', url, SVG.xlink)
- },
- // Link target attribute
- target: function (target) {
- return this.attr('target', target)
- }
- },
-
- // Add parent method
- construct: {
- // Create a hyperlink element
- link: function (url) {
- return this.put(new SVG.A()).to(url)
- }
- }
-})
-
-SVG.extend(SVG.Element, {
- // Create a hyperlink element
- linkTo: function (url) {
- var link = new SVG.A()
-
- if (typeof url === 'function') { url.call(link, link) } else {
- link.to(url)
- }
-
- return this.parent().put(link).put(this)
- }
-
-})
+ n.instance.events = {}; + } + }); +}; -SVG.Marker = SVG.invent({
- // Initialize node
- create: 'marker',
-
- // Inherit from
- inherit: SVG.Container,
-
- // Add class methods
- extend: {
- // Set width of element
- width: function (width) {
- return this.attr('markerWidth', width)
- },
- // Set height of element
- height: function (height) {
- return this.attr('markerHeight', height)
- },
- // Set marker refX and refY
- ref: function (x, y) {
- return this.attr('refX', x).attr('refY', y)
- },
- // Update marker
- update: function (block) {
- // remove all content
- this.clear()
-
- // invoke passed block
- if (typeof block === 'function') { block.call(this, this) }
-
- return this
- },
- // Return the fill id
- toString: function () {
- return 'url(#' + this.id() + ')'
- }
- },
-
- // Add parent method
- construct: {
- marker: function (width, height, block) {
- // Create marker element in defs
- return this.defs().marker(width, height, block)
- }
- }
-
-})
-
-SVG.extend(SVG.Defs, {
- // Create marker
- marker: function (width, height, block) {
- // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto
- return this.put(new SVG.Marker())
- .size(width, height)
- .ref(width / 2, height / 2)
- .viewbox(0, 0, width, height)
- .attr('orient', 'auto')
- .update(block)
- }
-
-})
-
-SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], {
- // Create and attach markers
- marker: function (marker, width, height, block) {
- var attr = ['marker']
-
- // Build attribute name
- if (marker !== 'all') attr.push(marker)
- attr = attr.join('-')
-
- // Set marker attribute
- marker = arguments[1] instanceof SVG.Marker
- ? arguments[1]
- : this.doc().marker(width, height, block)
-
- return this.attr(attr, marker)
- }
-})
- -// Define list of available attributes for stroke and fill
-var sugar = {
- stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
- fill: ['color', 'opacity', 'rule'],
- prefix: function (t, a) {
- return a === 'color' ? t : t + '-' + a
- }
-}
-
-// Add sugar for fill and stroke
-;['fill', 'stroke'].forEach(function (m) {
- var extension = {}
- var i
-
- extension[m] = function (o) {
- if (typeof o === 'undefined') {
- return this
- }
- if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {
- this.attr(m, o)
- } else {
- // set all attributes from sugar.fill and sugar.stroke list
- for (i = sugar[m].length - 1; i >= 0; i--) {
- if (o[sugar[m][i]] != null) {
- this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
- }
- }
- }
-
- return this
- }
-
- SVG.extend([SVG.Element, SVG.FX], extension)
-})
-
-SVG.extend([SVG.Element, SVG.FX], {
- // Map rotation to transform
- rotate: function (d, cx, cy) {
- return this.transform({ rotation: d, cx: cx, cy: cy })
- },
- // Map skew to transform
- skew: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({ skew: x, cx: y, cy: cx })
- : this.transform({ skewX: x, skewY: y, cx: cx, cy: cy })
- },
- // Map scale to transform
- scale: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({ scale: x, cx: y, cy: cx })
- : this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy })
- },
- // Map translate to transform
- translate: function (x, y) {
- return this.transform({ x: x, y: y })
- },
- // Map flip to transform
- flip: function (a, o) {
- o = typeof a === 'number' ? a : o
- return this.transform({ flip: a || 'both', offset: o })
- },
- // Map matrix to transform
- matrix: function (m) {
- return this.attr('transform', new SVG.Matrix(arguments.length === 6 ? [].slice.call(arguments) : m))
- },
- // Opacity
- opacity: function (value) {
- return this.attr('opacity', value)
- },
- // Relative move over x axis
- dx: function (x) {
- return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true)
- },
- // Relative move over y axis
- dy: function (y) {
- return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true)
- },
- // Relative move over x and y axes
- dmove: function (x, y) {
- return this.dx(x).dy(y)
- }
-})
-
-SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX], {
- // Add x and y radius
- radius: function (x, y) {
- var type = (this._target || this).type
- return type === 'radialGradient' || type === 'radialGradient'
- ? this.attr('r', new SVG.Number(x))
- : this.rx(x).ry(y == null ? x : y)
- }
-})
-
-SVG.extend(SVG.Path, {
- // Get path length
- length: function () {
- return this.node.getTotalLength()
- },
- // Get point at length
- pointAt: function (length) {
- return new SVG.Point(this.node.getPointAtLength(length))
- }
-})
-
-SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX], {
- // Set font
- font: function (a, v) {
- if (typeof a === 'object') {
- for (v in a) this.font(v, a[v])
- }
-
- return a === 'leading'
- ? this.leading(v)
- : a === 'anchor'
- ? this.attr('text-anchor', v)
- : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'
- ? this.attr('font-' + a, v)
- : this.attr(a, v)
- }
-})
+SVG.dispatch = function (node, event, data) { + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node; // Dispatch event -
-SVG.extend(SVG.Element, {
- // Store data values on svg nodes
- data: function (a, v, r) {
- if (typeof a === 'object') {
- for (v in a) {
- this.data(v, a[v])
- }
- } else if (arguments.length < 2) {
- try {
- return JSON.parse(this.attr('data-' + a))
- } catch (e) {
- return this.attr('data-' + a)
- }
- } else {
- this.attr('data-' + a,
- v === null ? null
- : r === true || typeof v === 'string' || typeof v === 'number' ? v
- : JSON.stringify(v)
- )
- }
-
- return this
- }
-})
+ if (event instanceof window.Event) { + n.dispatchEvent(event); + } else { + event = new window.CustomEvent(event, { + detail: data, + cancelable: true + }); + n.dispatchEvent(event); + } -
-SVG.extend(SVG.Element, {
- // Remember arbitrary data
- remember: function (k, v) {
- // remember every item in an object individually
- if (typeof arguments[0] === 'object') {
- for (var key in k) {
- this.remember(key, k[key])
- }
- } else if (arguments.length === 1) {
- // retrieve memory
- return this.memory()[k]
- } else {
- // store memory
- this.memory()[k] = v
- }
-
- return this
- },
-
- // Erase a given memory
- forget: function () {
- if (arguments.length === 0) {
- this._memory = {}
- } else {
- for (var i = arguments.length - 1; i >= 0; i--) {
- delete this.memory()[arguments[i]]
- }
- }
- return this
- },
-
- // Initialize or return local memory object
- memory: function () {
- return this._memory || (this._memory = {})
- }
-})
+ return event; +}; -/* global idFromReference */
-
-// Method for getting an element by id
-SVG.get = function (id) {
- var node = document.getElementById(idFromReference(id) || id)
- return SVG.adopt(node)
-}
-
-// Select elements by query string
-SVG.select = function (query, parent) {
- return SVG.utils.map((parent || document).querySelectorAll(query), function (node) {
- return SVG.adopt(node)
- })
-}
-
-SVG.$$ = function (query, parent) {
- return SVG.utils.map((parent || document).querySelectorAll(query), function (node) {
- return SVG.adopt(node)
- })
-}
-
-SVG.$ = function (query, parent) {
- return SVG.adopt((parent || document).querySelector(query))
-}
-
-SVG.extend(SVG.Parent, {
- // Scoped select method
- select: function (query) {
- return SVG.select(query, this.node)
- }
-})
+SVG.EventTarget = SVG.invent({ + create: function create() {}, + extend: { + // Bind given event to listener + on: function on(event, listener, binding, options) { + SVG.on(this, event, listener, binding, options); + return this; + }, + // Unbind event from listener + off: function off(event, listener) { + SVG.off(this, event, listener); + return this; + }, + dispatch: function dispatch(event, data) { + return SVG.dispatch(this, event, data); + }, + // Fire given event + fire: function fire(event, data) { + this.dispatch(event, data); + return this; + } + } +}); +/* global createElement */ -/* eslint no-unused-vars: 0 */
-
-function createElement (element, makeNested) {
- if (element instanceof SVG.Element) return element
-
- if (typeof element === 'object') {
- return SVG.adopt(element)
- }
-
- if (element == null) {
- return new SVG.Doc()
- }
-
- if (typeof element === 'string' && element.charAt(0) !== '<') {
- return SVG.adopt(document.querySelector(element))
- }
-
- var node = SVG.create('svg')
- node.innerHTML = element
-
- element = SVG.adopt(node.firstElementChild)
-
- return element
-}
-
-function isNulledBox (box) {
- return !box.w && !box.h && !box.x && !box.y
-}
-
-function domContains (node) {
- return (document.documentElement.contains || function (node) {
- // This is IE - it does not support contains() for top-level SVGs
- while (node.parentNode) {
- node = node.parentNode
- }
- return node === document
- }).call(document.documentElement, node)
-}
-
-function pathRegReplace (a, b, c, d) {
- return c + d.replace(SVG.regex.dots, ' .')
-}
-
-// creates deep clone of array
-function arrayClone (arr) {
- var clone = arr.slice(0)
- for (var i = clone.length; i--;) {
- if (Array.isArray(clone[i])) {
- clone[i] = arrayClone(clone[i])
- }
- }
- return clone
-}
-
-// tests if a given element is instance of an object
-function is (el, obj) {
- return el instanceof obj
-}
-
-// tests if a given selector matches an element
-function matches (el, selector) {
- return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector)
-}
-
-// Convert dash-separated-string to camelCase
-function camelCase (s) {
- return s.toLowerCase().replace(/-(.)/g, function (m, g) {
- return g.toUpperCase()
- })
-}
-
-// Capitalize first letter of a string
-function capitalize (s) {
- return s.charAt(0).toUpperCase() + s.slice(1)
-}
-
-// Ensure to six-based hex
-function fullHex (hex) {
- return hex.length === 4
- ? [ '#',
- hex.substring(1, 2), hex.substring(1, 2),
- hex.substring(2, 3), hex.substring(2, 3),
- hex.substring(3, 4), hex.substring(3, 4)
- ].join('')
- : hex
-}
-
-// Component to hex value
-function compToHex (comp) {
- var hex = comp.toString(16)
- return hex.length === 1 ? '0' + hex : hex
-}
-
-// Calculate proportional width and height values when necessary
-function proportionalSize (element, width, height) {
- if (width == null || height == null) {
- var box = element.bbox()
-
- if (width == null) {
- width = box.width / box.height * height
- } else if (height == null) {
- height = box.height / box.width * width
- }
- }
-
- return {
- width: width,
- height: height
- }
-}
-
-// Delta transform point
-function deltaTransformPoint (matrix, x, y) {
- return {
- x: x * matrix.a + y * matrix.c + 0,
- y: x * matrix.b + y * matrix.d + 0
- }
-}
-
-// Map matrix array to object
-function arrayToMatrix (a) {
- return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }
-}
-
-// Parse matrix if required
-function parseMatrix (matrix) {
- if (!(matrix instanceof SVG.Matrix)) {
- matrix = new SVG.Matrix(matrix)
- }
-
- return matrix
-}
-
-// Add centre point to transform object
-function ensureCentre (o, target) {
- o.cx = o.cx == null ? target.bbox().cx : o.cx
- o.cy = o.cy == null ? target.bbox().cy : o.cy
-}
-
-// PathArray Helpers
-function arrayToString (a) {
- for (var i = 0, il = a.length, s = ''; i < il; i++) {
- s += a[i][0]
-
- if (a[i][1] != null) {
- s += a[i][1]
-
- if (a[i][2] != null) {
- s += ' '
- s += a[i][2]
-
- if (a[i][3] != null) {
- s += ' '
- s += a[i][3]
- s += ' '
- s += a[i][4]
-
- if (a[i][5] != null) {
- s += ' '
- s += a[i][5]
- s += ' '
- s += a[i][6]
-
- if (a[i][7] != null) {
- s += ' '
- s += a[i][7]
- }
- }
- }
- }
- }
- }
-
- return s + ' '
-}
-
-// Deep new id assignment
-function assignNewId (node) {
- // do the same for SVG child nodes as well
- for (var i = node.children.length - 1; i >= 0; i--) {
- assignNewId(node.children[i])
- }
-
- if (node.id) {
- return SVG.adopt(node).id(SVG.eid(node.nodeName))
- }
-
- return SVG.adopt(node)
-}
-
-// Add more bounding box properties
-function fullBox (b) {
- if (b.x == null) {
- b.x = 0
- b.y = 0
- b.width = 0
- b.height = 0
- }
-
- b.w = b.width
- b.h = b.height
- b.x2 = b.x + b.width
- b.y2 = b.y + b.height
- b.cx = b.x + b.width / 2
- b.cy = b.y + b.height / 2
-
- return b
-}
-
-// Get id from reference string
-function idFromReference (url) {
- var m = (url || '').toString().match(SVG.regex.reference)
-
- if (m) return m[1]
-}
-
-// Create matrix array for looping
-var abcdef = 'abcdef'.split('')
+SVG.HtmlNode = SVG.invent({ + inherit: SVG.EventTarget, + create: function create(element) { + this.node = element; + }, + extend: { + add: function add(element, i) { + element = createElement(element); -/* globals fullBox, domContains, isNulledBox, Exception */
-
-SVG.Box = SVG.invent({
- create: function (source) {
- var base = [0, 0, 0, 0]
- source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat)
- : Array.isArray(source) ? source
- : typeof source === 'object' ? [source.left != null ? source.left
- : source.x, source.top != null ? source.top : source.y, source.width, source.height]
- : arguments.length === 4 ? [].slice.call(arguments)
- : base
-
- this.x = source[0]
- this.y = source[1]
- this.width = source[2]
- this.height = source[3]
-
- // add center, right, bottom...
- fullBox(this)
- },
- extend: {
- // Merge rect box with another, return a new instance
- merge: function (box) {
- var x = Math.min(this.x, box.x)
- var y = Math.min(this.y, box.y)
-
- return new SVG.Box(
- x, y,
- Math.max(this.x + this.width, box.x + box.width) - x,
- Math.max(this.y + this.height, box.y + box.height) - y
- )
- },
-
- transform: function (m) {
- var xMin = Infinity
- var xMax = -Infinity
- var yMin = Infinity
- var yMax = -Infinity
-
- var pts = [
- new SVG.Point(this.x, this.y),
- new SVG.Point(this.x2, this.y),
- new SVG.Point(this.x, this.y2),
- new SVG.Point(this.x2, this.y2)
- ]
-
- pts.forEach(function (p) {
- p = p.transform(m)
- xMin = Math.min(xMin, p.x)
- xMax = Math.max(xMax, p.x)
- yMin = Math.min(yMin, p.y)
- yMax = Math.max(yMax, p.y)
- })
-
- return new SVG.Box(
- xMin, yMin,
- xMax - xMin,
- yMax - yMin
- )
- },
-
- addOffset: function () {
- // offset by window scroll position, because getBoundingClientRect changes when window is scrolled
- this.x += window.pageXOffset
- this.y += window.pageYOffset
- return this
- },
- toString: function () {
- return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height
- },
- morph: function (x, y, width, height) {
- this.destination = new SVG.Box(x, y, width, height)
+ if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null); + } + + return this; + }, + put: function put(element, i) { + this.add(element, i); + return element; + }, + getEventTarget: function getEventTarget() { + return this.node; + } + } +}); +/* global proportionalSize, assignNewId, createElement, matches, is */ + +SVG.Element = SVG.invent({ + inherit: SVG.EventTarget, + // Initialize node + create: function create(node) { + // event listener + this.events = {}; // initialize data object + + this.dom = {}; // create circular reference + + this.node = node; + + if (this.node) { + this.type = node.nodeName; + this.node.instance = this; + this.events = node.events || {}; + + if (node.hasAttribute('svgjs:data')) { + // pull svgjs data from the dom (getAttributeNS doesn't work in html5) + this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}); + } + } + }, + // Add class methods + extend: { + // Move over x-axis + x: function x(_x) { + return this.attr('x', _x); + }, + // Move over y-axis + y: function y(_y) { + return this.attr('y', _y); + }, + // Move by center over x-axis + cx: function cx(x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); + }, + // Move by center over y-axis + cy: function cy(y) { + return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); + }, + // Move element to given x and y values + move: function move(x, y) { + return this.x(x).y(y); + }, + // Move element by its center + center: function center(x, y) { + return this.cx(x).cy(y); + }, + // Set width of element + width: function width(_width) { + return this.attr('width', _width); + }, + // Set height of element + height: function height(_height) { + return this.attr('height', _height); + }, + // Set element size to given width and height + size: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.width(new SVG.Number(p.width)).height(new SVG.Number(p.height)); + }, + // Clone element + clone: function clone(parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom(); // clone element and assign new id + + var clone = assignNewId(this.node.cloneNode(true)); // insert the clone in the given parent or after myself + + if (parent) parent.add(clone);else this.after(clone); + return clone; + }, + // Remove element + remove: function remove() { + if (this.parent()) { + this.parent().removeElement(this); + } + + return this; + }, + // Replace element + replace: function replace(element) { + this.after(element).remove(); + return element; + }, + // Add element to given container and return self + addTo: function addTo(parent) { + return createElement(parent).put(this); + }, + // Add element to given container and return container + putIn: function putIn(parent) { + return createElement(parent).add(this); + }, + // Get / set id + id: function id(_id) { + // generate new id if no id set + if (typeof _id === 'undefined' && !this.node.id) { + this.node.id = SVG.eid(this.type); + } // dont't set directly width this.node.id to make `null` work correctly + + + return this.attr('id', _id); + }, + // Checks whether the given point inside the bounding box of the element + inside: function inside(x, y) { + var box = this.bbox(); + return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; + }, + // Show element + show: function show() { + return this.css('display', ''); + }, + // Hide element + hide: function hide() { + return this.css('display', 'none'); + }, + // Is element visible? + visible: function visible() { + return this.css('display') !== 'none'; + }, + // Return id on string conversion + toString: function toString() { + return this.id(); + }, + // Return array of classes on the node + classes: function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(SVG.regex.delimiter); + }, + // Return true if class exists on the node, false otherwise + hasClass: function hasClass(name) { + return this.classes().indexOf(name) !== -1; + }, + // Add class to the node + addClass: function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); + } + + return this; + }, + // Remove class from the node + removeClass: function removeClass(name) { + if (this.hasClass(name)) { + this.attr('class', this.classes().filter(function (c) { + return c !== name; + }).join(' ')); + } + + return this; + }, + // Toggle the presence of a class on the node + toggleClass: function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); + }, + // Get referenced element form attribute value + reference: function reference(attr) { + return SVG.get(this.attr(attr)); + }, + // Returns the parent element instance + parent: function parent(type) { + var parent = this; // check for parent + + if (!parent.node.parentNode) return null; // get parent element + + parent = SVG.adopt(parent.node.parentNode); + if (!type) return parent; // loop trough ancestors if type is given + + while (parent && parent.node instanceof window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; + parent = SVG.adopt(parent.node.parentNode); + } + }, + // Get parent document + doc: function doc() { + var p = this.parent(SVG.Doc); + return p && p.doc(); + }, + // Get defs + defs: function defs() { + return this.doc().defs(); + }, + // return array of all ancestors of given type up to the root svg + parents: function parents(type) { + var parents = []; + var parent = this; + + do { + parent = parent.parent(type); + if (!parent || !parent.node) break; + parents.push(parent); + } while (parent.parent); + + return parents; + }, + // matches the element vs a css selector + matches: function matches(selector) { + return _matches(this.node, selector); + }, + // Returns the svg node to call native svg methods on it + native: function native() { + return this.node; + }, + // Import raw svg + svg: function svg(_svg) { + var well, len; // act as a setter if svg is given + + if (_svg && this instanceof SVG.Parent) { + // create temporary holder + well = document.createElementNS(SVG.ns, 'svg'); // dump raw svg + + well.innerHTML = _svg; // transplant nodes + + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild); + } // otherwise act as a getter + + } else { + // write svgjs data to the dom + this.writeDataToDom(); + return this.node.outerHTML; + } + + return this; + }, + // write svgjs data to the dom + writeDataToDom: function writeDataToDom() { + // dump variables recursively + if (this.is(SVG.Parent)) { + this.each(function () { + this.writeDataToDom(); + }); + } // remove previously set data + + + this.node.removeAttribute('svgjs:data'); + + if (Object.keys(this.dom).length) { + this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)); // see #428 + } + + return this; + }, + // set given data to the elements data property + setData: function setData(o) { + this.dom = o; + return this; + }, + is: function is(obj) { + return _is(this, obj); + }, + getEventTarget: function getEventTarget() { + return this.node; + } + } +}); +/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */ + +SVG.Matrix = SVG.invent({ + // Initialize + create: function create(source) { + var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object + + source = source instanceof SVG.Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new SVG.Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + + this.a = source.a != null ? source.a : base.a; + this.b = source.b != null ? source.b : base.b; + this.c = source.c != null ? source.c : base.c; + this.d = source.d != null ? source.d : base.d; + this.e = source.e != null ? source.e : base.e; + this.f = source.f != null ? source.f : base.f; + }, + // Add methods + extend: { + // Clones this matrix + clone: function clone() { + return new SVG.Matrix(this); + }, + // Transform a matrix into another matrix by manipulating the space + transform: function transform(o) { + // Check if o is a matrix and then left multiply it directly + if (isMatrixLike(o)) { + var matrix = new SVG.Matrix(o); + return matrix.multiplyO(this); + } // Get the proposed transformations and the current transformations + + + var t = formatTransforms(o); + var current = this; + + var _transform = new SVG.Point(t.ox, t.oy).transform(current), + ox = _transform.x, + oy = _transform.y; // Construct the resulting matrix + + + var transformer = new SVG.Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there + + if (isFinite(t.px) || isFinite(t.py)) { + var origin = new SVG.Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + + var dx = t.px ? t.px - origin.x : 0; + var dy = t.py ? t.py - origin.y : 0; + transformer.translateO(dx, dy); + } // Translate now after positioning + + + transformer.translateO(t.tx, t.ty); + return transformer; + }, + // Applies a matrix defined by its affine parameters + compose: function compose(o) { + if (o.origin) { + o.originX = o.origin[0]; + o.originY = o.origin[1]; + } // Get the parameters + + + var ox = o.originX || 0; + var oy = o.originY || 0; + var sx = o.scaleX || 1; + var sy = o.scaleY || 1; + var lam = o.shear || 0; + var theta = o.rotate || 0; + var tx = o.translateX || 0; + var ty = o.translateY || 0; // Apply the standard matrix + + var result = new SVG.Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); + return result; + }, + // Decomposes this matrix into its affine parameters + decompose: function decompose() { + var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + // Get the parameters from the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise + + var determinant = a * d - b * c; + var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + + var sx = ccw * Math.sqrt(a * a + b * b); + var thetaRad = Math.atan2(ccw * b, ccw * a); + var theta = 180 / Math.PI * thetaRad; + var ct = Math.cos(thetaRad); + var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + + var lam = (a * c + b * d) / determinant; + var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations + + var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); + var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it + + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + }, + // Morph one matrix into another + morph: function morph(matrix) { + // Store new destination + this.destination = new SVG.Matrix(matrix); + return this; + }, + // Get morphed matrix at a given position + at: function at(pos) { + // Make sure a destination is defined + if (!this.destination) return this; // Calculate morphed matrix at a given position + + var matrix = new SVG.Matrix({ + a: this.a + (this.destination.a - this.a) * pos, + b: this.b + (this.destination.b - this.b) * pos, + c: this.c + (this.destination.c - this.c) * pos, + d: this.d + (this.destination.d - this.d) * pos, + e: this.e + (this.destination.e - this.e) * pos, + f: this.f + (this.destination.f - this.f) * pos + }); + return matrix; + }, + // Left multiplies by the given matrix + multiply: function multiply(matrix) { + return this.clone().multiplyO(matrix); + }, + multiplyO: function multiplyO(matrix) { + // Get the matrices + var l = this; + var r = matrix instanceof SVG.Matrix ? matrix : new SVG.Matrix(matrix); + return matrixMultiply(l, r, this); + }, + lmultiply: function lmultiply(matrix) { + return this.clone().lmultiplyO(matrix); + }, + lmultiplyO: function lmultiplyO(matrix) { + var r = this; + var l = matrix instanceof SVG.Matrix ? matrix : new SVG.Matrix(matrix); + return matrixMultiply(l, r, this); + }, + // Inverses matrix + inverseO: function inverseO() { + // Get the current parameters out of the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Invert the 2x2 matrix in the top left + + var det = a * d - b * c; + if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix + + var na = d / det; + var nb = -b / det; + var nc = -c / det; + var nd = a / det; // Apply the inverted matrix to the top right + + var ne = -(na * e + nc * f); + var nf = -(nb * e + nd * f); // Construct the inverted matrix + + this.a = na; + this.b = nb; + this.c = nc; + this.d = nd; + this.e = ne; + this.f = nf; + return this; + }, + inverse: function inverse() { + return this.clone().inverseO(); + }, + // Translate matrix + translate: function translate(x, y) { + return this.clone().translateO(x, y); + }, + translateO: function translateO(x, y) { + this.e += x || 0; + this.f += y || 0; + return this; + }, + // Scale matrix + scale: function scale(x, y, cx, cy) { + var _this$clone; + + return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); + }, + scaleO: function scaleO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + + // Support uniform scaling + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } + + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * x; + this.b = b * y; + this.c = c * x; + this.d = d * y; + this.e = e * x - cx * x + cx; + this.f = f * y - cy * y + cy; + return this; + }, + // Rotate matrix + rotate: function rotate(r, cx, cy) { + return this.clone().rotateO(r, cx, cy); + }, + rotateO: function rotateO(r) { + var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + // Convert degrees to radians + r = SVG.utils.radians(r); + var cos = Math.cos(r); + var sin = Math.sin(r); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * cos - b * sin; + this.b = b * cos + a * sin; + this.c = c * cos - d * sin; + this.d = d * cos + c * sin; + this.e = e * cos - f * sin + cy * sin - cx * cos + cx; + this.f = f * cos + e * sin - cx * sin - cy * cos + cy; + return this; + }, + // Flip matrix on x or y, at a given offset + flip: function flip(axis, around) { + return this.clone().flipO(axis, around); + }, + flipO: function flipO(axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point + }, + // Shear matrix + shear: function shear(a, cx, cy) { + return this.clone().shearO(a, cx, cy); + }, + shearO: function shearO(lx) { + var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.c = c + d * lx; + this.e = e + f * lx - cy * lx; + return this; + }, + // Skew Matrix + skew: function skew(x, y, cx, cy) { + var _this$clone2; + + return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); + }, + skewO: function skewO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + + // support uniformal skew + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } // Convert degrees to radians + + + x = SVG.utils.radians(x); + y = SVG.utils.radians(y); + var lx = Math.tan(x); + var ly = Math.tan(y); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.b = b + a * ly; + this.c = c + d * lx; + this.d = d + c * ly; + this.e = e + f * lx - cy * lx; + this.f = f + e * ly - cx * ly; + return this; + }, + // SkewX + skewX: function skewX(x, cx, cy) { + return this.skew(x, 0, cx, cy); + }, + skewXO: function skewXO(x, cx, cy) { + return this.skewO(x, 0, cx, cy); + }, + // SkewY + skewY: function skewY(y, cx, cy) { + return this.skew(0, y, cx, cy); + }, + skewYO: function skewYO(y, cx, cy) { + return this.skewO(0, y, cx, cy); + }, + // Transform around a center point + aroundO: function aroundO(cx, cy, matrix) { + var dx = cx || 0; + var dy = cy || 0; + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); + }, + around: function around(cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix); + }, + // Convert to native SVGMatrix + native: function native() { + // create new matrix + var matrix = SVG.parser.nodes.svg.node.createSVGMatrix(); // update with current values + + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]]; + } + + return matrix; + }, + // Check if two matrices are equal + equals: function equals(other) { + var comp = new SVG.Matrix(other); + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); + }, + // Convert matrix to string + toString: function toString() { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; + }, + toArray: function toArray() { + return [this.a, this.b, this.c, this.d, this.e, this.f]; + }, + valueOf: function valueOf() { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } + }, + // Define parent + parent: SVG.Element, + // Add parent method + construct: { + // Get current matrix + ctm: function ctm() { + return new SVG.Matrix(this.node.getCTM()); + }, + // Get current screen matrix + screenCTM: function screenCTM() { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537
+ This is needed because FF does not return the transformation matrix
+ for the inner coordinate system when getScreenCTM() is called on nested svgs.
+ However all other Browsers do that */ + if (this instanceof SVG.Doc && !this.isRoot()) { + var rect = this.rect(1, 1); + var m = rect.node.getScreenCTM(); + rect.remove(); + return new SVG.Matrix(m); + } + + return new SVG.Matrix(this.node.getScreenCTM()); + } + } +}); // let extensions = {} +// ['rotate'].forEach((method) => { +// let methodO = method + 'O' +// extensions[method] = function (...args) { +// return new SVG.Matrix(this)[methodO](...args) +// } +// }) +// +// SVG.extend(SVG.Matrix, extensions) +// function matrixMultiplyParams (matrix, a, b, c, d, e, f) { +// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix) +// } + +SVG.Point = SVG.invent({ + // Initialize + create: function create(x, y, base) { + var source; + base = base || { + x: 0, + y: 0 // ensure source as object + + }; + source = Array.isArray(x) ? { + x: x[0], + y: x[1] + } : _typeof(x) === 'object' ? { + x: x.x, + y: x.y + } : { + x: x, + y: y // merge source + + }; + this.x = source.x == null ? base.x : source.x; + this.y = source.y == null ? base.y : source.y; + }, + // Add methods + extend: { + // Clone point + clone: function clone() { + return new SVG.Point(this); + }, + // Morph one point into another + morph: function morph(x, y) { + // store new destination + this.destination = new SVG.Point(x, y); + return this; + }, + // Get morphed point at a given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // calculate morphed matrix at a given position + + var point = new SVG.Point({ + x: this.x + (this.destination.x - this.x) * pos, + y: this.y + (this.destination.y - this.y) * pos + }); + return point; + }, + // Convert to native SVGPoint + native: function native() { + // create new point + var point = SVG.parser.nodes.svg.node.createSVGPoint(); // update with current values + + point.x = this.x; + point.y = this.y; + return point; + }, + // transform point with matrix + transform: function transform(m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e; + var y = m.b * this.x + m.d * this.y + m.f; // Return the required point + + return new SVG.Point(x, y); + } + } +}); +SVG.extend(SVG.Element, { + // Get point + point: function point(x, y) { + return new SVG.Point(x, y).transform(this.screenCTM().inverse()); + } +}); +SVG.extend(SVG.Element, { + // Set svg element attribute + attr: function attr(a, v, n) { + // act as full getter + if (a == null) { + // get an object of attributes + a = {}; + v = this.node.attributes; + + for (n = v.length - 1; n >= 0; n--) { + a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue) ? parseFloat(v[n].nodeValue) : v[n].nodeValue; + } + + return a; + } else if (_typeof(a) === 'object') { + // apply every attribute individually if an object is passed + for (v in a) { + this.attr(v, a[v]); + } + } else if (v === null) { + // remove value + this.node.removeAttribute(a); + } else if (v == null) { + // act as a getter if the first and only argument is not an object + v = this.node.getAttribute(a); + return v == null ? SVG.defaults.attrs[a] : SVG.regex.isNumber.test(v) ? parseFloat(v) : v; + } else { + // convert image fill and stroke to patterns + if (a === 'fill' || a === 'stroke') { + if (SVG.regex.isImage.test(v)) { + v = this.doc().defs().image(v); + } + + if (v instanceof SVG.Image) { + v = this.doc().defs().pattern(0, 0, function () { + this.add(v); + }); + } + } // ensure correct numeric values (also accepts NaN and Infinity) + + + if (typeof v === 'number') { + v = new SVG.Number(v); + } else if (SVG.Color.isColor(v)) { + // ensure full hex color + v = new SVG.Color(v); + } else if (Array.isArray(v)) { + // parse array values + v = new SVG.Array(v); + } // if the passed attribute is leading... + + + if (a === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(v); + } + } else { + // set given attribute on node + typeof n === 'string' ? this.node.setAttributeNS(n, a, v.toString()) : this.node.setAttribute(a, v.toString()); + } // rebuild if required + + + if (this.rebuild && (a === 'font-size' || a === 'x')) { + this.rebuild(a, v); + } + } + + return this; + } +}); +/* global arrayToMatrix getOrigin isMatrixLike */ + +SVG.extend(SVG.Element, { + // Reset all transformations + untransform: function untransform() { + return this.attr('transform', null); + }, + // merge the whole transformation chain into one matrix and returns it + matrixify: function matrixify() { + var matrix = (this.attr('transform') || ''). // split transformations + split(SVG.regex.transforms).slice(0, -1).map(function (str) { + // generate key => value pairs + var kv = str.trim().split('('); + return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { + return parseFloat(str); + })]; + }).reverse() // merge every transformation into one matrix + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(arrayToMatrix(transform[1])); + } + + return matrix[transform[0]].apply(matrix, transform[1]); + }, new SVG.Matrix()); + return matrix; + }, + // add an element to another parent without changing the visual representation on the screen + toParent: function toParent(parent) { + if (this === parent) return this; + var ctm = this.screenCTM(); + var pCtm = parent.screenCTM().inverse(); + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)); + return this; + }, + // same as above with parent equals root-svg + toDoc: function toDoc() { + return this.toParent(this.doc()); + } +}); +SVG.extend(SVG.Element, { + // Add transformations + transform: function transform(o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new SVG.Matrix(this).decompose(); + return decomposed[o] || decomposed; + } + + if (!isMatrixLike(o)) { + // Set the origin according to the defined transform + o = _objectSpread({}, o, { + origin: getOrigin(o, this) + }); + } // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing + + + var cleanRelative = relative === true ? this : relative || false; + var result = new SVG.Matrix(cleanRelative).transform(o); + return this.attr('transform', result); + } +}); +/* global camelCase */ + +SVG.extend(SVG.Element, { + // Dynamic style generator + css: function css(s, v) { + var ret = {}; + var t, i; + + if (arguments.length === 0) { + // get full style as object + this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { + return !!el.length; + }).forEach(function (el) { + t = el.split(/\s*:\s*/); + ret[t[0]] = t[1]; + }); + return ret; + } + + if (arguments.length < 2) { + // get style properties in the array + if (Array.isArray(s)) { + for (i = s.length; i--;) { + ret[camelCase(s[i])] = this.node.style[camelCase(s[i])]; + } + + return ret; + } // get style for property + + + if (typeof s === 'string') { + return this.node.style[camelCase(s)]; + } // set styles in object + + + if (_typeof(s) === 'object') { + for (i in s) { + // set empty string if null/undefined/'' was given + this.node.style[camelCase(i)] = s[i] == null || SVG.regex.isBlank.test(s[i]) ? '' : s[i]; + } + } + } // set style for property + + + if (arguments.length === 2) { + this.node.style[camelCase(s)] = v == null || SVG.regex.isBlank.test(v) ? '' : v; + } + + return this; + } +}); +/* global createElement */ + +SVG.Parent = SVG.invent({ + // Initialize node + create: function create(node) { + SVG.Element.call(this, node); + }, + // Inherit from + inherit: SVG.Element, + // Add class methods + extend: { + // Returns all child elements + children: function children() { + return SVG.utils.map(this.node.children, function (node) { + return SVG.adopt(node); + }); + }, + // Add given element at a position + add: function add(element, i) { + element = createElement(element); + + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null); + } + + return this; + }, + // Basically does the same as `add()` but returns the added element instead + put: function put(element, i) { + this.add(element, i); + return element.instance || element; + }, + // Checks if the given element is a child + has: function has(element) { + return this.index(element) >= 0; + }, + // Gets index of given element + index: function index(element) { + return [].slice.call(this.node.children).indexOf(element.node); + }, + // Get a element at the given index + get: function get(i) { + return SVG.adopt(this.node.children[i]); + }, + // Get first child + first: function first() { + return this.get(0); + }, + // Get the last child + last: function last() { + return this.get(this.node.children.length - 1); + }, + // Iterates over all children and invokes a given block + each: function each(block, deep) { + var children = this.children(); + var i, il; + + for (i = 0, il = children.length; i < il; i++) { + if (children[i] instanceof SVG.Element) { + block.apply(children[i], [i, children]); + } + + if (deep && children[i] instanceof SVG.Parent) { + children[i].each(block, deep); + } + } + + return this; + }, + // Remove a given child + removeElement: function removeElement(element) { + this.node.removeChild(element.node); + return this; + }, + // Remove all elements in this container + clear: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // remove defs reference + + + delete this._defs; + return this; + } + } +}); +SVG.extend(SVG.Parent, { + flatten: function flatten(parent) { + // flattens is only possible for nested svgs and groups + if (!(this instanceof SVG.G || this instanceof SVG.Doc)) { + return this; + } + + parent = parent || (this instanceof SVG.Doc && this.isRoot() ? this : this.parent(SVG.Parent)); + this.each(function () { + if (this instanceof SVG.Defs) return this; + if (this instanceof SVG.Parent) return this.flatten(parent); + return this.toParent(parent); + }); // we need this so that SVG.Doc does not get removed + + this.node.firstElementChild || this.remove(); + return this; + }, + ungroup: function ungroup(parent) { + // ungroup is only possible for nested svgs and groups + if (!(this instanceof SVG.G || this instanceof SVG.Doc && !this.isRoot())) { + return this; + } + + parent = parent || this.parent(SVG.Parent); + this.each(function () { + return this.toParent(parent); + }); // we need this so that SVG.Doc does not get removed + + this.remove(); + return this; + } +}); +SVG.Container = SVG.invent({ + // Initialize node + create: function create(node) { + SVG.Element.call(this, node); + }, + // Inherit from + inherit: SVG.Parent +}); +SVG.Defs = SVG.invent({ + // Initialize node + create: 'defs', + // Inherit from + inherit: SVG.Container +}); +SVG.G = SVG.invent({ + // Initialize node + create: 'g', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: {}, + // Add parent method + construct: { + // Create a group element + group: function group() { + return this.put(new SVG.G()); + } + } +}); // ### This module adds backward / forward functionality to elements. +// + +SVG.extend(SVG.Element, { + // Get all siblings, including myself + siblings: function siblings() { + return this.parent().children(); + }, + // Get the curent position siblings + position: function position() { + return this.parent().index(this); + }, + // Get the next element (will return null if there is none) + next: function next() { + return this.siblings()[this.position() + 1]; + }, + // Get the next element (will return null if there is none) + prev: function prev() { + return this.siblings()[this.position() - 1]; + }, + // Send given element one step forward + forward: function forward() { + var i = this.position() + 1; + var p = this.parent(); // move node one step forward + + p.removeElement(this).add(this, i); // make sure defs node is always at the top + + if (p instanceof SVG.Doc) { + p.node.appendChild(p.defs().node); + } + + return this; + }, + // Send given element one step backward + backward: function backward() { + var i = this.position(); + + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1); + } + + return this; + }, + // Send given element all the way to the front + front: function front() { + var p = this.parent(); // Move node forward + + p.node.appendChild(this.node); // Make sure defs node is always at the top + + if (p instanceof SVG.Doc) { + p.node.appendChild(p.defs().node); + } + + return this; + }, + // Send given element all the way to the back + back: function back() { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0); + } + + return this; + }, + // Inserts a given element before the targeted element + before: function before(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i); + return this; + }, + // Insters a given element after the targeted element + after: function after(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i + 1); + return this; + } +}); +SVG.Mask = SVG.invent({ + // Initialize node + create: 'mask', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Unmask all masked elements and remove itself + remove: function remove() { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask(); + }); // remove mask from parent + + return SVG.Element.prototype.remove.call(this); + }, + targets: function targets() { + return SVG.select('svg [mask*="' + this.id() + '"]'); + } + }, + // Add parent method + construct: { + // Create masking element + mask: function mask() { + return this.defs().put(new SVG.Mask()); + } + } +}); +SVG.extend(SVG.Element, { + // Distribute mask to svg element + maskWith: function maskWith(element) { + // use given mask or create a new one + var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element); // apply mask + + return this.attr('mask', 'url("#' + masker.id() + '")'); + }, + // Unmask element + unmask: function unmask() { + return this.attr('mask', null); + }, + masker: function masker() { + return this.reference('mask'); + } +}); +SVG.ClipPath = SVG.invent({ + // Initialize node + create: 'clipPath', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Unclip all clipped elements and remove itself + remove: function remove() { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip(); + }); // remove clipPath from parent + + return SVG.Element.prototype.remove.call(this); + }, + targets: function targets() { + return SVG.select('svg [clip-path*="' + this.id() + '"]'); + } + }, + // Add parent method + construct: { + // Create clipping element + clip: function clip() { + return this.defs().put(new SVG.ClipPath()); + } + } +}); // + +SVG.extend(SVG.Element, { + // Distribute clipPath to svg element + clipWith: function clipWith(element) { + // use given clip or create a new one + var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element); // apply mask + + return this.attr('clip-path', 'url("#' + clipper.id() + '")'); + }, + // Unclip element + unclip: function unclip() { + return this.attr('clip-path', null); + }, + clipper: function clipper() { + return this.reference('clip-path'); + } +}); +SVG.Gradient = SVG.invent({ + // Initialize node + create: function create(type) { + SVG.Element.call(this, _typeof(type) === 'object' ? type : SVG.create(type + 'Gradient')); + }, + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Add a color stop + stop: function stop(offset, color, opacity) { + return this.put(new SVG.Stop()).update(offset, color, opacity); + }, + // Update gradient + update: function update(block) { + // remove all stops + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + }, + // Return the fill id + url: function url() { + return 'url(#' + this.id() + ')'; + }, + // Alias string convertion to fill + toString: function toString() { + return this.url(); + }, + // custom attr to handle transform + attr: function attr(a, b, c) { + if (a === 'transform') a = 'gradientTransform'; + return SVG.Container.prototype.attr.call(this, a, b, c); + } + }, + // Add parent method + construct: { + // Create gradient element in defs + gradient: function gradient(type, block) { + return this.defs().gradient(type, block); + } + } +}); // Add animatable methods to both gradient and fx module + +SVG.extend([SVG.Gradient, SVG.Timeline], { + // From position + from: function from(x, y) { + return (this._target || this).type === 'radialGradient' ? this.attr({ + fx: new SVG.Number(x), + fy: new SVG.Number(y) + }) : this.attr({ + x1: new SVG.Number(x), + y1: new SVG.Number(y) + }); + }, + // To position + to: function to(x, y) { + return (this._target || this).type === 'radialGradient' ? this.attr({ + cx: new SVG.Number(x), + cy: new SVG.Number(y) + }) : this.attr({ + x2: new SVG.Number(x), + y2: new SVG.Number(y) + }); + } +}); // Base gradient generation + +SVG.extend(SVG.Defs, { + // define gradient + gradient: function gradient(type, block) { + return this.put(new SVG.Gradient(type)).update(block); + } +}); +SVG.Stop = SVG.invent({ + // Initialize node + create: 'stop', + // Inherit from + inherit: SVG.Element, + // Add class methods + extend: { + // add color stops + update: function update(o) { + if (typeof o === 'number' || o instanceof SVG.Number) { + o = { + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }; + } // set attributes + + + if (o.opacity != null) this.attr('stop-opacity', o.opacity); + if (o.color != null) this.attr('stop-color', o.color); + if (o.offset != null) this.attr('offset', new SVG.Number(o.offset)); + return this; + } + } +}); +SVG.Pattern = SVG.invent({ + // Initialize node + create: 'pattern', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Return the fill id + url: function url() { + return 'url(#' + this.id() + ')'; + }, + // Update pattern by rebuilding + update: function update(block) { + // remove content + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + }, + // Alias string convertion to fill + toString: function toString() { + return this.url(); + }, + // custom attr to handle transform + attr: function attr(a, b, c) { + if (a === 'transform') a = 'patternTransform'; + return SVG.Container.prototype.attr.call(this, a, b, c); + } + }, + // Add parent method + construct: { + // Create pattern element in defs + pattern: function pattern(width, height, block) { + return this.defs().pattern(width, height, block); + } + } +}); +SVG.extend(SVG.Defs, { + // Define gradient + pattern: function pattern(width, height, block) { + return this.put(new SVG.Pattern()).update(block).attr({ + x: 0, + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }); + } +}); +SVG.Doc = SVG.invent({ + // Initialize node + create: function create(node) { + SVG.Element.call(this, node || SVG.create('svg')); // set svg element attributes and ensure defs node + + this.namespace(); + }, + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + isRoot: function isRoot() { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; + }, + // Check if this is a root svg. If not, call docs from this element + doc: function doc() { + if (this.isRoot()) return this; + return SVG.Element.prototype.doc.call(this); + }, + // Add namespaces + namespace: function namespace() { + if (!this.isRoot()) return this.doc().namespace(); + return this.attr({ + xmlns: SVG.ns, + version: '1.1' + }).attr('xmlns:xlink', SVG.xlink, SVG.xmlns).attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns); + }, + // Creates and returns defs element + defs: function defs() { + if (!this.isRoot()) return this.doc().defs(); + return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs()); + }, + // custom parent method + parent: function parent(type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode; + } + + return SVG.Element.prototype.parent.call(this, type); + }, + // Removes the doc from the DOM + remove: function remove() { + if (!this.isRoot()) { + return SVG.Element.prototype.remove.call(this); + } + + if (this.parent()) { + this.parent().removeChild(this.node); + } + + return this; + }, + clear: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } + + return this; + } + }, + construct: { + // Create nested svg document + nested: function nested() { + return this.put(new SVG.Doc()); + } + } +}); +SVG.Shape = SVG.invent({ + // Initialize node + create: function create(node) { + SVG.Element.call(this, node); + }, + // Inherit from + inherit: SVG.Element +}); +SVG.Bare = SVG.invent({ + // Initialize + create: function create(element, inherit) { + // construct element + SVG.Element.call(this, SVG.create(element)); // inherit custom methods + + if (inherit) { + for (var method in inherit.prototype) { + if (typeof inherit.prototype[method] === 'function') { + this[method] = inherit.prototype[method]; + } + } + } + }, + // Inherit from + inherit: SVG.Element, + // Add methods + extend: { + // Insert some plain text + words: function words(text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // create text node + + + this.node.appendChild(document.createTextNode(text)); + return this; + } + } +}); +SVG.extend(SVG.Parent, { + // Create an element that is not described by SVG.js + element: function element(_element, inherit) { + return this.put(new SVG.Bare(_element, inherit)); + } +}); +SVG.Symbol = SVG.invent({ + // Initialize node + create: 'symbol', + // Inherit from + inherit: SVG.Container, + construct: { + // create symbol + symbol: function symbol() { + return this.put(new SVG.Symbol()); + } + } +}); +SVG.Use = SVG.invent({ + // Initialize node + create: 'use', + // Inherit from + inherit: SVG.Shape, + // Add class methods + extend: { + // Use element as a reference + element: function element(_element2, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + _element2, SVG.xlink); + } + }, + // Add parent method + construct: { + // Create a use element + use: function use(element, file) { + return this.put(new SVG.Use()).element(element, file); + } + } +}); +SVG.Rect = SVG.invent({ + // Initialize node + create: 'rect', + // Inherit from + inherit: SVG.Shape, + // Add parent method + construct: { + // Create a rect element + rect: function rect(width, height) { + return this.put(new SVG.Rect()).size(width, height); + } + } +}); +/* global proportionalSize */ + +SVG.Circle = SVG.invent({ + // Initialize node + create: 'circle', + // Inherit from + inherit: SVG.Shape, + // Add parent method + construct: { + // Create circle element, based on ellipse + circle: function circle(size) { + return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0); + } + } +}); +SVG.extend([SVG.Circle, SVG.Timeline], { + // Radius x value + rx: function rx(_rx) { + return this.attr('r', _rx); + }, + // Alias radius x value + ry: function ry(_ry) { + return this.rx(_ry); + } +}); +SVG.Ellipse = SVG.invent({ + // Initialize node + create: 'ellipse', + // Inherit from + inherit: SVG.Shape, + // Add parent method + construct: { + // Create an ellipse + ellipse: function ellipse(width, height) { + return this.put(new SVG.Ellipse()).size(width, height).move(0, 0); + } + } +}); +SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], { + // Radius x value + rx: function rx(_rx2) { + return this.attr('rx', _rx2); + }, + // Radius y value + ry: function ry(_ry2) { + return this.attr('ry', _ry2); + } +}); // Add common method + +SVG.extend([SVG.Circle, SVG.Ellipse], { + // Move over x-axis + x: function x(_x2) { + return _x2 == null ? this.cx() - this.rx() : this.cx(_x2 + this.rx()); + }, + // Move over y-axis + y: function y(_y2) { + return _y2 == null ? this.cy() - this.ry() : this.cy(_y2 + this.ry()); + }, + // Move by center over x-axis + cx: function cx(x) { + return x == null ? this.attr('cx') : this.attr('cx', x); + }, + // Move by center over y-axis + cy: function cy(y) { + return y == null ? this.attr('cy') : this.attr('cy', y); + }, + // Set width of element + width: function width(_width2) { + return _width2 == null ? this.rx() * 2 : this.rx(new SVG.Number(_width2).divide(2)); + }, + // Set height of element + height: function height(_height2) { + return _height2 == null ? this.ry() * 2 : this.ry(new SVG.Number(_height2).divide(2)); + }, + // Custom size function + size: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.rx(new SVG.Number(p.width).divide(2)).ry(new SVG.Number(p.height).divide(2)); + } +}); +/* global proportionalSize */ + +SVG.Line = SVG.invent({ + // Initialize node + create: 'line', + // Inherit from + inherit: SVG.Shape, + // Add class methods + extend: { + // Get array + array: function array() { + return new SVG.PointArray([[this.attr('x1'), this.attr('y1')], [this.attr('x2'), this.attr('y2')]]); + }, + // Overwrite native plot() method + plot: function plot(x1, y1, x2, y2) { + if (x1 == null) { + return this.array(); + } else if (typeof y1 !== 'undefined') { + x1 = { + x1: x1, + y1: y1, + x2: x2, + y2: y2 + }; + } else { + x1 = new SVG.PointArray(x1).toLine(); + } + + return this.attr(x1); + }, + // Move by left top corner + move: function move(x, y) { + return this.attr(this.array().move(x, y).toLine()); + }, + // Set element size to given width and height + size: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr(this.array().size(p.width, p.height).toLine()); + } + }, + // Add parent method + construct: { + // Create a line element + line: function line(x1, y1, x2, y2) { + // make sure plot is called as a setter + // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray + return SVG.Line.prototype.plot.apply(this.put(new SVG.Line()), x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]); + } + } +}); +/* global proportionalSize */ + +SVG.Polyline = SVG.invent({ + // Initialize node + create: 'polyline', + // Inherit from + inherit: SVG.Shape, + // Add parent method + construct: { + // Create a wrapped polyline element + polyline: function polyline(p) { + // make sure plot is called as a setter + return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray()); + } + } +}); +SVG.Polygon = SVG.invent({ + // Initialize node + create: 'polygon', + // Inherit from + inherit: SVG.Shape, + // Add parent method + construct: { + // Create a wrapped polygon element + polygon: function polygon(p) { + // make sure plot is called as a setter + return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray()); + } + } +}); // Add polygon-specific functions + +SVG.extend([SVG.Polyline, SVG.Polygon], { + // Get array + array: function array() { + return this._array || (this._array = new SVG.PointArray(this.attr('points'))); + }, + // Plot new path + plot: function plot(p) { + return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new SVG.PointArray(p)); + }, + // Clear array cache + clear: function clear() { + delete this._array; + return this; + }, + // Move by left top corner + move: function move(x, y) { + return this.attr('points', this.array().move(x, y)); + }, + // Set element size to given width and height + size: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('points', this.array().size(p.width, p.height)); + } +}); // unify all point to point elements + +SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon], { + // Define morphable array + MorphArray: SVG.PointArray, + // Move by left top corner over x-axis + x: function x(_x3) { + return _x3 == null ? this.bbox().x : this.move(_x3, this.bbox().y); + }, + // Move by left top corner over y-axis + y: function y(_y3) { + return _y3 == null ? this.bbox().y : this.move(this.bbox().x, _y3); + }, + // Set width of element + width: function width(_width3) { + var b = this.bbox(); + return _width3 == null ? b.width : this.size(_width3, b.height); + }, + // Set height of element + height: function height(_height3) { + var b = this.bbox(); + return _height3 == null ? b.height : this.size(b.width, _height3); + } +}); +/* global proportionalSize */ + +SVG.Path = SVG.invent({ + // Initialize node + create: 'path', + // Inherit from + inherit: SVG.Shape, + // Add class methods + extend: { + // Define morphable array + MorphArray: SVG.PathArray, + // Get array + array: function array() { + return this._array || (this._array = new SVG.PathArray(this.attr('d'))); + }, + // Plot new path + plot: function plot(d) { + return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new SVG.PathArray(d)); + }, + // Clear array cache + clear: function clear() { + delete this._array; + return this; + }, + // Move by left top corner + move: function move(x, y) { + return this.attr('d', this.array().move(x, y)); + }, + // Move by left top corner over x-axis + x: function x(_x4) { + return _x4 == null ? this.bbox().x : this.move(_x4, this.bbox().y); + }, + // Move by left top corner over y-axis + y: function y(_y4) { + return _y4 == null ? this.bbox().y : this.move(this.bbox().x, _y4); + }, + // Set element size to given width and height + size: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('d', this.array().size(p.width, p.height)); + }, + // Set width of element + width: function width(_width4) { + return _width4 == null ? this.bbox().width : this.size(_width4, this.bbox().height); + }, + // Set height of element + height: function height(_height4) { + return _height4 == null ? this.bbox().height : this.size(this.bbox().width, _height4); + } + }, + // Add parent method + construct: { + // Create a wrapped path element + path: function path(d) { + // make sure plot is called as a setter + return this.put(new SVG.Path()).plot(d || new SVG.PathArray()); + } + } +}); +SVG.Image = SVG.invent({ + // Initialize node + create: 'image', + // Inherit from + inherit: SVG.Shape, + // Add class methods + extend: { + // (re)load image + load: function load(url, callback) { + if (!url) return this; + var img = new window.Image(); + SVG.on(img, 'load', function (e) { + var p = this.parent(SVG.Pattern); // ensure image size + + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height); + } + + if (p instanceof SVG.Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()); + } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }); + } + }, this); + SVG.on(img, 'load error', function () { + // dont forget to unbind memory leaking events + SVG.off(img); + }); + return this.attr('href', img.src = url, SVG.xlink); + } + }, + // Add parent method + construct: { + // create image element, load image and set its size + image: function image(source, callback) { + return this.put(new SVG.Image()).size(0, 0).load(source, callback); + } + } +}); +SVG.Text = SVG.invent({ + // Initialize node + create: function create(node) { + SVG.Element.call(this, node || SVG.create('text')); + this.dom.leading = new SVG.Number(1.3); // store leading value for rebuilding + + this._rebuild = true; // enable automatic updating of dy values + + this._build = false; // disable build mode for adding multiple lines + // set default font + + this.attr('font-family', SVG.defaults.attrs['font-family']); + }, + // Inherit from + inherit: SVG.Parent, + // Add class methods + extend: { + // Move over x-axis + x: function x(_x5) { + // act as getter + if (_x5 == null) { + return this.attr('x'); + } + + return this.attr('x', _x5); + }, + // Move over y-axis + y: function y(_y5) { + var oy = this.attr('y'); + var o = typeof oy === 'number' ? oy - this.bbox().y : 0; // act as getter + + if (_y5 == null) { + return typeof oy === 'number' ? oy - o : oy; + } + + return this.attr('y', typeof _y5 === 'number' ? _y5 + o : _y5); + }, + // Move center over x-axis + cx: function cx(x) { + return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2); + }, + // Move center over y-axis + cy: function cy(y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2); + }, + // Set the text content + text: function text(_text) { + // act as getter + if (_text === undefined) { + var children = this.node.childNodes; + var firstLine = 0; + _text = ''; + + for (var i = 0, len = children.length; i < len; ++i) { + // skip textPaths - they are no lines + if (children[i].nodeName === 'textPath') { + if (i === 0) firstLine = 1; + continue; + } // add newline if its not the first child and newLined is set to true + + + if (i !== firstLine && children[i].nodeType !== 3 && SVG.adopt(children[i]).dom.newLined === true) { + _text += '\n'; + } // add content of this node + + + _text += children[i].textContent; + } + + return _text; + } // remove existing content + + + this.clear().build(true); + + if (typeof _text === 'function') { + // call block + _text.call(this, this); + } else { + // store text and make sure text is not blank + _text = _text.split('\n'); // build new lines + + for (var j = 0, jl = _text.length; j < jl; j++) { + this.tspan(_text[j]).newLine(); + } + } // disable build mode and rebuild lines + + + return this.build(false).rebuild(); + }, + // Set / get leading + leading: function leading(value) { + // act as getter + if (value == null) { + return this.dom.leading; + } // act as setter + + + this.dom.leading = new SVG.Number(value); + return this.rebuild(); + }, + // Rebuild appearance type + rebuild: function rebuild(_rebuild) { + // store new rebuild flag if given + if (typeof _rebuild === 'boolean') { + this._rebuild = _rebuild; + } // define position of all lines + + + if (this._rebuild) { + var self = this; + var blankLineOffset = 0; + var dy = this.dom.leading * new SVG.Number(this.attr('font-size')); + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')); + + if (this.text() === '\n') { + blankLineOffset += dy; + } else { + this.attr('dy', dy + blankLineOffset); + blankLineOffset = 0; + } + } + }); + this.fire('rebuild'); + } + + return this; + }, + // Enable / disable build mode + build: function build(_build) { + this._build = !!_build; + return this; + }, + // overwrite method from parent to set data properly + setData: function setData(o) { + this.dom = o; + this.dom.leading = new SVG.Number(o.leading || 1.3); + return this; + } + }, + // Add parent method + construct: { + // Create text element + text: function text(_text2) { + return this.put(new SVG.Text()).text(_text2); + }, + // Create plain text element + plain: function plain(text) { + return this.put(new SVG.Text()).plain(text); + } + } +}); +SVG.Tspan = SVG.invent({ + // Initialize node + create: 'tspan', + // Inherit from + inherit: SVG.Parent, + // Add class methods + extend: { + // Set text content + text: function text(_text3) { + if (_text3 == null) return this.node.textContent + (this.dom.newLined ? '\n' : ''); + typeof _text3 === 'function' ? _text3.call(this, this) : this.plain(_text3); + return this; + }, + // Shortcut dx + dx: function dx(_dx) { + return this.attr('dx', _dx); + }, + // Shortcut dy + dy: function dy(_dy) { + return this.attr('dy', _dy); + }, + // Create new line + newLine: function newLine() { + // fetch text parent + var t = this.parent(SVG.Text); // mark new line + + this.dom.newLined = true; // apply new position + + return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()); + } + } +}); +SVG.extend([SVG.Text, SVG.Tspan], { + // Create plain text node + plain: function plain(text) { + // clear if build mode is disabled + if (this._build === false) { + this.clear(); + } // create text node + + + this.node.appendChild(document.createTextNode(text)); + return this; + }, + // Create a tspan + tspan: function tspan(text) { + var tspan = new SVG.Tspan(); // clear if build mode is disabled + + if (!this._build) { + this.clear(); + } // add new tspan + + + this.node.appendChild(tspan.node); + return tspan.text(text); + }, + // FIXME: Does this also work for textpath? + // Get length of text element + length: function length() { + return this.node.getComputedTextLength(); + } +}); +SVG.TextPath = SVG.invent({ + // Initialize node + create: 'textPath', + // Inherit from + inherit: SVG.Text, + // Define parent class + parent: SVG.Parent, + // Add parent method + extend: { + MorphArray: SVG.PathArray, + // return the array of the path track element + array: function array() { + var track = this.track(); + return track ? track.array() : null; + }, + // Plot path if any + plot: function plot(d) { + var track = this.track(); + var pathArray = null; + + if (track) { + pathArray = track.plot(d); + } + + return d == null ? pathArray : this; + }, + // Get the path element + track: function track() { + return this.reference('href'); + } + }, + construct: { + textPath: function textPath(text, path) { + return this.defs().path(path).text(text).addTo(this); + } + } +}); +SVG.extend([SVG.Text], { + // Create path for text to run on + path: function path(track) { + var path = new SVG.TextPath(); // if d is a path, reuse it + + if (!(track instanceof SVG.Path)) { + // create path element + track = this.doc().defs().path(track); + } // link textPath to path and add content + + + path.attr('href', '#' + track, SVG.xlink); // add textPath element as child node and return textPath + + return this.put(path); + }, + // Todo: make this plural? + // Get the textPath children + textPath: function textPath() { + return this.select('textPath'); + } +}); +SVG.extend([SVG.Path], { + // creates a textPath from this path + text: function text(_text4) { + if (_text4 instanceof SVG.Text) { + var txt = _text4.text(); + + return _text4.clear().path(this).text(txt); + } + + return this.parent().put(new SVG.Text()).path(this).text(_text4); + } // TODO: Maybe add `targets` to get all textPaths associated with this path + +}); +SVG.A = SVG.invent({ + // Initialize node + create: 'a', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Link url + to: function to(url) { + return this.attr('href', url, SVG.xlink); + }, + // Link target attribute + target: function target(_target) { + return this.attr('target', _target); + } + }, + // Add parent method + construct: { + // Create a hyperlink element + link: function link(url) { + return this.put(new SVG.A()).to(url); + } + } +}); +SVG.extend(SVG.Element, { + // Create a hyperlink element + linkTo: function linkTo(url) { + var link = new SVG.A(); + + if (typeof url === 'function') { + url.call(link, link); + } else { + link.to(url); + } + + return this.parent().put(link).put(this); + } +}); +SVG.Marker = SVG.invent({ + // Initialize node + create: 'marker', + // Inherit from + inherit: SVG.Container, + // Add class methods + extend: { + // Set width of element + width: function width(_width5) { + return this.attr('markerWidth', _width5); + }, + // Set height of element + height: function height(_height5) { + return this.attr('markerHeight', _height5); + }, + // Set marker refX and refY + ref: function ref(x, y) { + return this.attr('refX', x).attr('refY', y); + }, + // Update marker + update: function update(block) { + // remove all content + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + }, + // Return the fill id + toString: function toString() { + return 'url(#' + this.id() + ')'; + } + }, + // Add parent method + construct: { + marker: function marker(width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block); + } + } +}); +SVG.extend(SVG.Defs, { + // Create marker + marker: function marker(width, height, block) { + // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto + return this.put(new SVG.Marker()).size(width, height).ref(width / 2, height / 2).viewbox(0, 0, width, height).attr('orient', 'auto').update(block); + } +}); +SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], { + // Create and attach markers + marker: function marker(_marker, width, height, block) { + var attr = ['marker']; // Build attribute name + + if (_marker !== 'all') attr.push(_marker); + attr = attr.join('-'); // Set marker attribute + + _marker = arguments[1] instanceof SVG.Marker ? arguments[1] : this.doc().marker(width, height, block); + return this.attr(attr, _marker); + } +}); // Define list of available attributes for stroke and fill + +var sugar = { + stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], + fill: ['color', 'opacity', 'rule'], + prefix: function prefix(t, a) { + return a === 'color' ? t : t + '-' + a; + } // Add sugar for fill and stroke + +}; +['fill', 'stroke'].forEach(function (m) { + var extension = {}; + var i; + + extension[m] = function (o) { + if (typeof o === 'undefined') { + return this; + } + + if (typeof o === 'string' || SVG.Color.isRgb(o) || o && typeof o.fill === 'function') { + this.attr(m, o); + } else { + // set all attributes from sugar.fill and sugar.stroke list + for (i = sugar[m].length - 1; i >= 0; i--) { + if (o[sugar[m][i]] != null) { + this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); + } + } + } + + return this; + }; + + SVG.extend([SVG.Element, SVG.Timeline], extension); +}); +SVG.extend([SVG.Element, SVG.Timeline], { + // Let the user set the matrix directly + matrix: function matrix(mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new SVG.Matrix(this); + } // Act as a setter, the user can pass a matrix or a set of numbers + + + return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f)); + }, + // Map rotation to transform + rotate: function rotate(angle, cx, cy) { + return this.transform({ + rotate: angle, + ox: cx, + oy: cy + }, true); + }, + // Map skew to transform + skew: function skew(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + skew: x, + ox: y, + oy: cx + }, true) : this.transform({ + skew: [x, y], + ox: cx, + oy: cy + }, true); + }, + shear: function shear(lam, cx, cy) { + return this.transform({ + shear: lam, + ox: cx, + oy: cy + }, true); + }, + // Map scale to transform + scale: function scale(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + scale: x, + ox: y, + oy: cx + }, true) : this.transform({ + scale: [x, y], + ox: cx, + oy: cy + }, true); + }, + // Map translate to transform + translate: function translate(x, y) { + return this.transform({ + translate: [x, y] + }, true); + }, + // Map relative translations to transform + relative: function relative(x, y) { + return this.transform({ + relative: [x, y] + }, true); + }, + // Map flip to transform + flip: function flip(direction, around) { + var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both'; + var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0]; + this.transform({ + flip: directionString, + origin: origin + }, true); + }, + // Opacity + opacity: function opacity(value) { + return this.attr('opacity', value); + }, + // Relative move over x axis + dx: function dx(x) { + return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true); + }, + // Relative move over y axis + dy: function dy(y) { + return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true); + }, + // Relative move over x and y axes + dmove: function dmove(x, y) { + return this.dx(x).dy(y); + } +}); +SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], { + // Add x and y radius + radius: function radius(x, y) { + var type = (this._target || this).type; + return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVG.Number(x)) : this.rx(x).ry(y == null ? x : y); + } +}); +SVG.extend(SVG.Path, { + // Get path length + length: function length() { + return this.node.getTotalLength(); + }, + // Get point at length + pointAt: function pointAt(length) { + return new SVG.Point(this.node.getPointAtLength(length)); + } +}); +SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], { + // Set font + font: function font(a, v) { + if (_typeof(a) === 'object') { + for (v in a) { + this.font(v, a[v]); + } + } + + return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v); + } +}); +SVG.extend(SVG.Element, { + // Store data values on svg nodes + data: function data(a, v, r) { + if (_typeof(a) === 'object') { + for (v in a) { + this.data(v, a[v]); + } + } else if (arguments.length < 2) { + try { + return JSON.parse(this.attr('data-' + a)); + } catch (e) { + return this.attr('data-' + a); + } + } else { + this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v : JSON.stringify(v)); + } + + return this; + } +}); +SVG.extend(SVG.Element, { + // Remember arbitrary data + remember: function remember(k, v) { + // remember every item in an object individually + if (_typeof(arguments[0]) === 'object') { + for (var key in k) { + this.remember(key, k[key]); + } + } else if (arguments.length === 1) { + // retrieve memory + return this.memory()[k]; + } else { + // store memory + this.memory()[k] = v; + } + + return this; + }, + // Erase a given memory + forget: function forget() { + if (arguments.length === 0) { + this._memory = {}; + } else { + for (var i = arguments.length - 1; i >= 0; i--) { + delete this.memory()[arguments[i]]; + } + } + + return this; + }, + // Initialize or return local memory object + memory: function memory() { + return this._memory || (this._memory = {}); + } +}); +/* global idFromReference */ +// Method for getting an element by id + +SVG.get = function (id) { + var node = document.getElementById(idFromReference(id) || id); + return SVG.adopt(node); +}; // Select elements by query string + + +SVG.select = function (query, parent) { + return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { + return SVG.adopt(node); + }); +}; + +SVG.$$ = function (query, parent) { + return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { + return SVG.adopt(node); + }); +}; + +SVG.$ = function (query, parent) { + return SVG.adopt((parent || document).querySelector(query)); +}; + +SVG.extend(SVG.Parent, { + // Scoped select method + select: function select(query) { + return SVG.select(query, this.node); + } +}); +/* eslint no-unused-vars: 0 */ + +function createElement(element, makeNested) { + if (element instanceof SVG.Element) return element; + + if (_typeof(element) === 'object') { + return SVG.adopt(element); + } + + if (element == null) { + return new SVG.Doc(); + } + + if (typeof element === 'string' && element.charAt(0) !== '<') { + return SVG.adopt(document.querySelector(element)); + } + + var node = SVG.create('svg'); + node.innerHTML = element; + element = SVG.adopt(node.firstElementChild); + return element; +} + +function isNulledBox(box) { + return !box.w && !box.h && !box.x && !box.y; +} + +function domContains(node) { + return (document.documentElement.contains || function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode; + } + + return node === document; + }).call(document.documentElement, node); +} + +function pathRegReplace(a, b, c, d) { + return c + d.replace(SVG.regex.dots, ' .'); +} // creates deep clone of array + + +function arrayClone(arr) { + var clone = arr.slice(0); + + for (var i = clone.length; i--;) { + if (Array.isArray(clone[i])) { + clone[i] = arrayClone(clone[i]); + } + } + + return clone; +} // tests if a given element is instance of an object + + +function _is(el, obj) { + return el instanceof obj; +} // tests if a given selector matches an element + + +function _matches(el, selector) { + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); +} // Convert dash-separated-string to camelCase + + +function camelCase(s) { + return s.toLowerCase().replace(/-(.)/g, function (m, g) { + return g.toUpperCase(); + }); +} // Capitalize first letter of a string + + +function capitalize(s) { + return s.charAt(0).toUpperCase() + s.slice(1); +} // Ensure to six-based hex + + +function fullHex(hex) { + return hex.length === 4 ? ['#', hex.substring(1, 2), hex.substring(1, 2), hex.substring(2, 3), hex.substring(2, 3), hex.substring(3, 4), hex.substring(3, 4)].join('') : hex; +} // Component to hex value + + +function compToHex(comp) { + var hex = comp.toString(16); + return hex.length === 1 ? '0' + hex : hex; +} // Calculate proportional width and height values when necessary + + +function proportionalSize(element, width, height) { + if (width == null || height == null) { + var box = element.bbox(); + + if (width == null) { + width = box.width / box.height * height; + } else if (height == null) { + height = box.height / box.width * width; + } + } + + return { + width: width, + height: height + }; +} // Map matrix array to object + + +function arrayToMatrix(a) { + return { + a: a[0], + b: a[1], + c: a[2], + d: a[3], + e: a[4], + f: a[5] + }; +} // Add centre point to transform object + + +function ensureCentre(o, target) { + o.cx = o.cx == null ? target.bbox().cx : o.cx; + o.cy = o.cy == null ? target.bbox().cy : o.cy; +} // PathArray Helpers + + +function arrayToString(a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0]; + + if (a[i][1] != null) { + s += a[i][1]; + + if (a[i][2] != null) { + s += ' '; + s += a[i][2]; + + if (a[i][3] != null) { + s += ' '; + s += a[i][3]; + s += ' '; + s += a[i][4]; + + if (a[i][5] != null) { + s += ' '; + s += a[i][5]; + s += ' '; + s += a[i][6]; + + if (a[i][7] != null) { + s += ' '; + s += a[i][7]; + } + } + } + } + } + } + + return s + ' '; +} // Deep new id assignment + + +function assignNewId(node) { + // do the same for SVG child nodes as well + for (var i = node.children.length - 1; i >= 0; i--) { + assignNewId(node.children[i]); + } + + if (node.id) { + return SVG.adopt(node).id(SVG.eid(node.nodeName)); + } + + return SVG.adopt(node); +} // Add more bounding box properties + + +function fullBox(b) { + if (b.x == null) { + b.x = 0; + b.y = 0; + b.width = 0; + b.height = 0; + } + + b.w = b.width; + b.h = b.height; + b.x2 = b.x + b.width; + b.y2 = b.y + b.height; + b.cx = b.x + b.width / 2; + b.cy = b.y + b.height / 2; + return b; +} // Get id from reference string + + +function idFromReference(url) { + var m = (url || '').toString().match(SVG.regex.reference); + if (m) return m[1]; +} // Create matrix array for looping + + +var abcdef = 'abcdef'.split(''); + +function closeEnough(a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6); +} + +function isMatrixLike(o) { + return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; +} // TODO: Refactor this to a static function of matrix.js + + +function formatTransforms(o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true; + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; + var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; + var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; + var shear = o.shear || 0; + var theta = o.rotate || o.theta || 0; + var origin = new SVG.Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var ox = origin.x; + var oy = origin.y; + var position = new SVG.Point(o.position || o.px || o.positionX, o.py || o.positionY); + var px = position.x; + var py = position.y; + var translate = new SVG.Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var tx = translate.x; + var ty = translate.y; + var relative = new SVG.Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var rx = relative.x; + var ry = relative.y; // Populate all of the values + + return { + scaleX: scaleX, + scaleY: scaleY, + skewX: skewX, + skewY: skewY, + shear: shear, + theta: theta, + rx: rx, + ry: ry, + tx: tx, + ty: ty, + ox: ox, + oy: oy, + px: px, + py: py + }; +} // left matrix, right matrix, target matrix which is overwritten + + +function matrixMultiply(l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b; + var b = l.b * r.a + l.d * r.b; + var c = l.a * r.c + l.c * r.d; + var d = l.b * r.c + l.d * r.d; + var e = l.e + l.a * r.e + l.c * r.f; + var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same + + o.a = a; + o.b = b; + o.c = c; + o.d = d; + o.e = e; + o.f = f; + return o; +} + +function getOrigin(o, element) { + // Allow origin or around as the names + var origin = o.origin; // o.around == null ? o.origin : o.around + + var ox, oy; // Allow the user to pass a string to rotate around a given point + + if (typeof origin === 'string' || origin == null) { + // Get the bounding box of the element with no transformations applied + var string = (origin || 'center').toLowerCase().trim(); + + var _element$bbox = element.bbox(), + height = _element$bbox.height, + width = _element$bbox.width, + x = _element$bbox.x, + y = _element$bbox.y; // Calculate the transformed x and y coordinates + + + var bx = string.includes('left') ? x : string.includes('right') ? x + width : x + width / 2; + var by = string.includes('top') ? y : string.includes('bottom') ? y + height : y + height / 2; // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + + ox = o.ox != null ? o.ox : bx; + oy = o.oy != null ? o.oy : by; + } else { + ox = origin[0]; + oy = origin[1]; + } // Return the origin as it is if it wasn't a string + + + return [ox, oy]; +} +/* globals fullBox, domContains, isNulledBox, Exception */ + + +SVG.Box = SVG.invent({ + create: function create(source) { + var base = [0, 0, 0, 0]; + source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; + this.x = source[0]; + this.y = source[1]; + this.width = source[2]; + this.height = source[3]; // add center, right, bottom... + + fullBox(this); + }, + extend: { + // Merge rect box with another, return a new instance + merge: function merge(box) { + var x = Math.min(this.x, box.x); + var y = Math.min(this.y, box.y); + return new SVG.Box(x, y, Math.max(this.x + this.width, box.x + box.width) - x, Math.max(this.y + this.height, box.y + box.height) - y); + }, + transform: function transform(m) { + var xMin = Infinity; + var xMax = -Infinity; + var yMin = Infinity; + var yMax = -Infinity; + var pts = [new SVG.Point(this.x, this.y), new SVG.Point(this.x2, this.y), new SVG.Point(this.x, this.y2), new SVG.Point(this.x2, this.y2)]; + pts.forEach(function (p) { + p = p.transform(m); + xMin = Math.min(xMin, p.x); + xMax = Math.max(xMax, p.x); + yMin = Math.min(yMin, p.y); + yMax = Math.max(yMax, p.y); + }); + return new SVG.Box(xMin, yMin, xMax - xMin, yMax - yMin); + }, + addOffset: function addOffset() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset; + this.y += window.pageYOffset; + return this; + }, + toString: function toString() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + }, + toArray: function toArray() { + return [this.x, this.y, this.width, this.height]; + }, + morph: function morph(x, y, width, height) { + this.destination = new SVG.Box(x, y, width, height); + return this; + }, + at: function at(pos) { + if (!this.destination) return this; + return new SVG.Box(this.x + (this.destination.x - this.x) * pos, this.y + (this.destination.y - this.y) * pos, this.width + (this.destination.width - this.width) * pos, this.height + (this.destination.height - this.height) * pos); + } + }, + // Define Parent + parent: SVG.Element, + // Constructor + construct: { + // Get bounding box + bbox: function bbox() { + var box; + + try { + // find native bbox + box = this.node.getBBox(); + + if (isNulledBox(box) && !domContains(this.node)) { + throw new Exception('Element not in the dom'); + } + } catch (e) { + try { + var clone = this.clone(SVG.parser().svg).show(); + box = clone.node.getBBox(); + clone.remove(); + } catch (e) { + console.warn('Getting a bounding box of this element is not possible'); + } + } + + return new SVG.Box(box); + }, + rbox: function rbox(el) { + // IE11 throws an error when element not in dom + try { + var box = new SVG.Box(this.node.getBoundingClientRect()); + if (el) return box.transform(el.screenCTM().inverse()); + return box.addOffset(); + } catch (e) { + return new SVG.Box(); + } + } + } +}); +SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new SVG.Box(this.attr('viewBox')); // act as setter + + return this.attr('viewBox', new SVG.Box(x, y, width, height)); + } +}); + +SVG.parser = function () { + var b; + + if (!SVG.parser.nodes.svg.node.parentNode) { + b = document.body || document.documentElement; + SVG.parser.nodes.svg.addTo(b); + } + + return SVG.parser.nodes; +}; + +SVG.parser.nodes = { + svg: SVG().size(2, 0).css({ + opacity: 0, + position: 'absolute', + left: '-100%', + top: '-100%', + overflow: 'hidden' + }) +}; +SVG.parser.nodes.path = SVG.parser.nodes.svg.path().node; +/* global requestAnimationFrame */ + +SVG.Animator = { + nextDraw: null, + frames: new SVG.Queue(), + timeouts: new SVG.Queue(), + timer: window.performance || window.Date, + transforms: [], + frame: function frame(fn) { + // Store the node + var node = SVG.Animator.frames.push({ + run: fn + }); // Request an animation frame if we don't have one + + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw); + } // Return the node so we can remove it easily + + + return node; + }, + transform_frame: function transform_frame(fn, id) { + SVG.Animator.transforms[id] = fn; + }, + timeout: function timeout(fn, delay) { + delay = delay || 0; // Work out when the event should fire + + var time = SVG.Animator.timer.now() + delay; // Add the timeout to the end of the queue + + var node = SVG.Animator.timeouts.push({ + run: fn, + time: time + }); // Request another animation frame if we need one + + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw); + } + + return node; + }, + cancelFrame: function cancelFrame(node) { + SVG.Animator.frames.remove(node); + }, + clearTimeout: function clearTimeout(node) { + SVG.Animator.timeouts.remove(node); + }, + _draw: function _draw(now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null; + var lastTimeout = SVG.Animator.timeouts.last(); + + while (nextTimeout = SVG.Animator.timeouts.shift()) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run(); + } else { + SVG.Animator.timeouts.push(nextTimeout); + } // If we hit the last item, we should stop shifting out more items + + + if (nextTimeout === lastTimeout) break; + } // Run all of the animation frames + + + var nextFrame = null; + var lastFrame = SVG.Animator.frames.last(); + + while (nextFrame !== lastFrame && (nextFrame = SVG.Animator.frames.shift())) { + nextFrame.run(); + } + + SVG.Animator.transforms.forEach(function (el) { + el(); + }); // If we have remaining timeouts or frames, draw until we don't anymore + + SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first() ? requestAnimationFrame(SVG.Animator._draw) : null; + } +}; +SVG.Morphable = SVG.invent({ + create: function create(stepper) { + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new SVG.Ease('-'); + this._from = null; + this._to = null; + this._type = null; + this._context = null; + this._morphObj = null; + }, + extend: { + from: function from(val) { + if (val == null) { + return this._from; + } + + this._from = this._set(val); + return this; + }, + to: function to(val) { + if (val == null) { + return this._to; + } + + this._to = this._set(val); + return this; + }, + type: function type(_type) { + // getter + if (_type == null) { + return this._type; + } // setter + + + this._type = _type; + return this; + }, + _set: function _set(value) { + if (!this._type) { + var type = _typeof(value); + + if (type === 'number') { + this.type(SVG.Number); + } else if (type === 'string') { + if (SVG.Color.isColor(value)) { + this.type(SVG.Color); + } else if (SVG.regex.delimiter.test(value)) { + this.type(SVG.regex.pathLetters.test(value) ? SVG.PathArray : SVG.Array); + } else if (SVG.regex.numberAndUnit.test(value)) { + this.type(SVG.Number); + } else { + this.type(SVG.Morphable.NonMorphable); + } + } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor); + } else if (Array.isArray(value)) { + this.type(SVG.Array); + } else if (type === 'object') { + this.type(SVG.Morphable.ObjectBag); + } else { + this.type(SVG.Morphable.NonMorphable); + } + } + + var result = new this._type(value).toArray(); + this._morphObj = this._morphObj || new this._type(); + this._context = this._context || Array.apply(null, Array(result.length)).map(Object); + return result; + }, + stepper: function stepper(_stepper) { + if (_stepper == null) return this._stepper; + this._stepper = _stepper; + return this; + }, + done: function done() { + var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { + return last && curr; + }, true); + + return complete; + }, + at: function at(pos) { + var _this = this; + + return this._morphObj.fromArray(this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); + })); + } + } +}); +SVG.Morphable.NonMorphable = SVG.invent({ + create: function create(val) { + val = Array.isArray(val) ? val[0] : val; + this.value = val; + }, + extend: { + valueOf: function valueOf() { + return this.value; + }, + toArray: function toArray() { + return [this.value]; + } + } +}); +SVG.Morphable.TransformBag = SVG.invent({ + create: function create(obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + }; + } + + Object.assign(this, SVG.Morphable.TransformBag.defaults, obj); + }, + extend: { + toArray: function toArray() { + var v = this; + return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; + } + } +}); +SVG.Morphable.TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 +}; +SVG.Morphable.ObjectBag = SVG.invent({ + create: function create(objOrArr) { + this.values = []; + + if (Array.isArray(objOrArr)) { + this.values = objOrArr; + return; + } + + var entries = Object.entries(objOrArr || {}).sort(function (a, b) { + return a[0] - b[0]; + }); + this.values = entries.reduce(function (last, curr) { + return last.concat(curr); + }, []); + }, + extend: { + valueOf: function valueOf() { + var obj = {}; + var arr = this.values; + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1]; + } + + return obj; + }, + toArray: function toArray() { + return this.values; + } + } +}); +SVG.MorphableTypes = [SVG.Number, SVG.Color, SVG.Box, SVG.Matrix, SVG.Array, SVG.PointArray, SVG.PathArray, SVG.Morphable.NonMorphable, SVG.Morphable.TransformBag, SVG.Morphable.ObjectBag]; +SVG.extend(SVG.MorphableTypes, { + to: function to(val, args) { + return new SVG.Morphable().type(this.constructor).from(this.valueOf()).to(val, args); + }, + fromArray: function fromArray(arr) { + this.constructor(arr); + return this; + } +}); +/* global isMatrixLike getOrigin */ + +SVG.easing = { + '-': function _(pos) { + return pos; + }, + '<>': function _(pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5; + }, + '>': function _(pos) { + return Math.sin(pos * Math.PI / 2); + }, + '<': function _(pos) { + return -Math.cos(pos * Math.PI / 2) + 1; + } +}; +SVG.Runner = SVG.invent({ + parent: SVG.Element, + create: function create(options) { + // Store a unique id on the runner, so that we can identify it later + this.id = SVG.Runner.id++; // Ensure a default value + + options = options == null ? SVG.defaults.timeline.duration : options; // Ensure that we get a controller + + options = typeof options === 'function' ? new SVG.Controller(options) : options; // Declare all of the variables + + this._element = null; + this._timeline = null; + this.done = false; + this._queue = []; // Work out the stepper and the duration + + this._duration = typeof options === 'number' && options; + this._isDeclarative = options instanceof SVG.Controller; + this._stepper = this._isDeclarative ? options : new SVG.Ease(); // We copy the current values from the timeline because they can change + + this._history = {}; // Store the state of the runner + + this.enabled = true; + this._time = 0; + this._last = 0; + this.tags = {}; // Save transforms applied to this runner + + this.transforms = new SVG.Matrix(); + this.transformId = 1; // Looping variables + + this._haveReversed = false; + this._reverse = false; + this._loopsDone = 0; + this._swing = false; + this._wait = 0; + this._times = 1; + }, + construct: { + animate: function animate(duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when); + var timeline = this.timeline(); + return new SVG.Runner(o.duration).loop(o).element(this).timeline(timeline).schedule(delay, when); + }, + delay: function delay(by, when) { + return this.animate(0, by, when); + } + }, + extend: { + /*
+ Runner Definitions
+ ==================
+ These methods help us define the runtime behaviour of the Runner or they
+ help us make new runners from the current runner
+ */ + element: function element(_element3) { + if (_element3 == null) return this._element; + this._element = _element3; + + _element3._prepareRunner(); + + return this; + }, + timeline: function timeline(_timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof _timeline === 'undefined') return this._timeline; + this._timeline = _timeline; + return this; + }, + animate: function animate(duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when); + var runner = new SVG.Runner(o.duration); + if (this._timeline) runner.timeline(this._timeline); + if (this._element) runner.element(this._element); + return runner.loop(o).schedule(delay, when); + }, + schedule: function schedule(timeline, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline instanceof SVG.Timeline)) { + when = delay; + delay = timeline; + timeline = this.timeline(); + } // If there is no timeline, yell at the user... + + + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline'); + } // Schedule the runner on the timeline provided + + + timeline.schedule(this, delay, when); + return this; + }, + unschedule: function unschedule() { + var timeline = this.timeline(); + timeline && timeline.unschedule(this); + return this; + }, + loop: function loop(times, swing, wait) { + // Deal with the user passing in an object + if (_typeof(times) === 'object') { + swing = times.swing; + wait = times.wait; + times = times.times; + } // Sanitise the values and store them + + + this._times = times || Infinity; + this._swing = swing || false; + this._wait = wait || 0; + return this; + }, + delay: function delay(_delay) { + return this.animate(0, _delay); + }, + + /*
+ Basic Functionality
+ ===================
+ These methods allow us to attach basic functions to the runner directly
+ */ + queue: function queue(initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || SVG.void, + runner: runFn || SVG.void, + isTransform: isTransform, + initialised: false, + finished: false + }); + + var timeline = this.timeline(); + timeline && this.timeline()._continue(); + return this; + }, + during: function during(fn) { + return this.queue(null, fn); + }, + after: function after(fn) { + return this.on('finish', fn); + }, + + /*
+ Runner animation methods
+ ========================
+ Control how the animation plays
+ */ + time: function time(_time) { + if (_time == null) { + return this._time; + } + + var dt = _time - this._time; + this.step(dt); + return this; + }, + duration: function duration() { + return this._times * (this._wait + this._duration) - this._wait; + }, + loops: function loops(p) { + var loopDuration = this._duration + this._wait; + + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration); + var relativeTime = this._time - loopsDone * loopDuration; + var position = relativeTime / this._duration; + return Math.min(loopsDone + position, this._times); + } + + var whole = Math.floor(p); + var partial = p % 1; + var time = loopDuration * whole + this._duration * partial; + return this.time(time); + }, + position: function position(p) { + // Get all of the variables we need + var x = this._time; + var d = this._duration; + var w = this._wait; + var t = this._times; + var s = this._swing; + var r = this._reverse; + var position; + + if (p == null) { + /*
+ This function converts a time to a position in the range [0, 1]
+ The full explanation can be found in this desmos demonstration
+ https://www.desmos.com/calculator/u4fbavgche
+ The logic is slightly simplified here because we can use booleans
+ */ + // Figure out the value without thinking about the start or end time + var f = function f(x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); + var backwards = swinging && !r || !swinging && r; + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; + var clipped = Math.max(Math.min(uncliped, 1), 0); + return clipped; + }; // Figure out the value by incorporating the start time + + + var endTime = t * (w + d) - w; + position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); + return position; + } // Work out the loops done and add the position to the loops done + + + var loopsDone = Math.floor(this.loops()); + var swingForward = s && loopsDone % 2 === 0; + var forwards = swingForward && !r || r && swingForward; + position = loopsDone + (forwards ? p : 1 - p); + return this.loops(position); + }, + progress: function progress(p) { + if (p == null) { + return Math.min(1, this._time / this.duration()); + } + + return this.time(p * this.duration()); + }, + step: function step(dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this; // Update the time and get the new position + + dt = dt == null ? 16 : dt; + this._time += dt; + var position = this.position(); // Figure out if we need to run the stepper in this frame + + var running = this._lastPosition !== position && this._time >= 0; + this._lastPosition = position; // Figure out if we just started + + var duration = this.duration(); + var justStarted = this._lastTime < 0 && this._time > 0; + var justFinished = this._lastTime < this._time && this.time > duration; + this._lastTime = this._time; + + if (justStarted) {} // this.fire('start', this) + // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + + + var declarative = this._isDeclarative; + this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function + + if (running || declarative) { + this._initialise(running); // clear the transforms on this runner so they dont get added again and again + + + this.transforms = new SVG.Matrix(); + + var converged = this._run(declarative ? dt : position); // this.fire('step', this) + + } // correct the done flag here + // declaritive animations itself know when they converged + + + this.done = this.done || converged && declarative; // if (this.done) { + // this.fire('finish', this) + // } + + return this; + }, + finish: function finish() { + return this.step(Infinity); + }, + reverse: function reverse(_reverse) { + this._reverse = _reverse == null ? !this._reverse : _reverse; + return this; + }, + ease: function ease(fn) { + this._stepper = new SVG.Ease(fn); + return this; + }, + active: function active(enabled) { + if (enabled == null) return this.enabled; + this.enabled = enabled; + return this; + }, + + /*
+ Runner Management
+ =================
+ Functions that are used to help index the runner
+ */ + tag: function tag(name) { + // Act as a getter to get all of the tags on this object + if (name == null) return Object.keys(this.tags); // Add all of the tags to the object directly + + name = Array.isArray(name) ? name : [name]; + + for (var i = name.length; i--;) { + this.tags[name[i]] = true; + } + + return this; + }, + untag: function untag(name) { + name = Array.isArray(name) ? name : [name]; + + for (var i = name.length; i--;) { + delete this.tags[name[i]]; + } + + return this; + }, + getEventTarget: function getEventTarget() { + return this._dispatcher; + }, + + /*
+ Private Methods
+ ===============
+ Methods that shouldn't be used externally
+ */ + // Save a morpher to the morpher list so that we can retarget it later + _rememberMorpher: function _rememberMorpher(method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + }; + }, + // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + _tryRetarget: function _tryRetarget(method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + var index = this._queue.indexOf(this._history[method].caller); + + this._queue.splice(index, 1); + + return false; + } // for the case of transformations, we use the special retarget function + // which has access to the outer scope + + + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient + + } else { + this._history[method].morpher.to(target); + } + + this._history[method].caller.finished = false; + var timeline = this.timeline(); + timeline && timeline._continue(); + return true; + } + + return false; + }, + // Run each initialise function in the runner if required + _initialise: function _initialise(running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return; // Loop through all of the initialisers + + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i]; // Determine whether we need to initialise + + var needsIt = this._isDeclarative || !current.initialised && running; + running = !current.finished; // Call the initialiser if we need to + + if (needsIt && running) { + current.initialiser.call(this); + current.initialised = true; + } + } + }, + // Run each run function for the position or dt given + _run: function _run(positionOrDt) { + // Run all of the _queue directly + var allfinished = true; + + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + + var converged = current.runner.call(this, positionOrDt); + current.finished = current.finished || converged === true; + allfinished = allfinished && current.finished; + } // We report when all of the constructors are finished + + + return allfinished; + }, + addTransform: function addTransform(transform, index) { + this.transforms.lmultiplyO(transform); + return this; + }, + clearTransform: function clearTransform() { + this.transforms = new SVG.Matrix(); + return this; + } + } +}); +SVG.Runner.id = 0; + +SVG.Runner.sanitise = function (duration, delay, when) { + // Initialise the default parameters + var times = 1; + var swing = false; + var wait = 0; + duration = duration || SVG.defaults.timeline.duration; + delay = delay || SVG.defaults.timeline.delay; + when = when || 'last'; // If we have an object, unpack the values + + if (_typeof(duration) === 'object' && !(duration instanceof SVG.Stepper)) { + delay = duration.delay || delay; + when = duration.when || when; + swing = duration.swing || swing; + times = duration.times || times; + wait = duration.wait || wait; + duration = duration.duration || SVG.defaults.timeline.duration; + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + }; +}; + +SVG.FakeRunner = +/*#__PURE__*/ +function () { + function _class() { + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new SVG.Matrix(); + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + _classCallCheck(this, _class); + + this.transforms = transforms; + this.id = id; + this.done = done; + } + + return _class; +}(); + +SVG.extend([SVG.Runner, SVG.FakeRunner], { + mergeWith: function mergeWith(runner) { + return new SVG.FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); + } +}); // SVG.FakeRunner.emptyRunner = new SVG.FakeRunner() + +var lmultiply = function lmultiply(last, curr) { + return last.lmultiplyO(curr); +}; + +var getRunnerTransform = function getRunnerTransform(runner) { + return runner.transforms; +}; + +function mergeTransforms() { + // Find the matrix to apply to the element and apply it + var runners = this._transformationRunners.runners; + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new SVG.Matrix()); + this.transform(netTransform); + + this._transformationRunners.merge(); + + if (this._transformationRunners.length() === 1) { + this._frameId = null; + } +} + +var RunnerArray = +/*#__PURE__*/ +function () { + function RunnerArray() { + _classCallCheck(this, RunnerArray); + + this.runners = []; + this.ids = []; + } + + _createClass(RunnerArray, [{ + key: "add", + value: function add(runner) { + if (this.runners.includes(runner)) return; + var id = runner.id + 1; + var leftSibling = this.ids.reduce(function (last, curr) { + if (curr > last && curr < id) return curr; + return last; + }, 0); + var index = this.ids.indexOf(leftSibling) + 1; + this.ids.splice(index, 0, id); + this.runners.splice(index, 0, runner); + return this; + } + }, { + key: "getByID", + value: function getByID(id) { + return this.runners[this.ids.indexOf(id + 1)]; + } + }, { + key: "remove", + value: function remove(id) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1); + this.runners.splice(index, 1); + return this; + } + }, { + key: "merge", + value: function merge() { + var _this2 = this; + + var lastRunner = null; + this.runners.forEach(function (runner, i) { + if (lastRunner && runner.done && lastRunner.done) { + _this2.remove(runner.id); + + _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); + } + + lastRunner = runner; + }); + return this; + } + }, { + key: "edit", + value: function edit(id, newRunner) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1, id); + this.runners.splice(index, 1, newRunner); + return this; + } + }, { + key: "length", + value: function length() { + return this.ids.length; + } + }, { + key: "clearBefore", + value: function clearBefore(id) { + var deleteCnt = this.ids.indexOf(id + 1) || 1; + this.ids.splice(0, deleteCnt, 0); + this.runners.splice(0, deleteCnt, new SVG.FakeRunner()); + return this; + } + }]); + + return RunnerArray; +}(); + +SVG.extend(SVG.Element, { + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id); + }, + _currentTransform: function _currentTransform(current) { + return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter(function (runner) { + return runner.id <= current.id; + }).map(getRunnerTransform).reduce(lmultiply, new SVG.Matrix()); + }, + addRunner: function addRunner(runner) { + this._transformationRunners.add(runner); + + SVG.Animator.transform_frame(mergeTransforms.bind(this), this._frameId); + }, + _prepareRunner: function _prepareRunner() { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray().add(new SVG.FakeRunner(new SVG.Matrix(this))); + this._frameId = SVG.Element.frameId++; + } + } +}); +SVG.Element.frameId = 0; +SVG.extend(SVG.Runner, { + attr: function attr(a, v) { + return this.styleAttr('attr', a, v); + }, + // Add animatable styles + css: function css(s, v) { + return this.styleAttr('css', s, v); + }, + styleAttr: function styleAttr(type, name, val) { + // apply attributes individually + if (_typeof(name) === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]); + } + } + + var morpher = new SVG.Morphable(this._stepper).to(val); + this.queue(function () { + morpher = morpher.from(this.element()[type](name)); + }, function (pos) { + this.element()[type](name, morpher.at(pos)); + return morpher.done(); + }); + return this; + }, + zoom: function zoom(level, point) { + var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level)); + this.queue(function () { + morpher = morpher.from(this.zoom()); + }, function (pos) { + this.element().zoom(morpher.at(pos), point); + return morpher.done(); + }); + return this; + }, + + /**
+ ** absolute transformations
+ **/ + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + transform: function transform(transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative; + + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this; + } // Parse the parameters + + + var isMatrix = isMatrixLike(transforms); + affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type + + var morpher = new SVG.Morphable().type(affine ? SVG.Morphable.TransformBag : SVG.Matrix).stepper(this._stepper); + var origin; + var element; + var current; + var currentAngle; + var startTransform; + + function setup() { + // make sure element and origin is defined + element = element || this.element(); + origin = origin || getOrigin(transforms, element); + startTransform = new SVG.Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + + element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute + + if (!relative) { + element._clearTransformRunnersBefore(this); + } + } + + function run(pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform(); + + var _transform2 = new SVG.Point(origin).transform(element._currentTransform(this)), + x = _transform2.x, + y = _transform2.y; + + var target = new SVG.Matrix(_objectSpread({}, transforms, { + origin: [x, y] + })); + var start = this._isDeclarative && current ? current : startTransform; + + if (affine) { + target = target.decompose(x, y); + start = start.decompose(x, y); // Get the current and target angle as it was set + + var rTarget = target.rotate; + var rCurrent = start.rotate; // Figure out the shortest path to rotate directly + + var possibilities = [rTarget - 360, rTarget, rTarget + 360]; + var distances = possibilities.map(function (a) { + return Math.abs(a - rCurrent); + }); + var shortest = Math.min.apply(Math, _toConsumableArray(distances)); + var index = distances.indexOf(shortest); + target.rotate = possibilities[index]; + } + + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of SVG.Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0; + } + + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle; + } + } + + morpher.from(start); + morpher.to(target); + var affineParameters = morpher.at(pos); + currentAngle = affineParameters.rotate; + current = new SVG.Matrix(affineParameters); + this.addTransform(current); + return morpher.done(); + } + + function retarget(newTransforms) { + // only get a new origin if it changed since the last call + if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { + origin = getOrigin(transforms, element); + } // overwrite the old transformations with the new ones + + + transforms = _objectSpread({}, newTransforms, { + origin: origin + }); + } + + this.queue(setup, run, retarget); + this._isDeclarative && this._rememberMorpher('transform', morpher); + return this; + }, + // Animatable x-axis + x: function x(_x6, relative) { + return this._queueNumber('x', _x6); + }, + // Animatable y-axis + y: function y(_y6) { + return this._queueNumber('y', _y6); + }, + dx: function dx(x) { + return this._queueNumberDelta('dx', x); + }, + dy: function dy(y) { + return this._queueNumberDelta('dy', y); + }, + _queueNumberDelta: function _queueNumberDelta(method, to) { + to = new SVG.Number(to); // Try to change the target if we have this method already registerd + + if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation + + var morpher = new SVG.Morphable(this._stepper).to(to); + this.queue(function () { + var from = this.element()[method](); + morpher.from(from); + morpher.to(from + to); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + + this._rememberMorpher(method, morpher); + + return this; + }, + _queueObject: function _queueObject(method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation + + var morpher = new SVG.Morphable(this._stepper).to(to); + this.queue(function () { + morpher.from(this.element()[method]()); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + + this._rememberMorpher(method, morpher); + + return this; + }, + _queueNumber: function _queueNumber(method, value) { + return this._queueObject(method, new SVG.Number(value)); + }, + // Animatable center x-axis + cx: function cx(x) { + return this._queueNumber('cx', x); + }, + // Animatable center y-axis + cy: function cy(y) { + return this._queueNumber('cy', y); + }, + // Add animatable move + move: function move(x, y) { + return this.x(x).y(y); + }, + // Add animatable center + center: function center(x, y) { + return this.cx(x).cy(y); + }, + // Add animatable size + size: function size(width, height) { + // animate bbox based size for all other elements + var box; + + if (!width || !height) { + box = this._element.bbox(); + } + + if (!width) { + width = box.width / box.height * height; + } + + if (!height) { + height = box.height / box.width * width; + } + + return this.width(width).height(height); + }, + // Add animatable width + width: function width(_width6) { + return this._queueNumber('width', _width6); + }, + // Add animatable height + height: function height(_height6) { + return this._queueNumber('height', _height6); + }, + // Add animatable plot + plot: function plot(a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]); + } // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function + + + return this._queueObject('plot', new this._element.MorphArray(a)); + /*
+ var morpher = this._element.morphArray().to(a)
+ this.queue(function () {
+ morpher.from(this._element.array())
+ }, function (pos) {
+ this._element.plot(morpher.at(pos))
+ })
return this
- },
-
- at: function (pos) {
- if (!this.destination) return this
-
- return new SVG.Box(
- this.x + (this.destination.x - this.x) * pos
- , this.y + (this.destination.y - this.y) * pos
- , this.width + (this.destination.width - this.width) * pos
- , this.height + (this.destination.height - this.height) * pos
- )
- }
- },
-
- // Define Parent
- parent: SVG.Element,
-
- // Constructor
- construct: {
- // Get bounding box
- bbox: function () {
- var box
-
- try {
- // find native bbox
- box = this.node.getBBox()
-
- if (isNulledBox(box) && !domContains(this.node)) {
- throw new Exception('Element not in the dom')
- }
- } catch (e) {
- try {
- var clone = this.clone(SVG.parser().svg).show()
- box = clone.node.getBBox()
- clone.remove()
- } catch (e) {
- console.warn('Getting a bounding box of this element is not possible')
- }
- }
-
- return new SVG.Box(box)
- },
-
- rbox: function (el) {
- // IE11 throws an error when element not in dom
- try {
- var box = new SVG.Box(this.node.getBoundingClientRect())
- if (el) return box.transform(el.screenCTM().inverse())
- return box.addOffset()
- } catch (e) {
- return new SVG.Box()
- }
- }
- }
-})
-
-SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], {
- viewbox: function (x, y, width, height) {
- // act as getter
- if (x == null) return new SVG.Box(this.attr('viewBox'))
-
- // act as setter
- return this.attr('viewBox', new SVG.Box(x, y, width, height))
- }
-})
+ */ + }, + // Add leading method + leading: function leading(value) { + return this._queueNumber('leading', value); + }, + // Add animatable viewbox + viewbox: function viewbox(x, y, width, height) { + return this._queueObject('viewbox', new SVG.Box(x, y, width, height)); + }, + update: function update(o) { + if (_typeof(o) !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }); + } -
-SVG.parser = function () {
- var b
-
- if (!SVG.parser.nodes.svg.node.parentNode) {
- b = document.body || document.documentElement
- SVG.parser.nodes.svg.addTo(b)
- }
-
- return SVG.parser.nodes
-}
-
-SVG.parser.nodes = {
- svg: SVG().size(2, 0).css({
- opacity: 0,
- position: 'absolute',
- left: '-100%',
- top: '-100%',
- overflow: 'hidden'
- })
-}
-
-SVG.parser.nodes.path = SVG.parser.nodes.svg.path().node
-
+ if (o.opacity != null) this.attr('stop-opacity', o.opacity); + if (o.color != null) this.attr('stop-color', o.color); + if (o.offset != null) this.attr('offset', o.offset); + return this; + } +}); // Must Change .... + +SVG.easing = { + '-': function _(pos) { + return pos; + }, + '<>': function _(pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5; + }, + '>': function _(pos) { + return Math.sin(pos * Math.PI / 2); + }, + '<': function _(pos) { + return -Math.cos(pos * Math.PI / 2) + 1; + } +}; +var time = window.performance || Date; + +var makeSchedule = function makeSchedule(runnerInfo) { + var start = runnerInfo.start; + var duration = runnerInfo.runner.duration(); + var end = start + duration; + return { + start: start, + duration: duration, + end: end, + runner: runnerInfo.runner + }; +}; + +SVG.Timeline = SVG.invent({ + inherit: SVG.EventTarget, + // Construct a new timeline on the given element + create: function create() { + this._timeSource = function () { + return time.now(); + }; + + this._dispatcher = document.createElement('div'); // Store the timing variables + + this._startTime = 0; + this._speed = 1.0; // Play control variables control how the animation proceeds + + this._reverse = false; + this._persist = 0; // Keep track of the running animations and their starting parameters + + this._nextFrame = null; + this._paused = false; + this._runners = []; + this._order = []; + this._time = 0; + this._lastSourceTime = 0; + this._lastStepTime = 0; + }, + extend: { + getEventTarget: function getEventTarget() { + return this._dispatcher; + }, + + /**
+ *
+ */ + // schedules a runner on the timeline + schedule: function schedule(runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return a.start - b.start || a.duration - b.duration; + }); + } + + if (!this.active()) { + this._step(); + + if (when == null) { + when = 'now'; + } + } // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + + + var absoluteStartTime = 0; + delay = delay || 0; // Work out when to start the animation + + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime; + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay; + delay = 0; + } else if (when === 'now') { + absoluteStartTime = this._time; + } else if (when === 'relative') { + var runnerInfo = this._runners[runner.id]; + + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay; + delay = 0; + } + } else { + throw new Error('Invalid value for the "when" parameter'); + } // Manage runner + + + runner.unschedule(); + runner.timeline(this); + runner.time(-delay); // Save startTime for next runner + + this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime // Save order and continue + + }; + + this._order.push(runner.id); + + this._continue(); + + return this; + }, + // Remove the runner from this timeline + unschedule: function unschedule(runner) { + var index = this._order.indexOf(runner.id); + + if (index < 0) return this; + delete this._runners[runner.id]; + + this._order.splice(index, 1); + + runner.timeline(null); + return this; + }, + play: function play() { + // Now make sure we are not paused and continue the animation + this._paused = false; + return this._continue(); + }, + pause: function pause() { + // Cancel the next animation frame and pause + this._nextFrame = null; + this._paused = true; + return this; + }, + stop: function stop() { + // Cancel the next animation frame and go to start + this.seek(-this._time); + return this.pause(); + }, + finish: function finish() { + this.seek(Infinity); + return this.pause(); + }, + speed: function speed(_speed) { + if (_speed == null) return this._speed; + this._speed = _speed; + return this; + }, + reverse: function reverse(yes) { + var currentSpeed = this.speed(); + if (yes == null) return this.speed(-currentSpeed); + var positive = Math.abs(currentSpeed); + return this.speed(yes ? positive : -positive); + }, + seek: function seek(dt) { + this._time += dt; + return this._continue(); + }, + time: function time(_time2) { + if (_time2 == null) return this._time; + this._time = _time2; + return this; + }, + persist: function persist(dtOrForever) { + if (dtOrForever == null) return this._persist; + this._persist = dtOrForever; + return this; + }, + source: function source(fn) { + if (fn == null) return this._timeSource; + this._timeSource = fn; + return this; + }, + _step: function _step() { + // If the timeline is paused, just do nothing + if (this._paused) return; // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + + var time = this._timeSource(); + + var dtSource = time - this._lastSourceTime; + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); + this._lastSourceTime = time; // Update the time + + this._time += dtTime; + this._lastStepTime = this._time; // this.fire('time', this._time) + // Run all of the runners directly + + var runnersLeft = false; + + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]]; + var runner = runnerInfo.runner; + var dt = dtTime; // Make sure that we give the actual difference + // between runner start time and now + + var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet + + if (dtToStart < 0) { + runnersLeft = true; + continue; + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart; + } + + if (!runner.active()) continue; // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + + var finished = runner.step(dt).done; + + if (!finished) { + runnersLeft = true; // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time; + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]]; + this._order.splice(i--, 1) && --len; + runner.timeline(null); + } + } + } // Get the next animation frame to keep the simulation going + + + if (runnersLeft) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)); + } else { + this._nextFrame = null; + } + + return this; + }, + // Checks if we are running and continues the animation + _continue: function _continue() { + if (this._paused) return this; + + if (!this._nextFrame) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)); + } + + return this; + }, + active: function active() { + return !!this._nextFrame; + } + }, + // These methods will be added to all SVG.Element objects + parent: SVG.Element, + construct: { + timeline: function timeline() { + this._timeline = this._timeline || new SVG.Timeline(); + return this._timeline; + } + } +}); // c = { +// finished: Whether or not we are finished +// } + +/***
+Base Class
+==========
+The base stepper class that will be
+***/ + +function makeSetterGetter(k, f) { + return function (v) { + if (v == null) return this[v]; + this[k] = v; + if (f) f.call(this); + return this; + }; +} + +SVG.Stepper = SVG.invent({ + create: function create() {} +}); +/***
+Easing Functions
+================
+***/ + +SVG.Ease = SVG.invent({ + inherit: SVG.Stepper, + create: function create(fn) { + SVG.Stepper.call(this, fn); + this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn; + }, + extend: { + step: function step(from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to; + } + + return from + (to - from) * this.ease(pos); + }, + done: function done(dt, c) { + return false; + } + } +}); +SVG.easing = { + '-': function _(pos) { + return pos; + }, + '<>': function _(pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5; + }, + '>': function _(pos) { + return Math.sin(pos * Math.PI / 2); + }, + '<': function _(pos) { + return -Math.cos(pos * Math.PI / 2) + 1; + }, + bezier: function bezier(t0, x0, t1, x1) { + return function (t) {// TODO: FINISH + }; + } + /***
+ Controller Types
+ ================
+ ***/ + +}; +SVG.Controller = SVG.invent({ + inherit: SVG.Stepper, + create: function create(fn) { + SVG.Stepper.call(this, fn); + this.stepper = fn; + }, + extend: { + step: function step(current, target, dt, c) { + return this.stepper(current, target, dt, c); + }, + done: function done(c) { + return c.done; + } + } +}); + +function recalculate() { + // Apply the default parameters + var duration = (this._duration || 500) / 1000; + var overshoot = this._overshoot || 0; // Calculate the PID natural response + + var eps = 1e-10; + var pi = Math.PI; + var os = Math.log(overshoot / 100 + eps); + var zeta = -os / Math.sqrt(pi * pi + os * os); + var wn = 3.9 / (zeta * duration); // Calculate the Spring values + + this.d = 2 * zeta * wn; + this.k = wn * wn; +} + +SVG.Spring = SVG.invent({ + inherit: SVG.Controller, + create: function create(duration, overshoot) { + this.duration(duration || 500).overshoot(overshoot || 0); + }, + extend: { + step: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + if (dt > 100) dt = 16; + dt /= 1000; // Get the previous velocity + + var velocity = c.velocity || 0; // Apply the control to get the new position and store it + + var acceleration = -this.d * velocity - this.k * (current - target); + var newPosition = current + velocity * dt + acceleration * dt * dt / 2; // Store the velocity + + c.velocity = velocity + acceleration * dt; // Figure out if we have converged, and if so, pass the value + + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002; + return c.done ? target : newPosition; + }, + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) + } +}); +SVG.PID = SVG.invent({ + inherit: SVG.Controller, + create: function create(p, i, d, windup) { + SVG.Controller.call(this); + p = p == null ? 0.1 : p; + i = i == null ? 0.01 : i; + d = d == null ? 0 : d; + windup = windup == null ? 1000 : windup; + this.p(p).i(i).d(d).windup(windup); + }, + extend: { + step: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + var p = target - current; + var i = (c.integral || 0) + p * dt; + var d = (p - (c.error || 0)) / dt; + var windup = this.windup; // antiwindup + + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)); + } + + c.error = p; + c.integral = i; + c.done = Math.abs(p) < 0.001; + return c.done ? target : current + (this.P * p + this.I * i + this.D * d); + }, + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') + } +});
return SVG
-}));
\ No newline at end of file +}));
+//# sourceMappingURL=svg.js.map diff --git a/dist/svg.min.js b/dist/svg.min.js deleted file mode 100644 index d644e90..0000000 --- a/dist/svg.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! svg.js v3.0.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function n(t,n){if(t instanceof P.Element)return t;if("object"==typeof t)return P.adopt(t);if(null==t)return new P.Doc;if("string"==typeof t&&"<"!==t.charAt(0))return P.adopt(e.querySelector(t));var i=P.create("svg");return i.innerHTML=t,t=P.adopt(i.firstElementChild)}function i(t){return!(t.w||t.h||t.x||t.y)}function r(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===e}).call(e.documentElement,t)}function s(t,e,n,i){return n+i.replace(P.regex.dots," .")}function o(t){for(var e=t.slice(0),n=e.length;n--;)Array.isArray(e[n])&&(e[n]=o(e[n]));return e}function a(t,e){return t instanceof e}function h(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function u(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function l(t){return t.charAt(0).toUpperCase()+t.slice(1)}function c(t){return 4===t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t}function f(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function d(t,e,n){if(null==e||null==n){var i=t.bbox();null==e?e=i.width/i.height*n:null==n&&(n=i.height/i.width*e)}return{width:e,height:n}}function p(t,e,n){return{x:e*t.a+n*t.c+0,y:e*t.b+n*t.d+0}}function m(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function x(t){return t instanceof P.Matrix||(t=new P.Matrix(t)),t}function y(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function v(t){for(var e=0,n=t.length,i="";e<n;e++)i+=t[e][0],null!=t[e][1]&&(i+=t[e][1],null!=t[e][2]&&(i+=" ",i+=t[e][2],null!=t[e][3]&&(i+=" ",i+=t[e][3],i+=" ",i+=t[e][4],null!=t[e][5]&&(i+=" ",i+=t[e][5],i+=" ",i+=t[e][6],null!=t[e][7]&&(i+=" ",i+=t[e][7])))));return i+" "}function g(t){for(var e=t.children.length-1;e>=0;e--)g(t.children[e]);return t.id?P.adopt(t).id(P.eid(t.nodeName)):P.adopt(t)}function w(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function b(t){var e=(t||"").toString().match(P.regex.reference);if(e)return e[1]}if(!e.createElementNS||!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect)return{supported:!1};var P=this.SVG=function(t){if(P.supported)return t=n(t)};P.supported=!0,P.ns="http://www.w3.org/2000/svg",P.xmlns="http://www.w3.org/2000/xmlns/",P.xlink="http://www.w3.org/1999/xlink",P.svgjs="http://svgjs.com/svgjs",P.did=1e3,P.eid=function(t){return"Svgjs"+l(t)+P.did++},P.create=function(t){return e.createElementNS(this.ns,t)},P.extend=function(t,e){var n,i;for(t=Array.isArray(t)?t:[t],i=t.length-1;i>=0;i--)if(t[i])for(n in e)t[i].prototype[n]=e[n]},P.invent=function(t){var e="function"==typeof t.create?t.create:function(e){this.constructor(e||P.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&P.extend(e,t.extend),t.construct&&P.extend(t.parent||P.Container,t.construct),e},P.adopt=function(e){if(!e)return null;if(e.instance instanceof P.Element)return e.instance;if(!(e instanceof t.SVGElement))return new P.HtmlNode(e);return"svg"===e.nodeName?new P.Doc(e):"linearGradient"===e.nodeName||"radialGradient"===e.nodeName?new P.Gradient(e):P[l(e.nodeName)]?new(P[l(e.nodeName)])(e):new P.Parent(e)},P.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},P.utils={map:function(t,e){var n,i=t.length,r=[];for(n=0;n<i;n++)r.push(e(t[n]));return r},filter:function(t,e){var n,i=t.length,r=[];for(n=0;n<i;n++)e(t[n])&&r.push(t[n]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},P.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},P.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?P.regex.isRgb.test(t)?(e=P.regex.rgb.exec(t.replace(P.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):P.regex.isHex.test(t)&&(e=P.regex.hex.exec(c(t)),this.r=parseInt(e[1],16),this.g=parseInt(e[2],16),this.b=parseInt(e[3],16)):"object"==typeof t&&(this.r=t.r,this.g=t.g,this.b=t.b))},P.extend(P.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+f(this.r)+f(this.g)+f(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new P.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new P.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),P.Color.test=function(t){return t+="",P.regex.isHex.test(t)||P.regex.isRgb.test(t)},P.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},P.Color.isColor=function(t){return P.Color.isRgb(t)||P.Color.test(t)},P.Array=function(t,e){t=(t||[]).valueOf(),0===t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},P.extend(P.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!==this.destination.length){for(var e=this.value[this.value.length-1],n=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(n);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,n=[];t<e;t++)-1===n.indexOf(this.value[t])&&n.push(this.value[t]);return this.value=n,n},at:function(t){if(!this.destination)return this;for(var e=0,n=this.value.length,i=[];e<n;e++)i.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new P.Array(i)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(P.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=o(this.value),t}}),P.PointArray=function(t,e){P.Array.call(this,t,e||[[0,0]])},P.PointArray.prototype=new P.Array,P.PointArray.prototype.constructor=P.PointArray,P.extend(P.PointArray,{toString:function(){for(var t=0,e=this.value.length,n=[];t<e;t++)n.push(this.value[t].join(","));return n.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,n=this.value.length,i=[];e<n;e++)i.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new P.PointArray(i)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(P.regex.delimiter).map(parseFloat);t.length%2!=0&&t.pop();for(var n=0,i=t.length;n<i;n+=2)e.push([t[n],t[n+1]]);return e},move:function(t,e){var n=this.bbox();if(t-=n.x,e-=n.y,!isNaN(t)&&!isNaN(e))for(var i=this.value.length-1;i>=0;i--)this.value[i]=[this.value[i][0]+t,this.value[i][1]+e];return this},size:function(t,e){var n,i=this.bbox();for(n=this.value.length-1;n>=0;n--)i.width&&(this.value[n][0]=(this.value[n][0]-i.x)*t/i.width+i.x),i.height&&(this.value[n][1]=(this.value[n][1]-i.y)*e/i.height+i.y);return this},bbox:function(){var t=-1/0,e=-1/0,n=1/0,i=1/0;return this.value.forEach(function(r){t=Math.max(r[0],t),e=Math.max(r[1],e),n=Math.min(r[0],n),i=Math.min(r[1],i)}),{x:n,y:i,width:t-n,height:e-i}}});for(var M={M:function(t,e,n){return e.x=n.x=t[0],e.y=n.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,n){return e.x=n.x,e.y=n.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},A="mlhvqtcsaz".split(""),N=0,C=A.length;N<C;++N)M[A[N]]=function(t){return function(e,n,i){if("H"===t)e[0]=e[0]+n.x;else if("V"===t)e[0]=e[0]+n.y;else if("A"===t)e[5]=e[5]+n.x,e[6]=e[6]+n.y;else for(var r=0,s=e.length;r<s;++r)e[r]=e[r]+(r%2?n.y:n.x);return M[t](e,n,i)}}(A[N].toUpperCase());P.PathArray=function(t,e){P.Array.call(this,t,e||[["M",0,0]])},P.PathArray.prototype=new P.Array,P.PathArray.prototype.constructor=P.PathArray,P.extend(P.PathArray,{toString:function(){return v(this.value)},move:function(t,e){var n=this.bbox();if(t-=n.x,e-=n.y,!isNaN(t)&&!isNaN(e))for(var i,r=this.value.length-1;r>=0;r--)i=this.value[r][0],"M"===i||"L"===i||"T"===i?(this.value[r][1]+=t,this.value[r][2]+=e):"H"===i?this.value[r][1]+=t:"V"===i?this.value[r][1]+=e:"C"===i||"S"===i||"Q"===i?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"===i&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"===i&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var n,i,r=this.bbox();for(n=this.value.length-1;n>=0;n--)i=this.value[n][0],"M"===i||"L"===i||"T"===i?(this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x,this.value[n][2]=(this.value[n][2]-r.y)*e/r.height+r.y):"H"===i?this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x:"V"===i?this.value[n][1]=(this.value[n][1]-r.y)*e/r.height+r.y:"C"===i||"S"===i||"Q"===i?(this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x,this.value[n][2]=(this.value[n][2]-r.y)*e/r.height+r.y,this.value[n][3]=(this.value[n][3]-r.x)*t/r.width+r.x,this.value[n][4]=(this.value[n][4]-r.y)*e/r.height+r.y,"C"===i&&(this.value[n][5]=(this.value[n][5]-r.x)*t/r.width+r.x,this.value[n][6]=(this.value[n][6]-r.y)*e/r.height+r.y)):"A"===i&&(this.value[n][1]=this.value[n][1]*t/r.width,this.value[n][2]=this.value[n][2]*e/r.height,this.value[n][6]=(this.value[n][6]-r.x)*t/r.width+r.x,this.value[n][7]=(this.value[n][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,n,i;for(t=new P.PathArray(t),i=this.value.length===t.value.length,e=0,n=this.value.length;i&&e<n;e++)i=this.value[e][0]===t.value[e][0];return i},morph:function(t){return t=new P.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,n,i,r,s=this.value,o=this.destination.value,a=[],h=new P.PathArray;for(e=0,n=s.length;e<n;e++){for(a[e]=[s[e][0]],i=1,r=s[e].length;i<r;i++)a[e][i]=s[e][i]+(o[e][i]-s[e][i])*t;"A"===a[e][0]&&(a[e][4]=+(0!==a[e][4]),a[e][5]=+(0!==a[e][5]))}return h.value=a,h},parse:function(t){if(t instanceof P.PathArray)return t.valueOf();var e,n={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7,Z:0};t="string"==typeof t?t.replace(P.regex.numbersWithDots,s).replace(P.regex.pathLetters," $& ").replace(P.regex.hyphen,"$1 -").trim().split(P.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var i=[],r=new P.Point,o=new P.Point,a=0,h=t.length;do{P.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"===e?e="L":"m"===e&&(e="l"),i.push(M[e].call(null,t.slice(a,a+=n[e.toUpperCase()]).map(parseFloat),r,o))}while(h>a);return i},bbox:function(){return P.parser().path.setAttribute("d",this.toString()),P.parser.nodes.path.getBBox()}}),P.Number=P.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(P.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof P.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new P.Number(t),new P.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new P.Number(t),new P.Number(this-t,this.unit||t.unit)},times:function(t){return t=new P.Number(t),new P.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new P.Number(t),new P.Number(this/t,this.unit||t.unit)},to:function(t){var e=new P.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new P.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new P.Number(this.destination).minus(this).times(t).plus(this):this}}}),P.HtmlNode=P.invent({create:function(t){this.node=t},extend:{add:function(t,e){return t=n(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t}}}),P.Element=P.invent({create:function(t){this.events={},this.dom={},this.node=t,this.node&&(this.type=t.nodeName,this.node.instance=this,this.events=t.events||{},t.hasAttribute("svgjs:data")&&this.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}))},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var n=d(this,t,e);return this.width(new P.Number(n.width)).height(new P.Number(n.height))},clone:function(t){this.writeDataToDom();var e=g(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return n(t).put(this)},putIn:function(t){return n(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=P.eid(this.type)),this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t<n.x+n.width&&e<n.y+n.height},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},visible:function(){return"none"!==this.css("display")},toString:function(){return this.id()},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(P.regex.delimiter)},hasClass:function(t){return-1!==this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!==t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return P.get(this.attr(t))},parent:function(e){var n=this;if(!n.node.parentNode)return null;if(n=P.adopt(n.node.parentNode),!e)return n;for(;n&&n.node instanceof t.SVGElement;){if("string"==typeof e?n.matches(e):n instanceof e)return n;n=P.adopt(n.node.parentNode)}},doc:function(){var t=this.parent(P.Doc);return t&&t.doc()},defs:function(){return this.doc().defs()},parents:function(t){var e=[],n=this;do{if(!(n=n.parent(t))||!n.node)break;e.push(n)}while(n.parent);return e},matches:function(t){return h(this.node,t)},native:function(){return this.node},svg:function(t){var n,i;if(!(t&&this instanceof P.Parent))return this.writeDataToDom(),this.node.outerHTML;for(n=e.createElementNS(P.ns,"svg"),n.innerHTML=t,i=n.children.length;i--;)this.node.appendChild(n.firstElementChild);return this},writeDataToDom:function(){return this.is(P.Parent)&&this.each(function(){this.writeDataToDom()}),this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return a(this,t)}}}),P.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},P.morph=function(t){return function(e,n){return new P.MorphObj(e,n).at(t)}},P.Situation=P.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new P.Number(t.duration).valueOf(),this.delay=new P.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),P.FX=P.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,n){"object"==typeof t&&(e=t.ease,n=t.delay,t=t.duration);var i=new P.Situation({duration:t||1e3,delay:n||0,ease:P.easing[e||"-"]||e});return this.queue(i),this},delay:function(t){var e=new P.Situation({duration:t,delay:0,ease:P.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof P.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof P.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof P.Situation?this.start():this.situation(this)),this},initAnimations:function(){var t,e,n,i=this.situation;if(i.init)return this;for(t in i.animations)for(n=this.target()[t](),Array.isArray(n)||(n=[n]),Array.isArray(i.animations[t])||(i.animations[t]=[i.animations[t]]),e=n.length;e--;)i.animations[t][e]instanceof P.Number&&(n[e]=new P.Number(n[e])),i.animations[t][e]=n[e].morph(i.animations[t][e]);for(t in i.attrs)i.attrs[t]=new P.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new P.MorphObj(this.target().css(t),i.styles[t]);return i.initialTransformation=this.target().matrixify(),i.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var n=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!n&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return!0===this.situation.loops&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var n=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*n,this.situation.finish=this.situation.start+n,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var n=this.last();return n.loops=null==t||t,n.loop=0,e&&(n.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return e.reversed=void 0===t?!e.reversed:t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){function e(i){i.detail.situation===n&&(t.call(this,n),this.off("finished.fx",e))}var n=this.last();return this.target().on("finished.fx",e),this._callStart()},during:function(t){function e(e){e.detail.situation===n&&t.call(this,e.detail.pos,P.morph(e.detail.pos),e.detail.eased,n)}var n=this.last();return this.target().off("during.fx",e).on("during.fx",e),this.after(function(){this.off("during.fx",e)}),this._callStart()},afterAll:function(t){var e=function e(n){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,P.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,n){return this.last()[n||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops){var e,n,i;e=Math.max(this.absPos,0),n=Math.floor(e),!0===this.situation.loops||n<this.situation.loops?(this.pos=e-n,i=this.situation.loop,this.situation.loop=n):(this.absPos=this.situation.loops,this.pos=1,i=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!==Boolean((this.situation.loop-i)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1===this.pos&&!this.situation.reversed||this.situation.reversed&&0===this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,n,i=this,r=this.target(),s=this.situation;for(t in s.animations)n=[].concat(s.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(i.pos),i.pos):t}),r[t].apply(r,n);for(t in s.attrs)n=[t].concat(s.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(i.pos),i.pos):t}),r.attr.apply(r,n);for(t in s.styles)n=[t].concat(s.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(i.pos),i.pos):t}),r.css.apply(r,n);if(s.transforms.length){for(n=s.initialTransformation,t=0,e=s.transforms.length;t<e;t++){var o=s.transforms[t];o instanceof P.Matrix?n=o.relative?n.multiply((new P.Matrix).morph(o).at(s.ease(this.pos))):n.morph(o).at(s.ease(this.pos)):(o.relative||o.undo(n.extract()),n=n.multiply(o.at(s.ease(this.pos))))}r.matrix(n)}return this},once:function(t,e,n){var i=this.last();return n||(t=i.ease(t)),i.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:P.Element,construct:{animate:function(t,e,n){return(this.fx||(this.fx=new P.FX(this))).animate(t,e,n)},delay:function(t){return(this.fx||(this.fx=new P.FX(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),P.MorphObj=P.invent({create:function(t,e){return P.Color.isColor(e)?new P.Color(t).morph(e):P.regex.delimiter.test(t)?new P.Array(t).morph(e):P.regex.numberAndUnit.test(e)?new P.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),P.extend(P.FX,{attr:function(t,e,n){if("object"==typeof t)for(var i in t)this.attr(i,t[i]);else this.add(t,e,"attrs");return this},css:function(t,e){if("object"==typeof t)for(var n in t)this.css(n,t[n]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof P.G)return this.transform({x:t},e),this;var n=new P.Number(t);return n.relative=e,this.add("x",n)},y:function(t,e){if(this.target()instanceof P.G)return this.transform({y:t},e),this;var n=new P.Number(t);return n.relative=e,this.add("y",n)},cx:function(t){return this.add("cx",new P.Number(t))},cy:function(t){return this.add("cy",new P.Number(t))},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){if(this.target()instanceof P.Text)this.attr("font-size",t);else{var n;t&&e||(n=this.target().bbox()),t||(t=n.width/n.height*e),e||(e=n.height/n.width*t),this.add("width",new P.Number(t)).add("height",new P.Number(e))}return this},width:function(t){return this.add("width",new P.Number(t))},height:function(t){return this.add("height",new P.Number(t))},plot:function(t,e,n,i){return 4===arguments.length?this.plot([t,e,n,i]):this.add("plot",new(this.target().MorphArray)(t))},leading:function(t){return this.target().leading?this.add("leading",new P.Number(t)):this},viewbox:function(t,e,n,i){return this.target()instanceof P.Container&&this.add("viewbox",new P.Box(t,e,n,i)),this},update:function(t){if(this.target()instanceof P.Stop){if("number"==typeof t||t instanceof P.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),P.Matrix=P.invent({create:function(t){var e,n=m([1,0,0,1,0,0]);for(t=t instanceof P.Element?t.matrixify():"string"==typeof t?m(t.split(P.regex.delimiter).map(parseFloat)):6===arguments.length?m([].slice.call(arguments)):Array.isArray(t)?m(t):"object"==typeof t?t:n,e=S.length-1;e>=0;--e)this[S[e]]=null!=t[S[e]]?t[S[e]]:n[S[e]]},extend:{extract:function(){var t=p(this,0,1),e=p(this,1,0),n=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(n*Math.PI/180)+this.f*Math.sin(n*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(n*Math.PI/180)+this.e*Math.sin(-n*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-n,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:n,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new P.Matrix(this)}},clone:function(){return new P.Matrix(this)},morph:function(t){return this.destination=new P.Matrix(t),this},at:function(t){return this.destination?new P.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t}):this},multiply:function(t){return new P.Matrix(this.native().multiply(x(t).native()))},inverse:function(){return new P.Matrix(this.native().inverse())},translate:function(t,e){return new P.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,n,i){return 1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t),this.around(n,i,new P.Matrix(t,0,0,e,0,0))},rotate:function(t,e,n){return t=P.utils.radians(t),this.around(e,n,new P.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return"x"===t?this.scale(-1,1,e,0):"y"===t?this.scale(1,-1,0,e):this.scale(-1,-1,t,null!=e?e:t)},skew:function(t,e,n,i){return 1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t),t=P.utils.radians(t),e=P.utils.radians(e),this.around(n,i,new P.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,n){return this.skew(t,0,e,n)},skewY:function(t,e,n){return this.skew(0,t,e,n)},around:function(t,e,n){return this.multiply(new P.Matrix(1,0,0,1,t||0,e||0)).multiply(n).multiply(new P.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=P.parser.nodes.svg.node.createSVGMatrix(),e=S.length-1;e>=0;e--)t[S[e]]=this[S[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:P.Element,construct:{ctm:function(){return new P.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof P.Doc&&!this.isRoot()){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new P.Matrix(e)}return new P.Matrix(this.node.getScreenCTM())}}}),P.Point=P.invent({create:function(t,e){var n,i={x:0,y:0};n=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:i,this.x=n.x,this.y=n.y},extend:{clone:function(){return new P.Point(this)},morph:function(t,e){return this.destination=new P.Point(t,e),this},at:function(t){return this.destination?new P.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t}):this},native:function(){var t=P.parser.nodes.svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new P.Point(this.native().matrixTransform(t.native()))}}}),P.extend(P.Element,{point:function(t,e){return new P.Point(t,e).transform(this.screenCTM().inverse())}}),P.extend(P.Element,{attr:function(t,e,n){if(null==t){for(t={},e=this.node.attributes,n=e.length-1;n>=0;n--)t[e[n].nodeName]=P.regex.isNumber.test(e[n].nodeValue)?parseFloat(e[n].nodeValue):e[n].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return e=this.node.getAttribute(t),null==e?P.defaults.attrs[t]:P.regex.isNumber.test(e)?parseFloat(e):e;"fill"!==t&&"stroke"!==t||(P.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof P.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new P.Number(e):P.Color.isColor(e)?e=new P.Color(e):Array.isArray(e)&&(e=new P.Array(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof n?this.node.setAttributeNS(n,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild(t,e)}return this}}),P.extend(P.Element,{transform:function(t,e){var n,i,r=this -;if("object"!=typeof t)return n=new P.Matrix(r).extract(),"string"==typeof t?n[t]:n;if(n=new P.Matrix(r),e=!!e||!!t.relative,null!=t.a)n=e?n.multiply(new P.Matrix(t)):new P.Matrix(t);else if(null!=t.rotation)y(t,r),n=e?n.rotate(t.rotation,t.cx,t.cy):n.rotate(t.rotation-n.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(y(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,!e){var s=n.extract();t.scaleX=1*t.scaleX/s.scaleX,t.scaleY=1*t.scaleY/s.scaleY}n=n.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(y(t,r),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var o=n.extract();n=n.multiply((new P.Matrix).skew(o.skewX,o.skewY,o.cx,o.cy).inverse())}n=n.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?("x"===t.flip||"y"===t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(i=r.bbox(),t.flip=i.cx,t.offset=i.cy):t.flip=t.offset,n=(new P.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(e?n=n.translate(t.x,t.y):(null!=t.x&&(n.e=t.x),null!=t.y&&(n.f=t.y)));return this.attr("transform",n)}}),P.extend(P.FX,{transform:function(t,e){var n,i,r=this.target();return"object"!=typeof t?(n=new P.Matrix(r).extract(),"string"==typeof t?n[t]:n):(e=!!e||!!t.relative,null!=t.a?n=new P.Matrix(t):null!=t.rotation?(y(t,r),n=new P.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(y(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,n=new P.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(y(t,r),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,n=new P.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?("x"===t.flip||"y"===t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(i=r.bbox(),t.flip=i.cx,t.offset=i.cy):t.flip=t.offset,n=(new P.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(n=new P.Translate(t.x,t.y)),n?(n.relative=e,this.last().transforms.push(n),this._callStart()):this)}}),P.extend(P.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(P.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(P.regex.delimiter).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"===e[0]?t.multiply(m(e[1])):t[e[0]].apply(t,e[1])},new P.Matrix)},toParent:function(t){if(this===t)return this;var e=this.screenCTM(),n=t.screenCTM().inverse();return this.addTo(t).untransform().transform(n.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),P.Transformation=P.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.bind(this)([].slice.call(arguments));var n,i;if(Array.isArray(t))for(n=0,i=this.arguments.length;n<i;++n)this[this.arguments[n]]=t[n];else if("object"==typeof t)for(n=0,i=this.arguments.length;n<i;++n)this[this.arguments[n]]=t[this.arguments[n]];this.inversed=!1,!0===e&&(this.inversed=!0)},extend:{arguments:[],method:"",at:function(t){for(var e=[],n=0,i=this.arguments.length;n<i;++n)e.push(this[this.arguments[n]]);var r=this._undo||new P.Matrix;return r=(new P.Matrix).morph(P.Matrix.prototype[this.method].apply(r,e)).at(t),this.inversed?r.inverse():r},undo:function(t){for(var e=0,n=this.arguments.length;e<n;++e)t[this.arguments[e]]=void 0===this[this.arguments[e]]?0:t[this.arguments[e]];return t.cx=this.cx,t.cy=this.cy,this._undo=new(P[l(this.method)])(t,!0).at(1),this}}}),P.Translate=P.invent({parent:P.Matrix,inherit:P.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["transformedX","transformedY"],method:"translate"}}),P.Rotate=P.invent({parent:P.Matrix,inherit:P.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["rotation","cx","cy"],method:"rotate",at:function(t){var e=(new P.Matrix).rotate((new P.Number).morph(this.rotation-(this._undo?this._undo.rotation:0)).at(t),this.cx,this.cy);return this.inversed?e.inverse():e},undo:function(t){return this._undo=t,this}}}),P.Scale=P.invent({parent:P.Matrix,inherit:P.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["scaleX","scaleY","cx","cy"],method:"scale"}}),P.Skew=P.invent({parent:P.Matrix,inherit:P.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["skewX","skewY","cx","cy"],method:"skew"}}),P.extend(P.Element,{css:function(t,e){var n,i,r={};if(0===arguments.length)return this.node.style.cssText.split(/\s*;\s*/).filter(function(t){return!!t.length}).forEach(function(t){n=t.split(/\s*:\s*/),r[n[0]]=n[1]}),r;if(arguments.length<2){if(Array.isArray(t)){for(i=t.length;i--;)r[u(t[i])]=this.node.style[u(t[i])];return r}if("string"==typeof t)return this.node.style[u(t)];if("object"==typeof t)for(i in t)this.node.style[u(i)]=null==t[i]||P.regex.isBlank.test(t[i])?"":t[i]}return 2===arguments.length&&(this.node.style[u(t)]=null==e||P.regex.isBlank.test(e)?"":e),this}}),P.Parent=P.invent({create:function(t){this.constructor(t)},inherit:P.Element,extend:{children:function(){return P.utils.map(this.node.children,function(t){return P.adopt(t)})},add:function(t,e){return t=n(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t.instance||t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.children).indexOf(t.node)},get:function(t){return P.adopt(this.node.children[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.children.length-1)},each:function(t,e){var n,i,r=this.children();for(n=0,i=r.length;n<i;n++)r[n]instanceof P.Element&&t.apply(r[n],[n,r]),e&&r[n]instanceof P.Parent&&r[n].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this}}}),P.extend(P.Parent,{flatten:function(t){return this instanceof P.G||this instanceof P.Doc?(t=t||(this instanceof P.Doc&&this.isRoot()?this:this.parent(P.Parent)),this.each(function(){return this instanceof P.Defs?this:this instanceof P.Parent?this.flatten(t):this.toParent(t)}),this.node.firstElementChild||this.remove(),this):this},ungroup:function(t){return this instanceof P.G||this instanceof P.Doc&&!this.isRoot()?(t=t||this.parent(P.Parent),this.each(function(){return this.toParent(t)}),this.remove(),this):this}}),P.Container=P.invent({create:function(t){this.constructor(t)},inherit:P.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){P.Element.prototype[t]=function(e){return P.on(this,t,e),this}}),P.listenerId=0,P.on=function(t,e,n,i,r){var s=n.bind(i||t),o=t instanceof P.Element?t.node:t;o.instance=o.instance||{events:{}};var a=o.instance.events;n._svgjsListenerId||(n._svgjsListenerId=++P.listenerId),e.split(P.regex.delimiter).forEach(function(t){var e=t.split(".")[0],i=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][i]=a[e][i]||{},a[e][i][n._svgjsListenerId]=s,o.addEventListener(e,s,r||!1)})},P.off=function(t,e,n,i){var r=t instanceof P.Element?t.node:t;if(r.instance&&("function"!=typeof n||(n=n._svgjsListenerId))){var s=r.instance.events;(e||"").split(P.regex.delimiter).forEach(function(t){var e,o,a=t&&t.split(".")[0],h=t&&t.split(".")[1];if(n)s[a]&&s[a][h||"*"]&&(r.removeEventListener(a,s[a][h||"*"][n],i||!1),delete s[a][h||"*"][n]);else if(a&&h){if(s[a]&&s[a][h]){for(o in s[a][h])P.off(r,[a,h].join("."),o);delete s[a][h]}}else if(h)for(t in s)for(e in s[t])h===e&&P.off(r,[t,h].join("."));else if(a){if(s[a]){for(e in s[a])P.off(r,[a,e].join("."));delete s[a]}}else{for(t in s)P.off(r,t);r.instance.events={}}})}},P.extend(P.Element,{on:function(t,e,n,i){return P.on(this,t,e,n,i),this},off:function(t,e){return P.off(this.node,t,e),this},dispatch:function(e,n){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:n,cancelable:!0})),e},fire:function(t,e){return this.dispatch(t,e),this}}),P.Defs=P.invent({create:"defs",inherit:P.Container}),P.G=P.invent({create:"g",inherit:P.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new P.G)}}}),P.extend(P.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},prev:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof P.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof P.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&this.parent().removeElement(this).add(this,0),this},before:function(t){t.remove();var e=this.position();return this.parent().add(t,e),this},after:function(t){t.remove();var e=this.position();return this.parent().add(t,e+1),this}}),P.Mask=P.invent({create:"mask",inherit:P.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),P.Element.prototype.remove.call(this)},targets:function(){return P.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new P.Mask)}}}),P.extend(P.Element,{maskWith:function(t){var e=t instanceof P.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.id()+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),P.ClipPath=P.invent({create:"clipPath",inherit:P.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),P.Element.prototype.remove.call(this)},targets:function(){return P.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new P.ClipPath)}}}),P.extend(P.Element,{clipWith:function(t){var e=t instanceof P.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),P.Gradient=P.invent({create:function(t){this.constructor("object"==typeof t?t:P.create(t+"Gradient"))},inherit:P.Container,extend:{stop:function(t,e,n){return this.put(new P.Stop).update(t,e,n)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},url:function(){return"url(#"+this.id()+")"},toString:function(){return this.url()},attr:function(t,e,n){return"transform"===t&&(t="gradientTransform"),P.Container.prototype.attr.call(this,t,e,n)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),P.extend([P.Gradient,P.FX],{from:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({fx:new P.Number(t),fy:new P.Number(e)}):this.attr({x1:new P.Number(t),y1:new P.Number(e)})},to:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({cx:new P.Number(t),cy:new P.Number(e)}):this.attr({x2:new P.Number(t),y2:new P.Number(e)})}}),P.extend(P.Defs,{gradient:function(t,e){return this.put(new P.Gradient(t)).update(e)}}),P.Stop=P.invent({create:"stop",inherit:P.Element,extend:{update:function(t){return("number"==typeof t||t instanceof P.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new P.Number(t.offset)),this}}}),P.Pattern=P.invent({create:"pattern",inherit:P.Container,extend:{url:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.url()},attr:function(t,e,n){return"transform"===t&&(t="patternTransform"),P.Container.prototype.attr.call(this,t,e,n)}},construct:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}}}),P.extend(P.Defs,{pattern:function(t,e,n){return this.put(new P.Pattern).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),P.Doc=P.invent({create:function(t){this.constructor(t||P.create("svg")),this.namespace()},inherit:P.Container,extend:{isRoot:function(){return!(this.node.parentNode&&this.node.parentNode instanceof t.SVGElement&&"#document"!==this.node.parentNode.nodeName)},doc:function(){return this.isRoot()?this:P.Element.prototype.doc.call(this)},namespace:function(){return this.isRoot()?this.attr({xmlns:P.ns,version:"1.1"}).attr("xmlns:xlink",P.xlink,P.xmlns).attr("xmlns:svgjs",P.svgjs,P.xmlns):this.doc().namespace()},defs:function(){return this.isRoot()?P.adopt(this.node.getElementsByTagName("defs")[0])||this.put(new P.Defs):this.doc().defs()},parent:function(t){return this.isRoot()?"#document"===this.node.parentNode.nodeName?null:this.node.parentNode:P.Element.prototype.parent.call(this,t)},remove:function(){return this.isRoot()?(this.parent()&&this.parent().removeChild(this.node),this):P.Element.prototype.remove.call(this)},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this}},construct:{nested:function(){return this.put(new P.Doc)}}}),P.Shape=P.invent({create:function(t){this.constructor(t)},inherit:P.Element}),P.Bare=P.invent({create:function(t,e){if(this.constructor(P.create(t)),e)for(var n in e.prototype)"function"==typeof e.prototype[n]&&(this[n]=e.prototype[n])},inherit:P.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),P.extend(P.Parent,{element:function(t,e){return this.put(new P.Bare(t,e))}}),P.Symbol=P.invent({create:"symbol",inherit:P.Container,construct:{symbol:function(){return this.put(new P.Symbol)}}}),P.Use=P.invent({create:"use",inherit:P.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,P.xlink)}},construct:{use:function(t,e){return this.put(new P.Use).element(t,e)}}}),P.Rect=P.invent({create:"rect",inherit:P.Shape,construct:{rect:function(t,e){return this.put(new P.Rect).size(t,e)}}}),P.Circle=P.invent({create:"circle",inherit:P.Shape,construct:{circle:function(t){return this.put(new P.Circle).rx(new P.Number(t).divide(2)).move(0,0)}}}),P.extend([P.Circle,P.FX],{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),P.Ellipse=P.invent({create:"ellipse",inherit:P.Shape,construct:{ellipse:function(t,e){return this.put(new P.Ellipse).size(t,e).move(0,0)}}}),P.extend([P.Ellipse,P.Rect,P.FX],{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),P.extend([P.Circle,P.Ellipse],{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new P.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new P.Number(t).divide(2))},size:function(t,e){var n=d(this,t,e);return this.rx(new P.Number(n.width).divide(2)).ry(new P.Number(n.height).divide(2))}}),P.Line=P.invent({create:"line",inherit:P.Shape,extend:{array:function(){return new P.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,n,i){return null==t?this.array():(t=void 0!==e?{x1:t,y1:e,x2:n,y2:i}:new P.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var n=d(this,t,e);return this.attr(this.array().size(n.width,n.height).toLine())}},construct:{line:function(t,e,n,i){return P.Line.prototype.plot.apply(this.put(new P.Line),null!=t?[t,e,n,i]:[0,0,0,0])}}}),P.Polyline=P.invent({create:"polyline",inherit:P.Shape,construct:{polyline:function(t){return this.put(new P.Polyline).plot(t||new P.PointArray)}}}),P.Polygon=P.invent({create:"polygon",inherit:P.Shape,construct:{polygon:function(t){return this.put(new P.Polygon).plot(t||new P.PointArray)}}}),P.extend([P.Polyline,P.Polygon],{array:function(){return this._array||(this._array=new P.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new P.PointArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var n=d(this,t,e);return this.attr("points",this.array().size(n.width,n.height))}}),P.extend([P.Line,P.Polyline,P.Polygon],{MorphArray:P.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),P.Path=P.invent({create:"path",inherit:P.Shape,extend:{MorphArray:P.PathArray,array:function(){return this._array||(this._array=new P.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new P.PathArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var n=d(this,t,e);return this.attr("d",this.array().size(n.width,n.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new P.Path).plot(t||new P.PathArray)}}}),P.Image=P.invent({create:"image",inherit:P.Shape,extend:{load:function(e,n){if(!e)return this;var i=new t.Image;return P.on(i,"load",function(t){var r=this.parent(P.Pattern);0===this.width()&&0===this.height()&&this.size(i.width,i.height),r instanceof P.Pattern&&0===r.width()&&0===r.height()&&r.size(this.width(),this.height()),"function"==typeof n&&n.call(this,{width:i.width,height:i.height,ratio:i.width/i.height,url:e})},this),P.on(i,"load error",function(){P.off(i)}),this.attr("href",i.src=e,P.xlink)}},construct:{image:function(t,e){return this.put(new P.Image).size(0,0).load(t,e)}}}),P.Text=P.invent({create:function(t){this.constructor(t||P.create("text")),this.dom.leading=new P.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",P.defaults.attrs["font-family"])},inherit:P.Parent,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},text:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i<r;++i)"textPath"!==e[i].nodeName?(i!==n&&3!==e[i].nodeType&&!0===P.adopt(e[i]).dom.newLined&&(t+="\n"),t+=e[i].textContent):0===i&&(n=1);return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var s=0,o=t.length;s<o;s++)this.tspan(t[s]).newLine()}return this.build(!1).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new P.Number(t),this.rebuild())},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,n=0,i=this.dom.leading*new P.Number(this.attr("font-size"));this.each(function(){this.dom.newLined&&(this.attr("x",e.attr("x")),"\n"===this.text()?n+=i:(this.attr("dy",i+n),n=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new P.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new P.Text).text(t)},plain:function(t){return this.put(new P.Text).plain(t)}}}),P.Tspan=P.invent({create:"tspan",inherit:P.Parent,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(P.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),P.extend([P.Text,P.Tspan],{plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=new P.Tspan;return this._build||this.clear(),this.node.appendChild(e.node),e.text(t)},length:function(){return this.node.getComputedTextLength()}}),P.TextPath=P.invent({create:"textPath",inherit:P.Text,parent:P.Parent,extend:{MorphArray:P.PathArray,array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),n=null;return e&&(n=e.plot(t)),null==t?n:this},track:function(){return this.reference("href")}},construct:{textPath:function(t,e){return this.defs().path(e).text(t).addTo(this)}}}),P.extend([P.Text],{path:function(t){var e=new P.TextPath;return t instanceof P.Path||(t=this.doc().defs().path(t)),e.attr("href","#"+t,P.xlink),this.put(e)},textPath:function(){return this.select("textPath")}}),P.extend([P.Path],{text:function(t){if(t instanceof P.Text){var e=t.text();return t.clear().path(this).text(e)}return this.parent().put(new P.Text).path(this).text(t)}}),P.A=P.invent({create:"a",inherit:P.Container,extend:{to:function(t){return this.attr("href",t,P.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new P.A).to(t)}}}),P.extend(P.Element,{linkTo:function(t){var e=new P.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),P.Marker=P.invent({create:"marker",inherit:P.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,n){return this.defs().marker(t,e,n)}}}),P.extend(P.Defs,{marker:function(t,e,n){return this.put(new P.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(n)}}),P.extend([P.Line,P.Polyline,P.Polygon,P.Path],{marker:function(t,e,n,i){var r=["marker"];return"all"!==t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof P.Marker?arguments[1]:this.doc().marker(e,n,i),this.attr(r,t)}});var k={stroke:["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],fill:["color","opacity","rule"],prefix:function(t,e){return"color"===e?t:t+"-"+e}};["fill","stroke"].forEach(function(t){var e,n={};n[t]=function(n){if(void 0===n)return this;if("string"==typeof n||P.Color.isRgb(n)||n&&"function"==typeof n.fill)this.attr(t,n);else for(e=k[t].length-1;e>=0;e--)null!=n[k[t][e]]&&this.attr(k.prefix(t,k[t][e]),n[k[t][e]]);return this},P.extend([P.Element,P.FX],n)}),P.extend([P.Element,P.FX],{rotate:function(t,e,n){return this.transform({rotation:t,cx:e,cy:n})},skew:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({skew:t,cx:e,cy:n}):this.transform({skewX:t,skewY:e,cx:n,cy:i})},scale:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({scale:t,cx:e,cy:n}):this.transform({scaleX:t,scaleY:e,cx:n,cy:i})},translate:function(t,e){return this.transform({x:t,y:e})},flip:function(t,e){return e="number"==typeof t?t:e,this.transform({flip:t||"both",offset:e})},matrix:function(t){return this.attr("transform",new P.Matrix(6===arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new P.Number(t).plus(this instanceof P.FX?0:this.x()),!0)},dy:function(t){return this.y(new P.Number(t).plus(this instanceof P.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),P.extend([P.Rect,P.Ellipse,P.Circle,P.Gradient,P.FX],{radius:function(t,e){var n=(this._target||this).type;return"radialGradient"===n||"radialGradient"===n?this.attr("r",new P.Number(t)):this.rx(t).ry(null==e?t:e)}}),P.extend(P.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new P.Point(this.node.getPointAtLength(t))}}),P.extend([P.Parent,P.Text,P.Tspan,P.FX],{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"===t?this.leading(e):"anchor"===t?this.attr("text-anchor",e):"size"===t||"family"===t||"weight"===t||"stretch"===t||"variant"===t||"style"===t?this.attr("font-"+t,e):this.attr(t,e)}}),P.extend(P.Element,{data:function(t,e,n){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:!0===n||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this}}),P.extend(P.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var n in t)this.remember(n,t[n]);else{if(1===arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0===arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),P.get=function(t){var n=e.getElementById(b(t)||t);return P.adopt(n)},P.select=function(t,n){return P.utils.map((n||e).querySelectorAll(t),function(t){return P.adopt(t)})},P.$$=function(t,n){return P.utils.map((n||e).querySelectorAll(t),function(t){return P.adopt(t)})},P.$=function(t,n){return P.adopt((n||e).querySelector(t))},P.extend(P.Parent,{select:function(t){return P.select(t,this.node)}});var S="abcdef".split("");return P.Box=P.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(P.regex.delimiter).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):e,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],w(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new P.Box(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)},transform:function(t){var e=1/0,n=-1/0,i=1/0,r=-1/0;return[new P.Point(this.x,this.y),new P.Point(this.x2,this.y),new P.Point(this.x,this.y2),new P.Point(this.x2,this.y2)].forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),n=Math.max(n,s.x),i=Math.min(i,s.y),r=Math.max(r,s.y)}),new P.Box(e,i,n-e,r-i)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,n,i){return this.destination=new P.Box(t,e,n,i),this},at:function(t){return this.destination?new P.Box(this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t):this}},parent:P.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),i(t)&&!r(this.node))throw new Exception("Element not in the dom")}catch(n){try{var e=this.clone(P.parser().svg).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new P.Box(t)},rbox:function(t){try{var e=new P.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new P.Box}}}}),P.extend([P.Doc,P.Symbol,P.Image,P.Pattern,P.Marker,P.ForeignObject,P.View],{viewbox:function(t,e,n,i){return null==t?new P.Box(this.attr("viewBox")):this.attr("viewBox",new P.Box(t,e,n,i))}}),P.parser=function(){var t;return P.parser.nodes.svg.node.parentNode||(t=e.body||e.documentElement,P.parser.nodes.svg.addTo(t)),P.parser.nodes},P.parser.nodes={svg:P().size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"})},P.parser.nodes.path=P.parser.nodes.svg.path().node,P});
\ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index d96451b..0f140f9 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,9 @@ var del = require('del'), uglify = require('gulp-uglify'),
wrapUmd = require('gulp-wrap'),
pkg = require('./package.json'),
- standard = require('gulp-standard')
+ standard = require('gulp-standard'),
+ babel = require('gulp-babel'),
+ sourcemaps = require('gulp-sourcemaps')
var headerLong = ['/*!',
'* <%= pkg.name %> - <%= pkg.description %>',
@@ -31,14 +33,16 @@ var parts = [ 'src/regex.js',
'src/utilities.js',
'src/default.js',
+ 'src/queue.js',
+ 'src/drawLoop.js',
'src/color.js',
'src/array.js',
'src/pointarray.js',
'src/patharray.js',
'src/number.js',
+ 'src/event.js',
'src/HtmlNode.js',
'src/element.js',
- 'src/fx.js',
'src/matrix.js',
'src/point.js',
'src/attr.js',
@@ -47,7 +51,6 @@ var parts = [ 'src/parent.js',
'src/flatten.js',
'src/container.js',
- 'src/event.js',
'src/defs.js',
'src/group.js',
'src/arrange.js',
@@ -79,33 +82,45 @@ var parts = [ 'src/helpers.js',
'src/polyfill.js',
'src/boxes.js',
- 'src/parser.js'
+ 'src/parser.js',
+ 'src/animator.js',
+ 'src/morph.js',
+ 'src/runner.js',
+ 'src/timeline.js',
+ 'src/controller.js'
]
gulp.task('clean', function () {
return del([ 'dist/*' ])
})
+gulp.task('lint', function () {
+ return gulp.src(parts)
+ .pipe(standard())
+ .pipe(standard.reporter('default', {
+ showRuleNames: true,
+ breakOnError: process.argv[2] !== "--dont-break",
+ quiet: true,
+ }))
+})
+
/**
* Compile everything in /src to one unified file in the order defined in the MODULES constant
* wrap the whole thing in a UMD wrapper (@see https://github.com/umdjs/umd)
* add the license information to the header plus the build time stamp
*/
-gulp.task('unify', ['clean'], function () {
+gulp.task('unify', ['clean', 'lint'], function () {
pkg.buildDate = Date()
return gulp.src(parts)
- .pipe(standard())
- .pipe(standard.reporter('default', {
- showRuleNames: true,
- breakOnError: true,
- quiet: true
- }))
+ .pipe(sourcemaps.init())
.pipe(concat('svg.js', { newLine: '\n' }))
+ .pipe(babel({presets: ['@babel/env']}))
// wrap the whole thing in an immediate function call
.pipe(wrapUmd({src: 'src/umd.js'}))
.pipe(header(headerLong, { pkg: pkg }))
.pipe(trim({ leading: false }))
.pipe(chmod(0o644))
+ .pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist'))
.pipe(size({ showFiles: true, title: 'Full' }))
})
diff --git a/package-lock.json b/package-lock.json index 96d4bac..e4be3b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,911 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.2.tgz", + "integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.2", + "@babel/helpers": "^7.1.2", + "@babel/parser": "^7.1.2", + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.1.2", + "convert-source-map": "^1.1.0", + "debug": "^3.1.0", + "json5": "^0.5.0", + "lodash": "^4.17.10", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "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" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.3.tgz", + "integrity": "sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ==", + "dev": true, + "requires": { + "@babel/types": "^7.1.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", + "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-define-map": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", + "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.0.0", + "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 + } + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", + "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", + "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0", + "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 + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", + "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", + "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 + } + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", + "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-wrap-function": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz", + "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helpers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.2.tgz", + "integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.1.2" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.3.tgz", + "integrity": "sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz", + "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.0.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz", + "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.0.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", + "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz", + "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz", + "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.2.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz", + "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz", + "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz", + "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz", + "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz", + "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz", + "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz", + "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz", + "integrity": "sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "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 + } + } + }, + "@babel/plugin-transform-classes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", + "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz", + "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.3.tgz", + "integrity": "sha512-Mb9M4DGIOspH1ExHOUnn2UUXFOyVTiX84fXCd+6B5iWrQg/QMeeRmSwpZ9lnjYLSXtZwiw80ytVMr3zue0ucYw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz", + "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz", + "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz", + "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz", + "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz", + "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz", + "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz", + "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz", + "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.1.3.tgz", + "integrity": "sha512-PvTxgjxQAq4pvVUZF3mD5gEtVDuId8NtWkJsZLEJZMZAW3TvgQl1pmydLLN1bM8huHFVVU43lf0uvjQj9FRkKw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz", + "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", + "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz", + "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz", + "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", + "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.13.3" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", + "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz", + "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz", + "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz", + "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz", + "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz", + "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/preset-env": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.0.tgz", + "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.1.0", + "@babel/plugin-proposal-json-strings": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", + "@babel/plugin-syntax-async-generators": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.1.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.1.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-dotall-regex": "^7.0.0", + "@babel/plugin-transform-duplicate-keys": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.1.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.1.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-amd": "^7.1.0", + "@babel/plugin-transform-modules-commonjs": "^7.1.0", + "@babel/plugin-transform-modules-systemjs": "^7.0.0", + "@babel/plugin-transform-modules-umd": "^7.1.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.1.0", + "@babel/plugin-transform-parameters": "^7.1.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typeof-symbol": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "browserslist": "^4.1.0", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.4.tgz", + "integrity": "sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.3", + "@babel/types": "^7.1.3", + "debug": "^3.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "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" + } + }, + "globals": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "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 + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.3.tgz", + "integrity": "sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, + "dependencies": { + "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 + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -16,14 +921,14 @@ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.11", "negotiator": "0.6.1" } }, "acorn": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", - "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", "dev": true }, "acorn-jsx": { @@ -32,7 +937,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -50,15 +955,13 @@ "dev": true }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ajv-keywords": { @@ -73,9 +976,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" }, "dependencies": { "kind-of": { @@ -84,7 +987,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -101,7 +1004,7 @@ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "ansi-wrap": "0.1.0" + "ansi-wrap": "^0.1.0" } }, "ansi-escapes": { @@ -143,8 +1046,8 @@ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" }, "dependencies": { "arr-diff": { @@ -153,7 +1056,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "array-unique": { @@ -168,9 +1071,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "expand-brackets": { @@ -179,7 +1082,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "extglob": { @@ -188,7 +1091,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "is-extglob": { @@ -203,7 +1106,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "kind-of": { @@ -212,7 +1115,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "micromatch": { @@ -221,27 +1124,27 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } } } }, "app-root-path": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", - "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", + "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", "dev": true }, "archy": { @@ -256,7 +1159,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "arr-diff": { @@ -307,7 +1210,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -328,8 +1231,8 @@ "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", "dev": true, "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.10.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" } }, "arraybuffer.slice": { @@ -368,9 +1271,9 @@ "integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=", "dev": true, "requires": { - "escodegen": "1.2.0", - "esprima": "1.0.4", - "through": "2.3.8" + "escodegen": "~1.2.0", + "esprima": "~1.0.4", + "through": "~2.3.4" }, "dependencies": { "escodegen": { @@ -379,10 +1282,10 @@ "integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=", "dev": true, "requires": { - "esprima": "1.0.4", - "estraverse": "1.5.1", - "esutils": "1.0.0", - "source-map": "0.1.43" + "esprima": "~1.0.4", + "estraverse": "~1.5.0", + "esutils": "~1.0.0", + "source-map": "~0.1.30" } }, "esprima": { @@ -410,7 +1313,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -440,9 +1343,9 @@ "dev": true }, "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", "dev": true }, "aws-sign2": { @@ -452,9 +1355,9 @@ "dev": true }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, "babel-code-frame": { @@ -463,9 +1366,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-runtime": { @@ -474,8 +1377,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "backo2": { @@ -496,13 +1399,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "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": { @@ -511,7 +1414,36 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "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" } } } @@ -523,9 +1455,9 @@ "dev": true }, "base64-js": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", - "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "base64id": { @@ -541,7 +1473,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "beeper": { @@ -578,27 +1510,27 @@ "dev": true }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.16" + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" }, "dependencies": { "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true } } @@ -609,7 +1541,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "brace-expansion": { @@ -618,60 +1550,49 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", - "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "kind-of": "6.0.2", - "repeat-element": "1.1.2", - "snapdragon": "0.8.1", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "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" }, "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.2" - } - }, "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.1" + "is-extendable": "^0.1.0" } } } }, "brfs": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.4.4.tgz", - "integrity": "sha512-rX2qc9hkpLPiwdu1HkLY642rwwo3X6N+ZPyEPdNn3OUKV/B2BRP7dHdnkhGantOJLVoTluNYBi4VecHb2Kq2hw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", + "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", "dev": true, "requires": { - "quote-stream": "1.0.2", - "resolve": "1.5.0", - "static-module": "2.1.1", - "through2": "2.0.3" + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^2.2.0", + "through2": "^2.0.0" } }, "brotli": { @@ -680,13 +1601,13 @@ "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=", "dev": true, "requires": { - "base64-js": "1.2.3" + "base64-js": "^1.1.2" } }, "browser-resolve": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, "requires": { "resolve": "1.1.7" @@ -707,8 +1628,19 @@ "dev": true, "requires": { "ast-transform": "0.0.0", - "ast-types": "0.7.8", - "browser-resolve": "1.11.2" + "ast-types": "^0.7.0", + "browser-resolve": "^1.8.1" + } + }, + "browserslist": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.2.1.tgz", + "integrity": "sha512-1oO0c7Zhejwd+LXihS89WqtKionSbz298rJZKJgfrHIZhrV8AC15gw553VcB0lcEugja7IhWD7iAlrsamfYVPA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000890", + "electron-to-chromium": "^1.3.79", + "node-releases": "^1.0.0-alpha.14" } }, "buffer-equal": { @@ -717,13 +1649,19 @@ "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", "dev": true }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, "bufferstreams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "^1.0.33" } }, "builtin-modules": { @@ -744,15 +1682,15 @@ "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" + "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" } }, "caller-path": { @@ -761,7 +1699,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsite": { @@ -788,10 +1726,16 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" } }, + "caniuse-lite": { + "version": "1.0.30000892", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", + "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==", + "dev": true + }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -804,16 +1748,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -822,11 +1758,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "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" } }, "chokidar": { @@ -835,15 +1771,15 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -858,7 +1794,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -875,10 +1811,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -887,65 +1823,8 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } + "is-descriptor": "^0.1.0" } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.1.0" - } - }, - "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 } } }, @@ -955,7 +1834,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "cli-width": { @@ -970,15 +1849,15 @@ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-buffer": { @@ -994,21 +1873,45 @@ "dev": true }, "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" }, "dependencies": { - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true + }, + "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" + } + }, + "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" + } } } }, @@ -1030,10 +1933,25 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" } }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -1041,9 +1959,9 @@ "dev": true }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", "dev": true }, "combine-lists": { @@ -1052,13 +1970,13 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "^4.5.0" }, "dependencies": { "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -1069,13 +1987,13 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", - "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, "component-bind": { @@ -1103,14 +2021,15 @@ "dev": true }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "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": { - "inherits": "2.0.3", - "readable-stream": "2.3.4", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" }, "dependencies": { "isarray": { @@ -1120,38 +2039,38 @@ "dev": true }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "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.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" + "safe-buffer": "~5.1.0" } } } }, "concat-with-sourcemaps": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.5.tgz", - "integrity": "sha512-YtnS0VEY+e2Khzsey/6mra9EoM6h/5gxaC0e3mcHpA5yfDxafhygytNmcJWodvUgyXzSiL5MSkPO6bQGgfliHw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, "requires": { - "source-map": "0.6.1" + "source-map": "^0.6.1" }, "dependencies": { "source-map": { @@ -1170,7 +2089,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "1.3.2", + "parseurl": "~1.3.2", "utils-merge": "1.0.1" } }, @@ -1180,7 +2099,7 @@ "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "3.5.1" + "bluebird": "^3.1.1" } }, "contains-path": { @@ -1195,6 +2114,12 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", @@ -1213,14 +2138,14 @@ "integrity": "sha1-8DJLvumXcRAeezraES8xPDk9uO0=", "dev": true, "requires": { - "each-props": "1.3.1", - "is-plain-object": "2.0.4" + "each-props": "^1.2.1", + "is-plain-object": "^2.0.1" } }, "core-js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", "dev": true }, "core-util-is": { @@ -1248,26 +2173,26 @@ "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "qs": "~6.3.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1", + "uuid": "^3.0.0" } } } @@ -1278,7 +2203,27 @@ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "2.x.x" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "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 + } } }, "currently-unhandled": { @@ -1287,7 +2232,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "1.0.2" + "array-find-index": "^1.0.1" } }, "custom-event": { @@ -1302,7 +2247,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.39" + "es5-ext": "^0.10.9" } }, "dashdash": { @@ -1311,7 +2256,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -1337,6 +2282,34 @@ "ms": "2.0.0" } }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "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.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "debug-log": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", @@ -1361,7 +2334,7 @@ "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", "dev": true, "requires": { - "is-obj": "1.0.1" + "is-obj": "^1.0.0" } }, "deep-equal": { @@ -1382,7 +2355,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.3" + "clone": "^1.0.2" } }, "define-properties": { @@ -1391,8 +2364,8 @@ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "foreach": "^2.0.5", + "object-keys": "^1.0.8" } }, "define-property": { @@ -1401,22 +2374,53 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "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" + } + } } }, "deglob": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz", - "integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", "dev": true, "requires": { - "find-root": "1.1.0", - "glob": "7.1.2", - "ignore": "3.3.7", - "pkg-config": "1.1.1", - "run-parallel": "1.1.7", - "uniq": "1.0.1" + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" } }, "del": { @@ -1425,13 +2429,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "delayed-stream": { @@ -1458,13 +2462,19 @@ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "dfa": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.1.0.tgz", "integrity": "sha1-0wIYvRDQMPpCHfPrvIIoVGOjF4E=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.11.6" } }, "di": { @@ -1479,7 +2489,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "2.0.2" + "esutils": "^2.0.2" } }, "dom-serialize": { @@ -1488,10 +2498,10 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "1.0.1", - "ent": "2.2.0", - "extend": "3.0.1", - "void-elements": "2.0.1" + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" } }, "duplexer": { @@ -1506,17 +2516,17 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" } }, "each-props": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.1.tgz", - "integrity": "sha1-/BOPUeOid0KG1IWOAtbn3kYt4Vg=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "dev": true, "requires": { - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0" + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, "ecc-jsbn": { @@ -1526,7 +2536,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "ee-first": { @@ -1535,6 +2545,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.79", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", + "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1547,7 +2563,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "1.3.3" + "once": "~1.3.0" }, "dependencies": { "once": { @@ -1556,7 +2572,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } } } @@ -1650,25 +2666,25 @@ "dev": true }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "es-abstract": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", - "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.1", - "is-callable": "1.1.3", - "is-regex": "1.0.4" + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" } }, "es-to-primitive": { @@ -1677,19 +2693,20 @@ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", "dev": true, "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" } }, "es5-ext": { - "version": "0.10.39", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.39.tgz", - "integrity": "sha512-AlaXZhPHl0po/uxMx1tyrlt1O86M6D5iVaDH8UgLfgek4kXTX6vzsRfJQWC2Ku+aG8pkw1XWzh9eTkwfVrsD5g==", + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", "dev": true, "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" } }, "es6-iterator": { @@ -1698,9 +2715,9 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-map": { @@ -1709,12 +2726,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, "es6-promise": { @@ -1729,11 +2746,11 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39", - "es6-iterator": "2.0.3", + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "event-emitter": "~0.3.5" } }, "es6-symbol": { @@ -1742,8 +2759,8 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39" + "d": "1", + "es5-ext": "~0.10.14" } }, "es6-weak-map": { @@ -1752,10 +2769,10 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "escape-html": { @@ -1776,13 +2793,19 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" }, "dependencies": { + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -1790,7 +2813,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -1801,73 +2824,59 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.18.0.tgz", - "integrity": "sha1-ZH6YXErnFQLSCsYsEJ9m1RBMiks=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "2.1.0", - "escope": "3.6.0", - "espree": "3.5.3", - "esquery": "1.0.0", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.2", - "is-resolvable": "1.1.0", - "js-yaml": "3.6.1", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" }, "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true }, "strip-bom": { @@ -1882,21 +2891,21 @@ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } } } }, "eslint-config-standard": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-7.1.0.tgz", - "integrity": "sha1-R+dp6gc59bLVaTsaUBwhyWUPr88=", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", "dev": true }, "eslint-config-standard-jsx": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", - "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.2.tgz", + "integrity": "sha512-F8fRh2WFnTek7dZH9ZaE0PCBwdVGkwVWZmizla/DDNOmg7Tx6B/IlK5+oYpiX29jpu73LszeJj5i1axEZv6VMw==", "dev": true }, "eslint-import-resolver-node": { @@ -1905,19 +2914,19 @@ "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", "dev": true, "requires": { - "debug": "2.6.9", - "object-assign": "4.1.1", - "resolve": "1.5.0" + "debug": "^2.2.0", + "object-assign": "^4.0.1", + "resolve": "^1.1.6" } }, "eslint-module-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, "requires": { - "debug": "2.6.9", - "pkg-dir": "1.0.0" + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" } }, "eslint-plugin-import": { @@ -1926,16 +2935,16 @@ "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", "dev": true, "requires": { - "builtin-modules": "1.1.1", - "contains-path": "0.1.0", - "debug": "2.6.9", + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.2.0", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.2.3", - "eslint-module-utils": "2.1.1", - "has": "1.0.1", - "lodash.cond": "4.5.2", - "minimatch": "3.0.4", - "pkg-up": "1.0.0" + "eslint-import-resolver-node": "^0.2.0", + "eslint-module-utils": "^2.0.0", + "has": "^1.0.1", + "lodash.cond": "^4.3.0", + "minimatch": "^3.0.3", + "pkg-up": "^1.0.0" }, "dependencies": { "doctrine": { @@ -1944,8 +2953,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "isarray": { @@ -1962,10 +2971,10 @@ "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", "dev": true, "requires": { - "ignore": "3.3.7", - "minimatch": "3.0.4", - "object-assign": "4.1.1", - "resolve": "1.5.0", + "ignore": "^3.0.11", + "minimatch": "^3.0.2", + "object-assign": "^4.0.1", + "resolve": "^1.1.7", "semver": "5.3.0" }, "dependencies": { @@ -1978,20 +2987,22 @@ } }, "eslint-plugin-promise": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", - "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", + "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", "dev": true }, "eslint-plugin-react": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.9.0.tgz", - "integrity": "sha1-VMLpkGt2+dEBQgML3DTp1oQKC7I=", + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", + "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", "dev": true, "requires": { - "array.prototype.find": "2.0.4", - "doctrine": "1.5.0", - "jsx-ast-utils": "1.4.1" + "array.prototype.find": "^2.0.1", + "doctrine": "^1.2.2", + "has": "^1.0.1", + "jsx-ast-utils": "^1.3.4", + "object.assign": "^4.0.4" }, "dependencies": { "doctrine": { @@ -2000,8 +3011,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "isarray": { @@ -2013,19 +3024,19 @@ } }, "eslint-plugin-standard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", - "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", "dev": true }, "espree": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", - "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.4.1", - "acorn-jsx": "3.0.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -2035,44 +3046,27 @@ "dev": true }, "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "4.2.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } + "estraverse": "^4.0.0" } }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } + "estraverse": "^4.1.0" } }, "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "esutils": { @@ -2087,14 +3081,14 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.39" + "d": "1", + "es5-ext": "~0.10.14" } }, "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", "dev": true }, "exit-hook": { @@ -2109,9 +3103,9 @@ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "0.2.3", - "array-unique": "0.2.1", - "braces": "0.1.5" + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" }, "dependencies": { "array-slice": { @@ -2132,7 +3126,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "0.1.1" + "expand-range": "^0.1.0" } }, "expand-range": { @@ -2141,8 +3135,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "0.1.1", - "repeat-string": "0.2.2" + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" } }, "is-number": { @@ -2165,13 +3159,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" + "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" }, "dependencies": { "define-property": { @@ -2180,7 +3174,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -2189,65 +3183,8 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.1.0" - } - }, - "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 } } }, @@ -2257,20 +3194,20 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.3" + "fill-range": "^2.1.0" }, "dependencies": { "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "is-number": { @@ -2279,7 +3216,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "isarray": { @@ -2303,7 +3240,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -2314,7 +3251,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } }, "extend": { @@ -2329,8 +3266,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -2339,7 +3276,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -2350,14 +3287,14 @@ "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.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" + "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": { @@ -2366,7 +3303,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -2375,38 +3312,50 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.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" } } } }, "extract-zip": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", - "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", "dev": true, "requires": { - "concat-stream": "1.6.0", + "concat-stream": "1.6.2", "debug": "2.6.9", - "mkdirp": "0.5.0", + "mkdirp": "0.5.1", "yauzl": "2.4.1" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - } } }, "extsprintf": { @@ -2421,10 +3370,10 @@ "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", "dev": true, "requires": { - "acorn": "5.4.1", - "foreach": "2.0.5", + "acorn": "^5.0.0", + "foreach": "^2.0.5", "isarray": "0.0.1", - "object-keys": "1.0.11" + "object-keys": "^1.0.6" } }, "fancy-log": { @@ -2433,15 +3382,15 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" } }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -2462,7 +3411,7 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "1.2.0" + "pend": "~1.2.0" } }, "figures": { @@ -2471,8 +3420,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "file-entry-cache": { @@ -2481,8 +3430,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "filename-regex": { @@ -2497,10 +3446,10 @@ "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.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -2509,7 +3458,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -2521,12 +3470,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" }, "dependencies": { "statuses": { @@ -2555,8 +3504,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "findup-sync": { @@ -2565,10 +3514,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.9", - "resolve-dir": "1.0.1" + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" } }, "fined": { @@ -2577,11 +3526,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" } }, "first-chunk-stream": { @@ -2602,10 +3551,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" }, "dependencies": { "graceful-fs": { @@ -2616,23 +3565,43 @@ } } }, + "follow-redirects": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", + "dev": true, + "requires": { + "debug": "^3.1.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" + } + } + } + }, "fontkit": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.7.7.tgz", "integrity": "sha1-668tjz/t8wKuPGS0vurdwkf827E=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "brfs": "1.4.4", - "brotli": "1.3.2", - "browserify-optional": "1.0.1", - "clone": "1.0.3", - "deep-equal": "1.0.1", - "dfa": "1.1.0", - "restructure": "0.5.4", - "tiny-inflate": "1.0.2", - "unicode-properties": "1.1.0", - "unicode-trie": "0.3.1" + "babel-runtime": "^6.11.6", + "brfs": "^1.4.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.0", + "clone": "^1.0.1", + "deep-equal": "^1.0.0", + "dfa": "^1.0.0", + "restructure": "^0.5.3", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.0.0", + "unicode-trie": "^0.3.0" } }, "for-in": { @@ -2647,7 +3616,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, "foreach": { @@ -2668,9 +3637,9 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" } }, "fragment-cache": { @@ -2679,7 +3648,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fs-extra": { @@ -2688,9 +3657,9 @@ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" }, "dependencies": { "graceful-fs": { @@ -2707,7 +3676,7 @@ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.2" }, "dependencies": { "graceful-fs": { @@ -2725,222 +3694,87 @@ "dev": true }, "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, "requires": { - "nan": "2.9.2", - "node-pre-gyp": "0.6.39" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "version": "1.1.1", + "bundled": true, "dev": true, "optional": true }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", - "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", + "version": "1.2.0", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "bundled": true, "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true, - "optional": true - }, "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "version": "1.0.0", + "bundled": true, "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "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.16.3" - } - }, "brace-expansion": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "version": "1.1.11", + "bundled": true, "dev": true, "requires": { - "balanced-match": "0.4.2", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "chownr": { + "version": "1.0.1", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "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 - }, - "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.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "bundled": true, "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } + "optional": true }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "version": "2.6.9", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2948,371 +3782,161 @@ } }, "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "version": "0.5.1", + "bundled": true, "dev": true, "optional": true }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz", - "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "version": "1.0.3", + "bundled": true, "dev": true, "optional": true }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "fs-minipass": { + "version": "1.2.5", + "bundled": true, "dev": true, "optional": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "minipass": "^2.2.1" } }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "bundled": true, "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } + "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } + "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.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "bundled": true, "dev": true, "optional": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "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", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "iconv-lite": { + "version": "0.4.21", + "bundled": true, "dev": true, + "optional": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "safer-buffer": "^2.1.0" } }, - "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": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "ignore-walk": { + "version": "3.0.1", + "bundled": true, "dev": true, "optional": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" + "minimatch": "^3.0.4" } }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, + "optional": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "version": "1.3.5", + "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true - }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "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, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "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=", + "bundled": true, "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, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "minimatch": { + "version": "3.0.4", + "bundled": true, "dev": true, - "optional": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } + "brace-expansion": "^1.1.7" } }, - "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "minimist": { + "version": "0.0.8", + "bundled": true, "dev": true }, - "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "minipass": { + "version": "2.2.4", + "bundled": true, "dev": true, "requires": { - "mime-db": "1.27.0" + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "minizlib": { + "version": "1.1.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "brace-expansion": "1.1.7" + "minipass": "^2.2.1" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" @@ -3320,424 +3944,280 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "dev": true, "optional": true }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, "node-pre-gyp": { - "version": "0.6.39", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", - "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", + "version": "0.10.0", + "bundled": true, "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "optional": true, "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", - "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "version": "4.1.2", + "bundled": true, "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "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", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "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=", + "bundled": true, "dev": true, "optional": true }, "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.5", + "bundled": true, "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "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 - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "2.0.0", + "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "version": "1.2.7", + "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } } }, "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.3.6", + "bundled": true, "dev": true, "optional": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" + "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.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "version": "2.6.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", + "version": "5.1.1", + "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.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "version": "5.5.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": 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.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", - "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", + "string-width": { + "version": "1.0.2", + "bundled": true, "dev": true, - "optional": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", - "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "1.1.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true, - "optional": true - }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true, "optional": true }, "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "version": "4.4.1", + "bundled": true, "dev": true, "optional": true, "requires": { - "safe-buffer": "5.0.1" + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", - "dev": true, - "optional": true - }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "bundled": true, "dev": true, "optional": true }, - "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, "dev": true } } @@ -3754,7 +4234,7 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "0.1.0" + "globule": "~0.1.0" } }, "generate-function": { @@ -3769,13 +4249,13 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "^1.0.0" } }, "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", "dev": true }, "get-value": { @@ -3790,7 +4270,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -3802,9 +4282,9 @@ } }, "gl-matrix": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.4.0.tgz", - "integrity": "sha1-IImxMwGinuyCLZ2Z3/wfeO6aPFA=", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.6.1.tgz", + "integrity": "sha512-fK37p7vkpw5H4WSypfa6TUV8nlB8+Fd1pZj15sMtvRPnfzArvTI4U4E25x2Hmp+UxZX11ve0aGaHarRieP+gSw==", "dev": true }, "glob": { @@ -3813,12 +4293,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "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" } }, "glob-base": { @@ -3827,8 +4307,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -3843,7 +4323,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -3854,7 +4334,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -3869,7 +4349,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -3880,12 +4360,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" }, "dependencies": { "glob": { @@ -3894,10 +4374,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" } }, "minimatch": { @@ -3906,7 +4386,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.0.0" } }, "readable-stream": { @@ -3915,10 +4395,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "through2": { @@ -3927,8 +4407,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } @@ -3939,7 +4419,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "0.5.2" + "gaze": "^0.5.1" } }, "glob2base": { @@ -3948,7 +4428,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "0.1.1" + "find-index": "^0.1.1" } }, "global-modules": { @@ -3957,9 +4437,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" } }, "global-prefix": { @@ -3968,11 +4448,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.0" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" } }, "globals": { @@ -3987,12 +4467,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "globule": { @@ -4001,9 +4481,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" }, "dependencies": { "glob": { @@ -4012,9 +4492,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" } }, "graceful-fs": { @@ -4035,8 +4515,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } } } @@ -4047,7 +4527,7 @@ "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" } }, "graceful-fs": { @@ -4056,7 +4536,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.1" + "natives": "^1.1.0" } }, "gulp": { @@ -4065,19 +4545,39 @@ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + } + }, + "gulp-babel": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0.tgz", + "integrity": "sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ==", + "dev": true, + "requires": { + "plugin-error": "^1.0.1", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } } }, "gulp-chmod": { @@ -4086,9 +4586,9 @@ "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", "dev": true, "requires": { - "deep-assign": "1.0.0", - "stat-mode": "0.2.2", - "through2": "2.0.3" + "deep-assign": "^1.0.0", + "stat-mode": "^0.2.0", + "through2": "^2.0.0" } }, "gulp-cli": { @@ -4097,24 +4597,24 @@ "integrity": "sha1-b1u+LNC9tISdEs+eEkalhh+LT4g=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "copy-props": "1.6.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "lodash.isfunction": "3.0.9", - "lodash.isplainobject": "4.0.6", - "lodash.sortby": "4.7.0", - "matchdep": "1.0.1", - "mute-stdout": "1.0.0", - "pretty-hrtime": "1.0.3", - "semver-greatest-satisfied-range": "1.1.0", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "wreck": "6.3.0", - "yargs": "3.32.0" + "archy": "^1.0.0", + "chalk": "^1.1.0", + "copy-props": "^1.4.1", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.3.0", + "lodash.isfunction": "^3.0.8", + "lodash.isplainobject": "^4.0.4", + "lodash.sortby": "^4.5.0", + "matchdep": "^1.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "semver-greatest-satisfied-range": "^1.0.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.9", + "wreck": "^6.3.0", + "yargs": "^3.28.0" } }, "gulp-concat": { @@ -4123,9 +4623,9 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "1.0.5", - "through2": "2.0.3", - "vinyl": "2.1.0" + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" }, "dependencies": { "clone": { @@ -4147,37 +4647,57 @@ "dev": true }, "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } } } }, "gulp-header": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.9.tgz", - "integrity": "sha1-yfEP7gYy2B6Tl4nG7PRaFRvzCYs=", + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, "requires": { - "concat-with-sourcemaps": "1.0.5", - "gulp-util": "3.0.8", - "object-assign": "4.1.1", - "through2": "2.0.3" + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, + "dependencies": { + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + } } }, "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.3.0.tgz", + "integrity": "sha512-nEuZB7/9i0IZ8AXORTizl2QLP9tcC9uWc/s329zElBLJw1CfOhmMXBxwVlCRKjDyrWuhVP0uBKl61KeQ32TiCg==", "dev": true }, "gulp-size": { @@ -4186,13 +4706,46 @@ "integrity": "sha1-HCtk8X+QcdWr2Z0VS3s0gfj7oSg=", "dev": true, "requires": { - "chalk": "1.1.3", - "gulp-util": "3.0.8", - "gzip-size": "3.0.0", - "object-assign": "4.1.1", - "pretty-bytes": "3.0.1", - "stream-counter": "1.0.0", - "through2": "2.0.3" + "chalk": "^1.0.0", + "gulp-util": "^3.0.0", + "gzip-size": "^3.0.0", + "object-assign": "^4.0.1", + "pretty-bytes": "^3.0.1", + "stream-counter": "^1.0.0", + "through2": "^2.0.0" + } + }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "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 + } } }, "gulp-standard": { @@ -4201,185 +4754,30 @@ "integrity": "sha512-w+VBktDzONh807qzV5FvngPgmzuGRWu7oMlIpIvOOmSPlyy/ixM138DGOuMWy1M9bRVMDKEfQSj0aGB2ZjzQSA==", "dev": true, "requires": { - "app-root-path": "2.0.1", - "colors": "1.1.2", - "log-symbols": "1.0.2", - "path": "0.12.7", - "plugin-error": "1.0.1", - "standard": "10.0.3", - "through2": "2.0.3" + "app-root-path": "^2.0.0", + "colors": "^1.1.2", + "log-symbols": "^1.0.2", + "path": "^0.12.7", + "plugin-error": "^1.0.0", + "standard": "^10.0.0", + "through2": "^2.0.0" }, "dependencies": { - "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "2.1.0", - "escope": "3.6.0", - "espree": "3.5.3", - "esquery": "1.0.0", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.2", - "is-resolvable": "1.1.0", - "js-yaml": "3.6.1", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" - } - }, - "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.2.tgz", - "integrity": "sha512-F8fRh2WFnTek7dZH9ZaE0PCBwdVGkwVWZmizla/DDNOmg7Tx6B/IlK5+oYpiX29jpu73LszeJj5i1axEZv6VMw==", - "dev": true - }, - "eslint-plugin-promise": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", - "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", - "dev": true - }, - "eslint-plugin-react": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", - "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", - "dev": true, - "requires": { - "array.prototype.find": "2.0.4", - "doctrine": "1.5.0", - "has": "1.0.1", - "jsx-ast-utils": "1.4.1", - "object.assign": "4.1.0" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - } - } - }, - "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", - "dev": true - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", - "dev": true - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "1.1.0", - "arr-diff": "4.0.0", - "arr-union": "3.1.0", - "extend-shallow": "3.0.2" - } - }, "standard": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/standard/-/standard-10.0.3.tgz", "integrity": "sha512-JURZ+85ExKLQULckDFijdX5WHzN6RC7fgiZNSV4jFQVo+3tPoQGHyBrGekye/yf0aOfb4210EM5qPNlc2cRh4w==", "dev": true, "requires": { - "eslint": "3.19.0", + "eslint": "~3.19.0", "eslint-config-standard": "10.2.1", "eslint-config-standard-jsx": "4.0.2", - "eslint-plugin-import": "2.2.0", - "eslint-plugin-node": "4.2.3", - "eslint-plugin-promise": "3.5.0", - "eslint-plugin-react": "6.10.3", - "eslint-plugin-standard": "3.0.1", - "standard-engine": "7.0.0" - } - }, - "standard-engine": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-7.0.0.tgz", - "integrity": "sha1-67d7nI/CyBZf+jU72Rug3/Qa9pA=", - "dev": true, - "requires": { - "deglob": "2.1.0", - "get-stdin": "5.0.1", - "minimist": "1.2.0", - "pkg-conf": "2.1.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" + "eslint-plugin-import": "~2.2.0", + "eslint-plugin-node": "~4.2.2", + "eslint-plugin-promise": "~3.5.0", + "eslint-plugin-react": "~6.10.0", + "eslint-plugin-standard": "~3.0.1", + "standard-engine": "~7.0.0" } } } @@ -4390,7 +4788,7 @@ "integrity": "sha1-exeRa4UMoPBa9BkN0k6aweJunyY=", "dev": true, "requires": { - "through2": "0.6.5" + "through2": "^0.6.3" }, "dependencies": { "readable-stream": { @@ -4399,10 +4797,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "through2": { @@ -4411,8 +4809,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } @@ -4423,20 +4821,20 @@ "integrity": "sha1-bbhbHQ7mPRgFhZK2WGSdZcLsRUE=", "dev": true, "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.5", - "make-error-cause": "1.2.2", - "through2": "2.0.3", - "uglify-js": "2.8.29", - "uglify-save-license": "0.4.1", - "vinyl-sourcemaps-apply": "0.2.1" + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash": "^4.13.1", + "make-error-cause": "^1.1.1", + "through2": "^2.0.0", + "uglify-js": "~2.8.10", + "uglify-save-license": "^0.4.1", + "vinyl-sourcemaps-apply": "^0.2.0" }, "dependencies": { "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -4447,24 +4845,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "object-assign": { @@ -4481,22 +4879,22 @@ "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", "dev": true, "requires": { - "consolidate": "0.14.5", - "es6-promise": "3.3.1", - "fs-readfile-promise": "2.0.1", - "gulp-util": "3.0.8", - "js-yaml": "3.6.1", - "lodash": "4.17.5", - "node.extend": "1.1.6", - "through2": "2.0.3", - "tryit": "1.0.3", - "vinyl-bufferstream": "1.0.1" + "consolidate": "^0.14.1", + "es6-promise": "^3.1.2", + "fs-readfile-promise": "^2.0.1", + "gulp-util": "^3.0.3", + "js-yaml": "^3.2.6", + "lodash": "^4.11.1", + "node.extend": "^1.1.2", + "through2": "^2.0.1", + "tryit": "^1.0.1", + "vinyl-bufferstream": "^1.0.1" }, "dependencies": { "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -4507,7 +4905,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.1" + "glogg": "^1.0.0" } }, "gzip-size": { @@ -4516,7 +4914,7 @@ "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", "dev": true, "requires": { - "duplexer": "0.1.1" + "duplexer": "^0.1.1" } }, "handlebars": { @@ -4525,10 +4923,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "source-map": { @@ -4537,7 +4935,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -4554,19 +4952,19 @@ "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, "requires": { - "chalk": "1.1.3", - "commander": "2.14.1", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.1.1" } }, "has-ansi": { @@ -4575,7 +4973,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-binary": { @@ -4605,7 +5003,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" } }, "has-symbols": { @@ -4620,9 +5018,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { @@ -4631,8 +5029,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -4641,7 +5039,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4652,8 +5050,8 @@ "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { - "is-stream": "1.1.0", - "pinkie-promise": "2.0.1" + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" } }, "hawk": { @@ -4662,10 +5060,10 @@ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" } }, "hoek": { @@ -4680,8 +5078,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "homedir-polyfill": { @@ -4690,43 +5088,36 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.1.tgz", + "integrity": "sha512-Ba4+0M4YvIDUUsprMjhVTU1yN9F2/LJSAl69ZpzaLT4l4j5mwTS6jqqW9Ojvj6lKz/veqPzpJBqGbXspOb533A==", "dev": true }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.1", + "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - } + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" } }, "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "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": "1.2.0", - "requires-port": "1.0.0" + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" } }, "http-signature": { @@ -4735,21 +5126,24 @@ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "image-size": { @@ -4770,7 +5164,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "indexof": { @@ -4785,8 +5179,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -4807,25 +5201,25 @@ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.5", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" }, "dependencies": { "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -4836,6 +5230,15 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -4854,17 +5257,28 @@ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" + "is-relative": "^1.0.0", + "is-windows": "^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==", + "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": "6.0.2" + "kind-of": "^3.0.2" + }, + "dependencies": { + "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" + } + } } }, "is-arrayish": { @@ -4879,7 +5293,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -4894,7 +5308,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, "is-callable": { @@ -4904,12 +5318,23 @@ "dev": true }, "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==", + "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": "6.0.2" + "kind-of": "^3.0.2" + }, + "dependencies": { + "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" + } + } } }, "is-date-object": { @@ -4919,14 +5344,22 @@ "dev": true }, "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "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": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "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-dotfile": { @@ -4941,7 +5374,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -4962,7 +5395,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -4971,7 +5404,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-glob": { @@ -4980,7 +5413,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } }, "is-my-ip-valid": { @@ -4995,11 +5428,11 @@ "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "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": { @@ -5008,7 +5441,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -5017,7 +5450,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -5028,23 +5461,6 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -5052,12 +5468,12 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -5066,7 +5482,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-plain-object": { @@ -5075,7 +5491,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "is-posix-bracket": { @@ -5090,6 +5506,12 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -5102,7 +5524,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.1" + "has": "^1.0.1" } }, "is-relative": { @@ -5111,7 +5533,7 @@ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "1.0.0" + "is-unc-path": "^1.0.0" } }, "is-resolvable": { @@ -5144,7 +5566,7 @@ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "^0.1.2" } }, "is-utf8": { @@ -5195,20 +5617,20 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.6.1", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "glob": { @@ -5217,11 +5639,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "resolve": { @@ -5236,14 +5658,8 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true } } }, @@ -5253,6 +5669,12 @@ "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", "dev": true }, + "js-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", + "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==", + "dev": true + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -5265,8 +5687,8 @@ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" + "argparse": "^1.0.7", + "esprima": "^2.6.0" } }, "jsbn": { @@ -5276,10 +5698,16 @@ "dev": true, "optional": true }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, "json-parse-better-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema": { @@ -5300,7 +5728,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -5315,13 +5743,19 @@ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", "dev": true }, + "json5": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" }, "dependencies": { "graceful-fs": { @@ -5377,33 +5811,33 @@ "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", "dev": true, "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "chokidar": "1.7.0", - "colors": "1.1.2", - "combine-lists": "1.0.1", - "connect": "3.6.6", - "core-js": "2.5.3", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.6.0", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.2.0", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^1.4.1", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^3.8.0", + "log4js": "^0.6.31", + "mime": "^1.3.4", + "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": "1.7.3", - "source-map": "0.5.7", + "source-map": "^0.5.3", "tmp": "0.0.31", - "useragent": "2.3.0" + "useragent": "^2.1.12" }, "dependencies": { "graceful-fs": { @@ -5421,16 +5855,16 @@ } }, "karma-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.1.tgz", - "integrity": "sha1-Wv+LOc9plNwi3kyENix2ABtjfPY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", + "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", "dev": true, "requires": { - "dateformat": "1.0.12", - "istanbul": "0.4.5", - "lodash": "3.10.1", - "minimatch": "3.0.4", - "source-map": "0.5.7" + "dateformat": "^1.0.6", + "istanbul": "^0.4.0", + "lodash": "^4.17.0", + "minimatch": "^3.0.0", + "source-map": "^0.5.1" }, "dependencies": { "dateformat": { @@ -5439,14 +5873,20 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" + "get-stdin": "^4.0.1", + "meow": "^3.3.0" } }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -5458,9 +5898,9 @@ "dev": true }, "karma-jasmine": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.1.tgz", - "integrity": "sha1-b+hA51oRYAydkehLM8RY4cRqNSk=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", + "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", "dev": true }, "karma-phantomjs-launcher": { @@ -5469,14 +5909,14 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "4.17.5", - "phantomjs-prebuilt": "2.1.16" + "lodash": "^4.0.1", + "phantomjs-prebuilt": "^2.1.7" }, "dependencies": { "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true } } @@ -5499,7 +5939,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.9" }, "dependencies": { "graceful-fs": { @@ -5512,13 +5952,10 @@ } }, "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "dev": true, - "requires": { - "set-getter": "0.1.0" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true }, "lcid": { "version": "1.0.0", @@ -5526,7 +5963,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "lcov-parse": { @@ -5541,8 +5978,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "liftoff": { @@ -5551,27 +5988,26 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.5.0" + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { "graceful-fs": { @@ -5580,14 +6016,17 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true } } }, @@ -5597,8 +6036,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "dependencies": { "path-exists": { @@ -5681,7 +6120,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" } }, "lodash.isarguments": { @@ -5714,9 +6153,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "lodash.restparam": { @@ -5737,15 +6176,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" } }, "lodash.templatesettings": { @@ -5754,8 +6193,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } }, "log-driver": { @@ -5770,7 +6209,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.0.0" } }, "log4js": { @@ -5779,8 +6218,8 @@ "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "semver": "4.3.6" + "readable-stream": "~1.0.2", + "semver": "~4.3.3" }, "dependencies": { "readable-stream": { @@ -5789,10 +6228,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } } } @@ -5803,14 +6242,23 @@ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" } }, "lru-cache": { @@ -5819,6 +6267,24 @@ "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "dev": true, + "requires": { + "vlq": "^0.2.2" + } + }, "make-error": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", @@ -5831,27 +6297,16 @@ "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", "dev": true, "requires": { - "make-error": "1.3.4" + "make-error": "^1.2.0" } }, "make-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", - "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "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.6" - } - } + "kind-of": "^6.0.2" } }, "map-cache": { @@ -5872,7 +6327,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "matchdep": { @@ -5881,9 +6336,9 @@ "integrity": "sha1-pXozgESR+64girqPaDgEN6vC3KU=", "dev": true, "requires": { - "findup-sync": "0.3.0", - "micromatch": "2.3.11", - "resolve": "1.1.7", + "findup-sync": "~0.3.0", + "micromatch": "^2.3.7", + "resolve": "~1.1.6", "stack-trace": "0.0.9" }, "dependencies": { @@ -5893,7 +6348,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "array-unique": { @@ -5908,9 +6363,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "expand-brackets": { @@ -5919,7 +6374,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "extglob": { @@ -5928,7 +6383,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "findup-sync": { @@ -5937,7 +6392,7 @@ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", "dev": true, "requires": { - "glob": "5.0.15" + "glob": "~5.0.0" } }, "glob": { @@ -5946,11 +6401,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "is-extglob": { @@ -5965,7 +6420,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "kind-of": { @@ -5974,7 +6429,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "micromatch": { @@ -5983,19 +6438,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } }, "resolve": { @@ -6006,49 +6461,80 @@ } } }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, "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 }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "dev": true, + "requires": { + "source-map": "^0.5.6" } }, "micromatch": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", - "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", - "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.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" + "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" } }, "mime": { @@ -6069,7 +6555,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "minimatch": { @@ -6078,7 +6564,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -6093,8 +6579,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -6103,7 +6589,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -6153,36 +6639,35 @@ "dev": true }, "nan": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.9.2.tgz", - "integrity": "sha512-ltW65co7f3PQWBDbqVvaU1WtFJUsNW7sWWm4HINhbMQIyVyzIeyZ8toX5TC5eeooE6piZoaEh4cZkueSKG3KYw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", "dev": true, "optional": true }, "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "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-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" + "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" } }, "natives": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", "dev": true }, "natural-compare": { @@ -6197,13 +6682,36 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node-releases": { + "version": "1.0.0-alpha.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.14.tgz", + "integrity": "sha512-G8nnF9cP9QPP/jUmYWw/uUUhumHmkm+X/EarCugYFjYm2uXRMFeOD6CVT3RLdoyCvDUNy51nirGfUItKWs/S1g==", + "dev": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, "node.extend": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", "dev": true, "requires": { - "is": "3.2.1" + "is": "^3.1.0" } }, "nopt": { @@ -6212,7 +6720,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } }, "normalize-package-data": { @@ -6221,10 +6729,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "4.3.6", - "validate-npm-package-license": "3.0.1" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -6233,7 +6741,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } }, "number-is-nan": { @@ -6266,9 +6774,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -6277,44 +6785,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" - } - }, - "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.2.2" - } - }, - "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.2.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.1.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-descriptor": "^0.1.0" } }, "kind-of": { @@ -6323,7 +6794,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6335,9 +6806,9 @@ "dev": true }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, "object-visit": { @@ -6346,7 +6817,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" } }, "object.assign": { @@ -6355,10 +6826,10 @@ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "object.defaults": { @@ -6367,10 +6838,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" } }, "object.map": { @@ -6379,8 +6850,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.0" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, "object.omit": { @@ -6389,8 +6860,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" }, "dependencies": { "for-own": { @@ -6399,7 +6870,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } } } @@ -6410,7 +6881,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "on-finished": { @@ -6428,12 +6899,12 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -6443,8 +6914,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.2" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { "minimist": { @@ -6452,6 +6923,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true } } }, @@ -6461,20 +6938,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "options": { @@ -6489,9 +6958,9 @@ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.1" + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" } }, "ordered-read-streams": { @@ -6512,7 +6981,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "^1.0.0" } }, "os-tmpdir": { @@ -6522,12 +6991,12 @@ "dev": true }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -6536,7 +7005,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.2.0" + "p-limit": "^1.1.0" } }, "p-try": { @@ -6557,9 +7026,9 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" } }, "parse-glob": { @@ -6568,10 +7037,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -6586,18 +7055,19 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "parse-passwd": { @@ -6612,7 +7082,7 @@ "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseqs": { @@ -6621,7 +7091,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseuri": { @@ -6630,7 +7100,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseurl": { @@ -6651,8 +7121,8 @@ "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", "dev": true, "requires": { - "process": "0.11.10", - "util": "0.10.3" + "process": "^0.11.1", + "util": "^0.10.3" } }, "path-exists": { @@ -6661,7 +7131,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } }, "path-is-absolute": { @@ -6688,7 +7158,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "^0.1.0" } }, "path-root-regex": { @@ -6703,9 +7173,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "graceful-fs": { @@ -6734,15 +7204,15 @@ "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "dev": true, "requires": { - "es6-promise": "4.2.4", - "extract-zip": "1.6.6", - "fs-extra": "1.0.0", - "hasha": "2.2.0", - "kew": "0.7.0", - "progress": "1.1.8", - "request": "2.83.0", - "request-progress": "2.0.1", - "which": "1.3.0" + "es6-promise": "^4.0.3", + "extract-zip": "^1.6.5", + "fs-extra": "^1.0.0", + "hasha": "^2.2.0", + "kew": "^0.7.0", + "progress": "^1.1.8", + "request": "^2.81.0", + "request-progress": "^2.0.1", + "which": "^1.2.10" }, "dependencies": { "es6-promise": { @@ -6771,7 +7241,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-conf": { @@ -6780,8 +7250,8 @@ "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", "dev": true, "requires": { - "find-up": "2.1.0", - "load-json-file": "4.0.0" + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" }, "dependencies": { "find-up": { @@ -6790,48 +7260,8 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.1" + "locate-path": "^2.0.0" } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -6841,9 +7271,9 @@ "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", "dev": true, "requires": { - "debug-log": "1.0.1", - "find-root": "1.1.0", - "xtend": "4.0.1" + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" } }, "pkg-dir": { @@ -6852,7 +7282,7 @@ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "^1.0.0" } }, "pkg-up": { @@ -6861,7 +7291,19 @@ "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "^1.0.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" } }, "pluralize": { @@ -6894,7 +7336,7 @@ "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "pretty-hrtime": { @@ -6903,6 +7345,12 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -6952,28 +7400,26 @@ "dev": true, "requires": { "buffer-equal": "0.0.1", - "minimist": "1.2.0", - "through2": "2.0.3" + "minimist": "^1.1.3", + "through2": "^2.0.0" } }, "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "dependencies": { - "kind-of": { + "is-number": { "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.6" - } + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true } } }, @@ -6984,14 +7430,14 @@ "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "dev": true, "requires": { "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, @@ -7001,9 +7447,48 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } } }, "read-pkg-up": { @@ -7012,8 +7497,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, "readable-stream": { @@ -7022,10 +7507,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "readdirp": { @@ -7034,10 +7519,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.4", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" }, "dependencies": { "graceful-fs": { @@ -7053,27 +7538,27 @@ "dev": true }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "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.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" + "safe-buffer": "~5.1.0" } } } @@ -7084,8 +7569,8 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" } }, @@ -7095,7 +7580,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "^1.1.6" } }, "redent": { @@ -7104,8 +7589,23 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", + "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" } }, "regenerator-runtime": { @@ -7114,13 +7614,22 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "regenerator-transform": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", + "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "^0.1.3" } }, "regex-not": { @@ -7129,8 +7638,45 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", + "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.4.0", + "regjsparser": "^0.3.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" + } + }, + "regjsgen": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.4.0.tgz", + "integrity": "sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==", + "dev": true + }, + "regjsparser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.3.0.tgz", + "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } } }, "remove-trailing-separator": { @@ -7157,7 +7703,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "replace-ext": { @@ -7167,35 +7713,45 @@ "dev": true }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "dev": true, - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" }, "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -7208,50 +7764,21 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.2.1" - } - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.2.1" - } - } - } - }, "form-data": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "har-validator": { @@ -7260,61 +7787,34 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.2.1" - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } } } @@ -7325,7 +7825,7 @@ "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { - "throttleit": "1.0.0" + "throttleit": "^1.0.0" } }, "require-uncached": { @@ -7334,8 +7834,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, "requires-port": { @@ -7345,12 +7845,12 @@ "dev": true }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-dir": { @@ -7359,8 +7859,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } }, "resolve-from": { @@ -7381,8 +7881,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, "restructure": { @@ -7391,7 +7891,7 @@ "integrity": "sha1-9U591WNZD7NP1r9Vh2EJrsyyjeg=", "dev": true, "requires": { - "browserify-optional": "1.0.1" + "browserify-optional": "^1.0.0" } }, "ret": { @@ -7406,7 +7906,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -7415,7 +7915,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "run-async": { @@ -7424,13 +7924,13 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.0" } }, "run-parallel": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.7.tgz", - "integrity": "sha512-nB641a6enJOh0fdsFHR9SiVCiOlAyjMplImDdjV3kWCzJZw9rwzvGwmpGuPmfX//Yxblh0pkzPcFcxA81iwmxA==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", "dev": true }, "rx-lite": { @@ -7440,9 +7940,9 @@ "dev": true }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "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": { @@ -7451,9 +7951,15 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "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 + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -7472,7 +7978,7 @@ "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", "dev": true, "requires": { - "sver-compat": "1.5.0" + "sver-compat": "^1.5.0" } }, "sequencify": { @@ -7481,15 +7987,6 @@ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "0.3.0" - } - }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", @@ -7502,10 +7999,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -7514,15 +8011,15 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } }, "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, "shallow-copy": { @@ -7537,9 +8034,9 @@ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } }, "sigmund": { @@ -7561,19 +8058,19 @@ "dev": true }, "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "2.0.2" + "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": { "define-property": { @@ -7582,7 +8079,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -7591,65 +8088,8 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.1.0" - } - }, - "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 } } }, @@ -7659,9 +8099,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -7670,7 +8110,36 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "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" } } } @@ -7681,7 +8150,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { @@ -7690,7 +8159,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -7701,13 +8170,13 @@ "integrity": "sha1-ahfUeYy7yLxuETFTaUkHqLrJSU0=", "dev": true, "requires": { - "chalk": "1.1.3", - "inherits": "2.0.3", - "minimist": "1.2.0", - "readable-stream": "2.3.4", - "standard": "9.0.2", - "standard-json": "1.0.2", - "text-table": "0.2.0" + "chalk": "^1.1.0", + "inherits": "^2.0.1", + "minimist": "^1.1.1", + "readable-stream": "^2.0.6", + "standard": "*", + "standard-json": "^1.0.0", + "text-table": "^0.2.0" }, "dependencies": { "isarray": { @@ -7717,27 +8186,27 @@ "dev": true }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "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.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" + "safe-buffer": "~5.1.0" } } } @@ -7748,7 +8217,7 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "socket.io": { @@ -7894,16 +8363,16 @@ "dev": true }, "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "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.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "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": { @@ -7913,30 +8382,41 @@ "dev": true }, "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", "dev": true }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "split-string": { @@ -7945,7 +8425,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -7955,19 +8435,20 @@ "dev": true }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" }, "dependencies": { "assert-plus": { @@ -7990,43 +8471,166 @@ "integrity": "sha1-m9O5RnSS4hKxkU14VTlD/5tI/Zk=", "dev": true, "requires": { - "eslint": "3.18.0", + "eslint": "~3.18.0", "eslint-config-standard": "7.1.0", "eslint-config-standard-jsx": "3.3.0", - "eslint-plugin-promise": "3.4.2", - "eslint-plugin-react": "6.9.0", - "eslint-plugin-standard": "2.0.1", - "standard-engine": "5.4.0" + "eslint-plugin-promise": "~3.4.0", + "eslint-plugin-react": "~6.9.0", + "eslint-plugin-standard": "~2.0.1", + "standard-engine": "~5.4.0" + }, + "dependencies": { + "eslint": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.18.0.tgz", + "integrity": "sha1-ZH6YXErnFQLSCsYsEJ9m1RBMiks=", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + }, + "eslint-config-standard": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-7.1.0.tgz", + "integrity": "sha1-R+dp6gc59bLVaTsaUBwhyWUPr88=", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", + "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", + "dev": true + }, + "eslint-plugin-promise": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", + "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", + "dev": true + }, + "eslint-plugin-react": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.9.0.tgz", + "integrity": "sha1-VMLpkGt2+dEBQgML3DTp1oQKC7I=", + "dev": true, + "requires": { + "array.prototype.find": "^2.0.1", + "doctrine": "^1.2.2", + "jsx-ast-utils": "^1.3.4" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-standard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", + "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "standard-engine": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-5.4.0.tgz", + "integrity": "sha1-4OhpWeoHhkJdM4PkDBv3DS+YVXk=", + "dev": true, + "requires": { + "deglob": "^2.1.0", + "get-stdin": "^5.0.1", + "home-or-tmp": "^2.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + } } }, "standard-engine": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-5.4.0.tgz", - "integrity": "sha1-4OhpWeoHhkJdM4PkDBv3DS+YVXk=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-7.0.0.tgz", + "integrity": "sha1-67d7nI/CyBZf+jU72Rug3/Qa9pA=", "dev": true, "requires": { - "deglob": "2.1.0", - "get-stdin": "5.0.1", - "home-or-tmp": "2.0.0", - "minimist": "1.2.0", - "pkg-conf": "2.1.0" - }, - "dependencies": { - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - } + "deglob": "^2.1.0", + "get-stdin": "^5.0.1", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" } }, "standard-json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/standard-json/-/standard-json-1.0.2.tgz", - "integrity": "sha1-gt6koUx4zZ4104zeS4isa2JZaiM=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/standard-json/-/standard-json-1.0.3.tgz", + "integrity": "sha512-lhMP+KREBcfyyMe2ObJlEjJ0lc0ItA9uny83d9ZL6ggYtB79DuaAKCxJVoiflg5EV3D2rpuWn+n4+zXjWXk0sQ==", "dev": true, "requires": { - "concat-stream": "1.6.0" + "concat-stream": "^1.5.0" } }, "stat-mode": { @@ -8041,7 +8645,7 @@ "integrity": "sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw==", "dev": true, "requires": { - "escodegen": "1.8.1" + "escodegen": "^1.8.1" } }, "static-extend": { @@ -8050,8 +8654,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -8060,85 +8664,31 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } + "is-descriptor": "^0.1.0" } - }, - "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.1.0" - } - }, - "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 } } }, "static-module": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.1.1.tgz", - "integrity": "sha512-PPLCnxRl74wV38rG1T0rH8Fl2wIktTXFo7/varrZjtSGb/vndZIGkpe4HJVd8hoBYXRkRHW6hlCRAHvmDgrYQQ==", - "dev": true, - "requires": { - "concat-stream": "1.6.0", - "duplexer2": "0.1.4", - "escodegen": "1.9.0", - "falafel": "2.1.0", - "has": "1.0.1", - "object-inspect": "1.4.1", - "quote-stream": "1.0.2", - "readable-stream": "2.3.4", - "shallow-copy": "0.0.1", - "static-eval": "2.0.0", - "through2": "2.0.3" + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", + "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", + "dev": true, + "requires": { + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "~1.9.0", + "falafel": "^2.1.0", + "has": "^1.0.1", + "magic-string": "^0.22.4", + "merge-source-map": "1.0.4", + "object-inspect": "~1.4.0", + "quote-stream": "~1.0.2", + "readable-stream": "~2.3.3", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.0", + "through2": "~2.0.3" }, "dependencies": { "duplexer2": { @@ -8147,20 +8697,20 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "2.3.4" + "readable-stream": "^2.0.2" } }, "escodegen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", - "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", "dev": true, "requires": { - "esprima": "3.1.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.5.7" + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" } }, "esprima": { @@ -8169,12 +8719,6 @@ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -8182,35 +8726,42 @@ "dev": true }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "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.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, + "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, + "optional": true + }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" + "safe-buffer": "~5.1.0" } } } }, "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stream-consume": { @@ -8225,27 +8776,27 @@ "integrity": "sha1-kc8lac5NxQYf6816yyY5SloRR1E=", "dev": true }, - "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 - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, + "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 + }, "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", "dev": true }, "strip-ansi": { @@ -8254,7 +8805,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -8263,17 +8814,31 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "4.0.1" + "get-stdin": "^4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } } }, "strip-json-comments": { @@ -8294,8 +8859,8 @@ "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", "dev": true, "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "svgdom": { @@ -8304,10 +8869,10 @@ "integrity": "sha1-djlZYSQUjJ8eBlntNGgtN5s2dO4=", "dev": true, "requires": { - "fontkit": "1.7.7", - "gl-matrix": "2.4.0", - "image-size": "0.5.5", - "sax": "1.2.4" + "fontkit": "^1.5.4", + "gl-matrix": "^2.3.2", + "image-size": "^0.5.1", + "sax": "^1.2.2" } }, "table": { @@ -8316,24 +8881,14 @@ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.5", + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", "slice-ansi": "0.0.4", - "string-width": "2.1.1" + "string-width": "^2.0.0" }, "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -8347,9 +8902,9 @@ "dev": true }, "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true }, "string-width": { @@ -8358,8 +8913,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -8368,7 +8923,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -8397,8 +8952,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.4", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "isarray": { @@ -8408,27 +8963,27 @@ "dev": true }, "readable-stream": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", - "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "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.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" + "safe-buffer": "~5.1.0" } } } @@ -8439,7 +8994,7 @@ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "time-stamp": { @@ -8448,6 +9003,29 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + }, + "dependencies": { + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + } + } + }, "tiny-inflate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", @@ -8460,7 +9038,7 @@ "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.1" } }, "to-array": { @@ -8469,13 +9047,19 @@ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "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.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -8484,7 +9068,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -8495,10 +9079,10 @@ "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" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -8507,17 +9091,17 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "trim-newlines": { @@ -8526,6 +9110,12 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "tryit": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", @@ -8551,7 +9141,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { @@ -8561,7 +9151,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "typedarray": { @@ -8576,9 +9166,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "camelcase": { @@ -8593,8 +9183,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, @@ -8604,15 +9194,21 @@ "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 + }, "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.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } @@ -8643,24 +9239,52 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", + "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "dev": true + }, "unicode-properties": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.1.0.tgz", "integrity": "sha1-epbu9J91aC6mnSMV7smsQ//fAME=", "dev": true, "requires": { - "brfs": "1.4.4", - "unicode-trie": "0.3.1" + "brfs": "^1.4.0", + "unicode-trie": "^0.3.0" } }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", + "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "dev": true + }, "unicode-trie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz", "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=", "dev": true, "requires": { - "pako": "0.2.9", - "tiny-inflate": "1.0.2" + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" } }, "union-value": { @@ -8669,10 +9293,10 @@ "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" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -8681,7 +9305,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -8690,10 +9314,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } @@ -8722,8 +9346,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -8732,9 +9356,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -8769,82 +9393,12 @@ "dev": true }, "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { - "define-property": "0.2.5", - "isobject": "3.0.1", - "lazy-cache": "2.0.2" - }, - "dependencies": { - "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.6" - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.2.2" - }, - "dependencies": { - "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.6" - } - } - } - }, - "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.1.0" - } - }, - "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 - } + "kind-of": "^6.0.2" } }, "user-home": { @@ -8859,37 +9413,29 @@ "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { - "lru-cache": "4.1.1", - "tmp": "0.0.31" + "lru-cache": "4.1.x", + "tmp": "0.0.x" }, "dependencies": { "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } } } }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } + "inherits": "2.0.3" } }, "util-deprecate": { @@ -8905,9 +9451,9 @@ "dev": true }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.0.tgz", + "integrity": "sha512-ijO9N2xY/YaOqQ5yz5c4sy2ZjWmA6AR6zASb/gdpeKZ8+948CxwfMW9RrKVk5may6ev8c0/Xguu32e2Llelpqw==", "dev": true }, "v8flags": { @@ -8916,17 +9462,17 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "1.1.1" + "user-home": "^1.1.1" } }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "verror": { @@ -8935,9 +9481,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "assert-plus": { @@ -8954,8 +9500,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" } }, @@ -8974,14 +9520,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" }, "dependencies": { "clone": { @@ -8996,10 +9542,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "through2": { @@ -9008,8 +9554,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } }, "vinyl": { @@ -9018,8 +9564,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" } } } @@ -9030,9 +9576,15 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.1" } }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, "void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -9040,12 +9592,12 @@ "dev": true }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "window-size": { @@ -9055,9 +9607,9 @@ "dev": true }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { @@ -9066,8 +9618,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" } }, "wrappy": { @@ -9082,8 +9634,8 @@ "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", "dev": true, "requires": { - "boom": "2.10.1", - "hoek": "2.16.3" + "boom": "2.x.x", + "hoek": "2.x.x" } }, "write": { @@ -9092,7 +9644,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "ws": { @@ -9101,8 +9653,8 @@ "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", "dev": true, "requires": { - "options": "0.0.6", - "ultron": "1.0.2" + "options": ">=0.0.5", + "ultron": "1.0.x" } }, "wtf-8": { @@ -9141,13 +9693,13 @@ "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "dev": true, "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" } }, "yauzl": { @@ -9156,7 +9708,7 @@ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { - "fd-slicer": "1.0.1" + "fd-slicer": "~1.0.1" } }, "yeast": { diff --git a/package.json b/package.json index 9cc9a1d..c718bec 100644 --- a/package.json +++ b/package.json @@ -55,21 +55,27 @@ "typings": "./svg.js.d.ts", "scripts": { "build": "gulp", + "lint": "gulp lint", "build:test": "gulp unify", + "build:dev": "gulp --dont-break", "test": "karma start .config/karma.conf.js --single-run", - "test:quick": "karma start .config/karma.quick.js", - "lint": "standard --verbose | snazzy" + "test:dots": "karma start .config/karma.conf.js --single-run --reporters dots", + "test:quick": "karma start .config/karma.quick.js" }, "devDependencies": { + "@babel/core": "^7.1.2", + "@babel/preset-env": "^7.1.0", "coveralls": "^2.11.15", "del": "^2.2.0", "gulp": "^3.8.6", + "gulp-babel": "^8.0.0", "gulp-chmod": "^2.0.0", "gulp-cli": "^1.2.2", "gulp-concat": "^2.3.3", "gulp-header": "^1.0.5", "gulp-rename": "^1.2.0", "gulp-size": "^2.1.0", + "gulp-sourcemaps": "^2.6.4", "gulp-standard": "^10.1.2", "gulp-trimlines": "^1.0.0", "gulp-uglify": "^2.0.0", @@ -88,6 +94,7 @@ "standard": { "ignore": [ "/dist", + "/spec", "/src/umd.js" ], "globals": [ diff --git a/playgrounds/matrix/drag.js b/playgrounds/matrix/drag.js new file mode 100644 index 0000000..2dd6cac --- /dev/null +++ b/playgrounds/matrix/drag.js @@ -0,0 +1,68 @@ +function reactToDrag(element, onDrag, beforeDrag) { + + let xStart, yStart + let startDrag = event => { + + // Avoid the default events + event.preventDefault() + + // Store the position where the drag started + xStart = event.pageX + yStart = event.pageY + + // Fire the start drag event + if (beforeDrag) { + var { x, y } = parent.point(event.pageX, event.pageY) + beforeDrag(event, x, y) + } + + // Register events to react to dragging and drag ends + SVG.on(window, ['mousemove.drag', 'touchmove.drag'], reactDrag) + SVG.on(window, ['mouseup.drag', 'touchend.drag'], stopDrag) + } + + let reactDrag = event => { + + // Convert screen coordinates to svg coordinates and use them + var { x, y } = parent.point(event.pageX, event.pageY) + if (onDrag) + onDrag(event, x, y) + } + + let stopDrag = event => { + SVG.off(window, ['mousemove.drag', 'touchmove.drag']) + SVG.off(window, ['mouseup.drag', 'touchend.drag']) + } + + // Bind the drag tracker to this element directly + let parent = element.doc() + let point = new SVG.Point() + element.mousedown(startDrag).touchstart(startDrag) +} + +SVG.extend(SVG.Element, { + draggable: function (after) { + + let sx, sy + + reactToDrag(this, (e, x, y) => { + + this.transform({ + origin: [sx, sy], + position: [x, y], + }) + + if (after) { + after(this, x, y) + } + + }, (e, x, y) => { + + var toAbsolute = new SVG.Matrix(this).inverse() + var p = new SVG.Point(x, y).transform(toAbsolute) + sx = p.x + sy = p.y + }) + return this + }, +}) diff --git a/playgrounds/matrix/matrix.html b/playgrounds/matrix/matrix.html new file mode 100644 index 0000000..cd34b7d --- /dev/null +++ b/playgrounds/matrix/matrix.html @@ -0,0 +1,47 @@ + +<!DOCTYPE html> +<html> + + <head> + <meta charset="utf-8"> + <title>SVG Playground</title> + <link rel="stylesheet" href="../playground.css"> + </head> + + <body> + + <h1>SVG Transformations</h1> + + <p> + This playground tests the <code>compose/decompose</code> functionality in + svg matrix, as well as the draggable code and the transformations. + </p> + + <svg viewBox="-200 -200 400 400"> + + <g id="tester"> + <rect class="green" width=50 height=50 /> + <line x2=50 stroke=black stroke-width=1 /> + </g> + + <g id="guess"> + <rect class="dark-pink" width=50 height=50 opacity=0.5 /> + <line x2=50 stroke=black stroke-width=1 /> + </g> + <g id="true"> + <rect class="pink" width=50 height=50 opacity=0.5 /> + <line x2=50 stroke=black stroke-width=1 /> + </g> + <ellipse id="or" class="dark-pink" rx=5 ry=5 /> + <ellipse id="b1" class="pink" cx="50" rx=5 ry=5 /> + <ellipse id="b2" class="green" cy="50" rx=5 ry=5 /> + + </svg> + + </body> + + <script src="../../dist/svg.js" charset="utf-8"></script> + <script src="drag.js" charset="utf-8"></script> + <script src="matrix.js" charset="utf-8"></script> + +</html> diff --git a/playgrounds/matrix/matrix.js b/playgrounds/matrix/matrix.js new file mode 100644 index 0000000..33e21d1 --- /dev/null +++ b/playgrounds/matrix/matrix.js @@ -0,0 +1,41 @@ + +function print (mat) { + let {a, b, c, d} = mat + console.log(` + a: ${a.toFixed(2)} + b: ${b.toFixed(2)} + c: ${c.toFixed(2)} + d: ${d.toFixed(2)} + `) +} + +function moveit () { + + let {cx: x0, cy: y0} = or.rbox(svg) + let {cx: x1, cy: y1} = b1.rbox(svg) + let {cx: x2, cy: y2} = b2.rbox(svg) + + let m = new SVG.Matrix( + (x1 - x0) / 50, (y1 - y0) / 50, (x2 - x0) / 50, (y2 - y0) / 50, x0, y0) + let com = m.decompose() + let g = new SVG.Matrix().compose(com) + + // Transform both of the items + target.transform(m) + mover.transform(g) + + console.log(com); + print(m) + print(g) +} + +// Declare the two points +let svg = SVG('svg') +var or = SVG("#or").draggable(moveit) +var b1 = SVG("#b1").draggable(moveit) +var b2 = SVG("#b2").draggable(moveit) + +// Declare the squares +let target = SVG("#true") +let mover = SVG("#guess") +let tester = SVG("#tester") diff --git a/playgrounds/playground.css b/playgrounds/playground.css new file mode 100644 index 0000000..f327905 --- /dev/null +++ b/playgrounds/playground.css @@ -0,0 +1,70 @@ + +* { + box-sizing: border-box; +} + +html { + background-color : #fefefe; +} + +body { + margin: 0; + width: 100vw; + height: 99vh; + grid-gap: 30px; + display: inline-grid; + align-items: center; + grid-template-columns: 10vw 40vw auto 10vw; + grid-template-rows: 0 10vw auto 0; +} + +h1 { + text-align: right; + border-right: solid 3px #f06; + padding-right: 12px; + color: #f06; + font-size: 52px; + font-family: Helvetica; + grid-row: 2; + grid-column: 2; + line-height: 1.8em; +} + +p { + padding-right: 50px; + color: #444; + font-size: 18px; + font-family: Helvetica; + grid-row: 2; + grid-column: 3; +} + +svg { + height: 100%; + width: 100%; + grid-row: 3; + grid-column: 2/4; + background-color: #f5f6f7; + border-radius: 20px; + border: #f065 1px solid; +} + +.pink { + fill: #FF0066; +} + +.green { + fill: #00ff99; +} + +.dark-pink { + fill: #660029; +} + +.light-pink { + fill: #FF99C2; +} + +.off-white { + fill: #FFCCE0; +} diff --git a/playgrounds/transforms/transforms.html b/playgrounds/transforms/transforms.html new file mode 100644 index 0000000..a165dd9 --- /dev/null +++ b/playgrounds/transforms/transforms.html @@ -0,0 +1,27 @@ + +<!DOCTYPE html> +<html> + + <head> + <meta charset="utf-8"> + <title>SVG Playground</title> + <link rel="stylesheet" href="../playground.css"> + </head> + + <body> + + <h1>Transformations</h1> + + <p> + Here you can try out our transformation code, try moving around the pink + box in your console with its variable name: <code>mover</code> + </p> + + <svg viewBox="0 0 1500 1500" id="canvas"></svg> + + </body> + + <script src="../../dist/svg.js" charset="utf-8"></script> + <script src="transforms.js" charset="utf-8"></script> + +</html> diff --git a/playgrounds/transforms/transforms.js b/playgrounds/transforms/transforms.js new file mode 100644 index 0000000..1918cd7 --- /dev/null +++ b/playgrounds/transforms/transforms.js @@ -0,0 +1,23 @@ + + +let canvas = SVG('#canvas') + +// Make the green rectange +canvas.rect(200, 400).move(200, 400) + .attr('opacity', 0.3) + .addClass('green') + +// Make the pink rectangle +let a = canvas.rect(200, 400).move(200, 400) + .attr('opacity', 0.3) + .addClass('pink') + .transform({ px: 100, py: 500, origin: 'top-left' }) + +debugger + a.animate() + .rotate({ rotate: 500, origin: 'top-right' }) + +// Put an ellipse where we expect the object to be +canvas.ellipse(30, 30).center(100, 500) + .attr('opacity', 0.3) + .addClass('dark-pink') diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html index bd47626..2a9b8d8 100644 --- a/spec/SpecRunner.html +++ b/spec/SpecRunner.html @@ -10,11 +10,19 @@ <script src="lib/jasmine-2.6.0/jasmine.js"></script> <script src="lib/jasmine-2.6.0/jasmine-html.js"></script> <script src="lib/jasmine-2.6.0/boot.js"></script> + <script src="lib/RAFPlugin.js"></script> <link rel="stylesheet" href="fixtures/fixture.css"> <!-- include source files here... --> <script src="../dist/svg.js" charset="utf-8"></script> + <script type="text/javascript" src="../src/helpers.js"></script> + <script type="text/javascript" src="../src/transform.js"></script> + <script type="text/javascript" src="../src/matrix.js"></script> + <script type="text/javascript" src="../src/morph.js"></script> + <script type="text/javascript" src="../src/runner.js"></script> + <script type="text/javascript" src="../src/timeline.js"></script> + <script type="text/javascript" src="../src/controller.js"></script> </head> @@ -52,6 +60,7 @@ <!-- include spec files here... --> + <!-- <script src="spec/adopter.js"></script> <script src="spec/arrange.js"></script> <script src="spec/array.js"></script> @@ -68,17 +77,15 @@ <script src="spec/ellipse.js"></script> <script src="spec/event.js"></script> <script src="spec/fx.js"></script> - <script src="spec/gradient.js"></script> - <script src="spec/group.js"></script> + <script src="spec/gradient.js"></script>--> <script src="spec/helper.js"></script> - <script src="spec/hyperlink.js"></script> + <!--<script src="spec/hyperlink.js"></script> <script src="spec/image.js"></script> <script src="spec/line.js"></script> <script src="spec/marker.js"></script> - <script src="spec/mask.js"></script> - <script src="spec/matrix.js"></script> - <script src="spec/memory.js"></script> - <script src="spec/number.js"></script> + <script src="spec/mask.js"></script>--> + <!--<script src="spec/matrix.js"></script>--> + <!--<script src="spec/number.js"></script> <script src="spec/path.js"></script> <script src="spec/pattern.js"></script> <script src="spec/point.js"></script> @@ -96,7 +103,10 @@ <script src="spec/tspan.js"></script> <script src="spec/use.js"></script> <script src="spec/utils.js"></script> - <script src="spec/viewbox.js"></script> + <script src="spec/viewbox.js"></script> --> + <script src="spec/morphing.js"></script> + <script src="spec/animator.js"></script> + <script src="spec/runner.js"></script> </body> </html> diff --git a/spec/lib/RAFPlugin.js b/spec/lib/RAFPlugin.js new file mode 100644 index 0000000..fefdda6 --- /dev/null +++ b/spec/lib/RAFPlugin.js @@ -0,0 +1,82 @@ +/** + * Jasmine RequestAnimationFrame: a set of helpers for testing funcionality + * that uses requestAnimationFrame under the Jasmine BDD framework for JavaScript. + */ +;(function() { + + var index = 0, + callbacks = []; + + function MockRAF(global) { + this.realRAF = global.requestAnimationFrame, + this.realCAF = global.cancelAnimationFrame, + this.realPerf = global.performance, + this.nextTime = 0 + + var _this = this + + /** + * Mock for window.requestAnimationFrame + */ + this.mockRAF = function(fn) { + if (typeof fn !== 'function') { + throw new Error('You should pass a function to requestAnimationFrame'); + } + + callbacks[index++] = fn; + + return index; + }; + + /** + * Mock for window.cancelAnimationFrame + */ + this.mockCAF = function(requestID) { + callbacks.splice(requestID, 1) + }; + + this.mockPerf = { + now: function () { + return _this.nextTime + } + } + + /** + * Install request animation frame mocks. + */ + this.install = function() { + global.requestAnimationFrame = _this.mockRAF; + global.cancelAnimationFrame = _this.mockCAF; + global.performance = _this.mockPerf; + }; + + /** + * Uninstall request animation frame mocks. + */ + this.uninstall = function() { + global.requestAnimationFrame = _this.realRAF; + global.cancelAnimationFrame = _this.realCAF; + global.performance = _this.realPerf; + }; + + /** + * Simulate animation frame readiness. + */ + this.tick = function(dt) { + _this.nextTime += (dt || 1) + + var fns = callbacks, fn, i; + + callbacks = []; + index = 0; + + for (i in fns) { + fn = fns[i]; + fn(_this.nextTime); + } + }; + } + + + jasmine.RequestAnimationFrame = new MockRAF(window); +}()); diff --git a/spec/spec/animator.js b/spec/spec/animator.js new file mode 100644 index 0000000..a36408c --- /dev/null +++ b/spec/spec/animator.js @@ -0,0 +1,49 @@ +describe('SVG.Animator', function () { + + beforeEach(function () { + jasmine.RequestAnimationFrame.install() + SVG.Animator.timer = jasmine.RequestAnimationFrame.mockPerf + }) + + afterEach(function () { + jasmine.RequestAnimationFrame.uninstall() + SVG.Animator.timer = jasmine.RequestAnimationFrame.realPerf + }) + + describe('timeout()', function () { + it('calls a function after a specific time', function () { + + var spy = jasmine.createSpy('tester') + var id = SVG.Animator.timeout(spy, 100) + + jasmine.RequestAnimationFrame.tick(99) + expect(spy).not.toHaveBeenCalled() + jasmine.RequestAnimationFrame.tick() + expect(spy).toHaveBeenCalled() + }) + }) + + describe('cancelTimeout()', function () { + it('cancels a timeout which was created with timeout()', function () { + var spy = jasmine.createSpy('tester') + var id = SVG.Animator.timeout(spy, 100) + SVG.Animator.clearTimeout(id) + + expect(spy).not.toHaveBeenCalled() + jasmine.RequestAnimationFrame.tick(100) + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('frame()', function () { + it('calls a function at the next animationFrame', function () { + var spy = jasmine.createSpy('tester') + + SVG.Animator.frame(spy) + expect(spy).not.toHaveBeenCalled() + jasmine.RequestAnimationFrame.tick() + expect(spy).toHaveBeenCalled() + }) + }) + +}) diff --git a/spec/spec/boxes.js b/spec/spec/boxes.js index 9e33c60..934f472 100644 --- a/spec/spec/boxes.js +++ b/spec/spec/boxes.js @@ -163,7 +163,7 @@ describe('Boxes', function() { offset = draw.screenCTM() draw.viewbox(100,100, 200, 200) nested = draw.nested().size(200, 200).move(100,100).viewbox(0, 0, 100, 100) - rect = nested.rect(50, 180).stroke({width:0}).move(25, 90).scale(2, 0, 0).transform({x:10, y:10}, true) + rect = nested.rect(50, 180).stroke({width:0}).move(25, 90).transform({scale: 2, origin: [0, 0]}).relative(10, 10) }) afterEach(function() { draw.clear().attr('viewBox', null) @@ -269,9 +269,3 @@ describe('Boxes', function() { }) }) - - - - - - diff --git a/spec/spec/circle.js b/spec/spec/circle.js index fc66e0c..0f2c8f4 100644 --- a/spec/spec/circle.js +++ b/spec/spec/circle.js @@ -1,14 +1,15 @@ + describe('Circle', function() { var circle - + beforeEach(function() { circle = draw.circle(240) }) - + afterEach(function() { draw.clear() }) - + describe('x()', function() { it('returns the value of x without an argument', function() { expect(circle.x()).toBe(0) @@ -19,7 +20,7 @@ describe('Circle', function() { expect(box.x).toBeCloseTo(123) }) }) - + describe('y()', function() { it('returns the value of y without an argument', function() { expect(circle.y()).toBe(0) @@ -30,7 +31,7 @@ describe('Circle', function() { expect(box.y).toBe(345) }) }) - + describe('cx()', function() { it('returns the value of cx without an argument', function() { expect(circle.cx()).toBe(120) @@ -41,7 +42,7 @@ describe('Circle', function() { expect(box.cx).toBe(123) }) }) - + describe('cy()', function() { it('returns the value of cy without an argument', function() { expect(circle.cy()).toBe(120) @@ -81,7 +82,7 @@ describe('Circle', function() { expect(circle.node.getAttribute('r')).toBe('120') }) }) - + describe('move()', function() { it('sets the x and y position', function() { circle.move(123, 456) @@ -115,7 +116,7 @@ describe('Circle', function() { expect(circle.node.getAttribute('cy')).toBe('205') }) }) - + describe('center()', function() { it('sets the cx and cy position', function() { circle.center(321,567) @@ -144,24 +145,24 @@ describe('Circle', function() { expect((circle.height() / 2).toString()).toBe(circle.node.getAttribute('r')) }) }) - + describe('size()', function() { it('defines the r of the element', function() { circle.size(987) expect(circle.node.getAttribute('r')).toBe((987 / 2).toString()) }) }) - + describe('scale()', function() { it('should scale the element universally with one argument', function() { var box = circle.scale(2).rbox() - + expect(box.width).toBe(circle.attr('r') * 2 * 2) expect(box.height).toBe(circle.attr('r') * 2 * 2) }) it('should scale the element over individual x and y axes with two arguments', function() { var box = circle.scale(2, 3.5).rbox() - + expect(box.width).toBe(circle.attr('r') * 2 * 2) expect(box.height).toBe(circle.attr('r') * 2 * 3.5) }) @@ -169,9 +170,8 @@ describe('Circle', function() { describe('translate()', function() { it('sets the translation of an element', function() { - circle.transform({ x: 12, y: 12 }) + circle.transform({ tx: 12, ty: 12 }) expect(window.matrixStringToArray(circle.node.getAttribute('transform'))).toEqual([1,0,0,1,12,12]) }) }) - }) diff --git a/spec/spec/doc.js b/spec/spec/doc.js index 5accd5b..f82f1cb 100644 --- a/spec/spec/doc.js +++ b/spec/spec/doc.js @@ -41,9 +41,7 @@ describe('Doc', function() { expect(SVG().addTo(document.createElement('div')).isRoot()).toBe(true) }) it('returns true when its the root element of the dom', function () { - if(parserInDoc) { - expect(draw.isRoot()).toBe(true) - } + expect(draw.isRoot()).toBe(true) }) it('returns false when parent is svg element', function () { expect(SVG().addTo(SVG()).isRoot()).toBe(false) @@ -59,7 +57,7 @@ describe('Doc', function() { }else{ expect(window.document.querySelectorAll('svg').length).toBe(cnt-1) } - + draw = SVG().addTo(drawing).size(100,100); expect(window.document.querySelectorAll('svg').length).toBe(cnt) }) diff --git a/spec/spec/element.js b/spec/spec/element.js index 53ed84f..41f2af4 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -134,13 +134,13 @@ describe('Element', function() { it('increases the global id sequence', function() { var did = SVG.did rect.id() - + expect(did + 1).toBe(SVG.did) }) it('adds a unique id containing the node name', function() { var did = SVG.did rect.id() - + expect(rect.attr('id')).toBe('SvgjsRect' + did) }) it('gets the value if the id attribute without an argument', function() { @@ -194,23 +194,23 @@ describe('Element', function() { rect = draw.rect(100,100) }) - it('gets the current transformations', function() { - expect(rect.transform()).toEqual(new SVG.Matrix(rect).extract()) + it('gets the current transformation matrix', function() { + expect(rect.transform()).toEqual(jasmine.objectContaining({ + a: 1, b: 0, c: 0, d: 1, e: 0, f: 0, + scaleX: 1, scaleY: 1, shear: 0, rotate: 0, + translateX: 0, translateY: 0, + })) }) it('sets the translation of and element', function() { - rect.transform({ x: 10, y: 11 }) + rect.transform({ translate: [10, 11] }) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,10,11]) }) it('performs an absolute translation', function() { - rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21 }) + rect.transform({ translate: [10, 11] }).transform({ translate: [20, 21] }) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,20,21]) }) - it('performs a relative translation when relative is set to true', function() { - rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21, relative: true }) - expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,30,32]) - }) it('performs a relative translation with relative flag', function() { - rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21 }, true) + rect.transform({ translate: [10, 11] }).transform({ translate: [20, 21] }, true) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,30,32]) }) it('sets the scaleX and scaleY of an element', function() { @@ -248,7 +248,7 @@ describe('Element', function() { expect(ctm.f).toBe(0) }) it('sets the skewX of an element with given center', function() { - ctm = rect.transform({ skewX: 10, cx: 0, cy: 0 }).ctm() + ctm = rect.transform({ skewX: 10, ox: 0, oy: 0 }).ctm() expect(ctm.a).toBe(1) expect(ctm.b).toBe(0) expect(ctm.c).toBeCloseTo(0.17632698070846498) @@ -257,7 +257,7 @@ describe('Element', function() { expect(ctm.f).toBe(0) }) it('sets the skewY of an element', function() { - ctm = rect.transform({ skewY: -10, cx: 0, cy: 0 }).ctm() + ctm = rect.transform({ skewY: -10, ox: 0, oy: 0 }).ctm() expect(ctm.a).toBe(1) expect(ctm.b).toBeCloseTo(-0.17632698070846498) expect(ctm.c).toBe(0) @@ -266,7 +266,7 @@ describe('Element', function() { expect(ctm.f).toBe(0) }) it('sets the skewX and skewY of an element', function() { - ctm = rect.transform({ skewX: 10, skewY: -10, cx: 0, cy: 0 }).ctm() + ctm = rect.transform({ skewX: 10, skewY: -10, ox: 0, oy: 0 }).ctm() expect(ctm.a).toBe(1) expect(ctm.b).toBeCloseTo(-0.17632698070846498) expect(ctm.c).toBeCloseTo(0.17632698070846498) @@ -275,7 +275,7 @@ describe('Element', function() { expect(ctm.f).toBe(0) }) it('performs a uniform skew with skew given', function() { - ctm = rect.transform({ skew: 5, cx: 0, cy: 0 }).ctm() + ctm = rect.transform({ skew: 5, ox: 0, oy: 0 }).ctm() expect(ctm.a).toBe(1) expect(ctm.b).toBeCloseTo(0.08748866352592401) expect(ctm.c).toBeCloseTo(0.08748866352592401) @@ -284,17 +284,16 @@ describe('Element', function() { expect(ctm.f).toBe(0) }) it('rotates the element around its centre if no rotation point is given', function() { - ctm = rect.center(100, 100).transform({ rotation: 45 }).ctm() + ctm = rect.center(100, 100).transform({ rotate: 45 }).ctm() expect(ctm.a).toBeCloseTo(0.7071068286895752) expect(ctm.b).toBeCloseTo(0.7071068286895752) expect(ctm.c).toBeCloseTo(-0.7071068286895752) expect(ctm.d).toBeCloseTo(0.7071068286895752) expect(ctm.e).toBeCloseTo(100) expect(ctm.f).toBeCloseTo(-41.421356201171875) - expect(rect.transform('rotation')).toBe(45) }) it('rotates the element around the given rotation point', function() { - ctm = rect.transform({ rotation: 55, cx: 80, cy:2 }).ctm() + ctm = rect.transform({ rotate: 55, origin: [80, 2] }).ctm() expect(ctm.a).toBeCloseTo(0.5735765099525452) expect(ctm.b).toBeCloseTo(0.8191521167755127) expect(ctm.c).toBeCloseTo(-0.8191521167755127) @@ -315,15 +314,15 @@ describe('Element', function() { expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,1,100,0]) }) it('flips the element on x axis with offset', function() { - rect.transform({ flip: 'x', offset: 20 }) + rect.transform({ flip: 'x', origin: [20, 0] }) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,1,40,0]) }) it('flips the element on y axis with offset', function() { - rect.transform({ flip: 'y', offset: 20 }) + rect.transform({ flip: 'y', origin: [0, 20] }) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,-1,0,40]) }) it('flips the element on both axis with offset', function() { - rect.transform({ flip: 'both', offset: 20 }) + rect.transform({ flip: 'both', origin: [20, 20] }) expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,-1,40,40]) }) it('flips the element on both axis', function() { @@ -386,6 +385,20 @@ describe('Element', function() { rect.attr('transform', 'translate(24,14) , translate(36,6)') expect(rect.matrixify().toString()).toBe('matrix(1,0,0,1,60,20)') }) + + + it('merges non-commutative transformations correctly', function() { + // Spaces before the comma + rect.attr('transform', 'scale(3, 2) translate(20,16)') + expect(rect.matrixify().toString()).toBe('matrix(3,0,0,2,60,32)') + }) + + it('doesn\'t care if you have matrices there', function() { + // Spaces before the comma + rect.attr('transform', 'matrix(3, 0, 0, 2, 0, 0) translate(20,16)') + expect(rect.matrixify().toString()).toBe('matrix(3,0,0,2,60,32)') + }) + }) describe('toParent()', function() { @@ -408,13 +421,11 @@ describe('Element', function() { }) it('moves the element to other parent while maintaining the same visal representation', function() { - expect(rect1.toParent(nested).transform()).toEqual(jasmine.objectContaining({ - a:2, b:0, c:0, d:2, e:70, f:70 - })) + expect(window.roundMatrix(rect1.toParent(nested).matrix())) + .toEqual(new SVG.Matrix(2, 0, 0, 2, 70, 70)) expect(rect1.parent()).toEqual(nested) - expect(rect2.toParent(g2).transform()).toEqual(jasmine.objectContaining({ - a:0.5, b:0, c:0, d:0.5, e:-95, f:-95 - })) + expect(window.roundMatrix(rect2.toParent(g2).matrix())) + .toEqual(new SVG.Matrix(0.5, 0, 0, 0.5, -95, -95)) expect(rect2.parent()).toEqual(g2) }) }) @@ -466,17 +477,13 @@ describe('Element', function() { expect(g1.node.parentNode).toBeFalsy() expect(g2.node.parentNode).toBeFalsy() - expect(rect1.transform()).toEqual(jasmine.objectContaining({ - a:2, b:0, c:0, d:2, e:70, f:70 - })) - expect(rect2.transform()).toEqual(jasmine.objectContaining({ - a:0.5, b:0, c:0, d:0.5, e:45, f:45 - })) + expect(window.roundMatrix(rect1.matrix())).toEqual(new SVG.Matrix(2, 0, 0, 2, 70, 70)) + expect(window.roundMatrix(rect2.matrix())).toEqual(new SVG.Matrix(0.5, 0, 0, 0.5, 45, 45)) }) it('ungroups everything to the doc root when called on SVG.Doc / does not ungroup defs/parser', function() { draw.flatten() - + expect(rect1.parent()).toBe(draw) expect(rect2.parent()).toBe(draw) @@ -484,12 +491,8 @@ describe('Element', function() { expect(g2.node.parentNode).toBeFalsy() expect(nested.node.parentNode).toBeFalsy() - expect(rect1.transform()).toEqual(jasmine.objectContaining({ - a:2, b:0, c:0, d:2, e:70, f:70 - })) - expect(rect2.transform()).toEqual(jasmine.objectContaining({ - a:0.5, b:0, c:0, d:0.5, e:45, f:45 - })) + expect(window.roundMatrix(rect1.matrix())).toEqual(new SVG.Matrix(2, 0, 0, 2, 70, 70)) + expect(window.roundMatrix(rect2.matrix())).toEqual(new SVG.Matrix(0.5, 0, 0, 0.5, 45, 45)) expect(draw.children().length).toBe(3+parserInDoc) // 2 * rect + defs }) diff --git a/spec/spec/ellipse.js b/spec/spec/ellipse.js index f6aa271..76f16e6 100644 --- a/spec/spec/ellipse.js +++ b/spec/spec/ellipse.js @@ -1,14 +1,14 @@ describe('Ellipse', function() { var ellipse - + beforeEach(function() { ellipse = draw.ellipse(240,90) }) - + afterEach(function() { draw.clear() }) - + describe('x()', function() { it('returns the value of x without an argument', function() { expect(ellipse.x()).toBe(0) @@ -19,7 +19,7 @@ describe('Ellipse', function() { expect(box.x).toBeCloseTo(123) }) }) - + describe('y()', function() { it('returns the value of y without an argument', function() { expect(ellipse.y()).toBe(0) @@ -30,7 +30,7 @@ describe('Ellipse', function() { expect(box.y).toBe(345) }) }) - + describe('cx()', function() { it('returns the value of cx without an argument', function() { expect(ellipse.cx()).toBe(120) @@ -41,7 +41,7 @@ describe('Ellipse', function() { expect(box.cx).toBe(123) }) }) - + describe('cy()', function() { it('returns the value of cy without an argument', function() { expect(ellipse.cy()).toBe(45) @@ -70,7 +70,7 @@ describe('Ellipse', function() { expect(ellipse.node.getAttribute('ry')).toBe('0') }) }) - + describe('move()', function() { it('sets the x and y position', function() { ellipse.move(123, 456) @@ -104,7 +104,7 @@ describe('Ellipse', function() { expect(ellipse.node.getAttribute('cy')).toBe('130') }) }) - + describe('center()', function() { it('sets the cx and cy position', function() { ellipse.center(321,567) @@ -133,7 +133,7 @@ describe('Ellipse', function() { expect((ellipse.height() / 2).toString()).toBe(ellipse.node.getAttribute('ry')) }) }) - + describe('size()', function() { it('defines the rx and ry of the element', function() { ellipse.size(987,654) @@ -153,17 +153,17 @@ describe('Ellipse', function() { expect(ellipse.width() / ellipse.height()).toBe(box.width / box.height) }) }) - + describe('scale()', function() { it('should scale the element universally with one argument', function() { var box = ellipse.scale(2).rbox() - + expect(box.width).toBe(ellipse.attr('rx') * 2 * 2) expect(box.height).toBe(ellipse.attr('ry') * 2 * 2) }) it('should scale the element over individual x and y axes with two arguments', function() { var box = ellipse.scale(2, 3.5).rbox() - + expect(box.width).toBe(ellipse.attr('rx') * 2 * 2) expect(box.height).toBe(ellipse.attr('ry') * 2 * 3.5) }) @@ -171,17 +171,9 @@ describe('Ellipse', function() { describe('translate()', function() { it('sets the translation of an element', function() { - ellipse.transform({ x: 12, y: 12 }) + ellipse.transform({ tx: 12, ty: 12 }) expect(ellipse.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) - -}) - - - - - - - +}) diff --git a/spec/spec/fx.js b/spec/spec/fx.js index 5186016..e813cf1 100644 --- a/spec/spec/fx.js +++ b/spec/spec/fx.js @@ -1729,252 +1729,252 @@ describe('FX', function() { expect(called).toBe(true) }) - it('animates matrix', function() { - var ctm, called = false - - fx.transform({a:0.8, b:0.4, c:-0.15, d:0.7, e: 90.3, f: 27.07}).after(function(){ - - var ctm = rect.ctm() - expect(ctm.a).toBeCloseTo(0.8) - expect(ctm.b).toBeCloseTo(0.4) - expect(ctm.c).toBeCloseTo(-0.15) - expect(ctm.d).toBeCloseTo(0.7) - expect(ctm.e).toBeCloseTo(90.3) - expect(ctm.f).toBeCloseTo(27.07) - called = true - - }) - - jasmine.clock().tick(250) - fx.step() - ctm = rect.ctm() - expect(ctm.a).toBeLessThan(1) - expect(ctm.b).toBeGreaterThan(0) - expect(ctm.c).toBeLessThan(0) - expect(ctm.d).toBeGreaterThan(0) - expect(ctm.e).toBeGreaterThan(0) - expect(ctm.f).toBeGreaterThan(0) - - jasmine.clock().tick(250) - fx.step() - expect(called).toBe(true) - }) - - it('animate a scale transform using the passed center point when there is already a transform in place', function(){ - var ctm - - // When no ceter point is passed to the method scale, it use the center of the element as the center point - - rect.scale(2) // The transform in place - - fx.scale(0.5) - jasmine.clock().tick(500) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(0.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(0.5) - expect(ctm.e).toBe(75) - expect(ctm.f).toBe(75) - }) - - it('animate a flip(x) transform', function() { - var ctm - - fx.transform({flip: 'x'}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(0.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(1) - expect(ctm.e).toBe(75) - expect(ctm.f).toBe(0) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(-1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(1) - expect(ctm.e).toBe(300) - expect(ctm.f).toBe(0) - }) - - it('animate a flip(x) transform with an offset', function() { - var ctm - - fx.transform({flip: 'x', offset: 20}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(0.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(1) - expect(ctm.e).toBe(10) - expect(ctm.f).toBe(0) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(-1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(1) - expect(ctm.e).toBe(40) - expect(ctm.f).toBe(0) - }) - - it('animate a flip(y) transform', function() { - var ctm - - fx.transform({flip: 'y'}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(0.5) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(75) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(-1) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(300) - }) - - it('animate a flip(y) transform with an offset', function() { - var ctm - - fx.transform({flip: 'y', offset: 20}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(0.5) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(10) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(-1) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(40) - }) - - it('animate a flip() transform', function() { - var ctm - - fx.transform({flip: 'both'}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(0.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(0.5) - expect(ctm.e).toBe(75) - expect(ctm.f).toBe(75) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(-1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(-1) - expect(ctm.e).toBe(300) - expect(ctm.f).toBe(300) - }) - - it('animate a flip() transform with an offset', function() { - var ctm - - fx.transform({flip: 'both', offset: 20}).start() - - jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(0.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(0.5) - expect(ctm.e).toBe(10) - expect(ctm.f).toBe(10) - - jasmine.clock().tick(475) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(-1) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(-1) - expect(ctm.e).toBe(40) - expect(ctm.f).toBe(40) - }) - - it('animate relative matrix transform', function(){ - var ctm - - fx.transform(new SVG.Matrix().scale(2,0,0), true) - - jasmine.clock().tick(250) // Have the animation be half way - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(1.5) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(1.5) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(0) - - jasmine.clock().tick(250) // Have the animation reach its end - fx.step() - - ctm = rect.ctm() - expect(ctm.a).toBe(2) - expect(ctm.b).toBe(0) - expect(ctm.c).toBe(0) - expect(ctm.d).toBe(2) - expect(ctm.e).toBe(0) - expect(ctm.f).toBe(0) - }) + // it('animates matrix', function() { + // var ctm, called = false + // + // fx.transform({a:0.8, b:0.4, c:-0.15, d:0.7, e: 90.3, f: 27.07}).after(function(){ + // + // var ctm = rect.ctm() + // expect(ctm.a).toBeCloseTo(0.8) + // expect(ctm.b).toBeCloseTo(0.4) + // expect(ctm.c).toBeCloseTo(-0.15) + // expect(ctm.d).toBeCloseTo(0.7) + // expect(ctm.e).toBeCloseTo(90.3) + // expect(ctm.f).toBeCloseTo(27.07) + // called = true + // + // }) + // + // jasmine.clock().tick(250) + // fx.step() + // ctm = rect.ctm() + // expect(ctm.a).toBeLessThan(1) + // expect(ctm.b).toBeGreaterThan(0) + // expect(ctm.c).toBeLessThan(0) + // expect(ctm.d).toBeGreaterThan(0) + // expect(ctm.e).toBeGreaterThan(0) + // expect(ctm.f).toBeGreaterThan(0) + // + // jasmine.clock().tick(250) + // fx.step() + // expect(called).toBe(true) + // }) + + // it('animate a scale transform using the passed center point when there is already a transform in place', function(){ + // var ctm + // + // // When no ceter point is passed to the method scale, it use the center of the element as the center point + // + // rect.scale(2) // The transform in place + // + // fx.scale(0.5) + // jasmine.clock().tick(500) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(0.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(0.5) + // expect(ctm.e).toBe(75) + // expect(ctm.f).toBe(75) + // }) + + // it('animate a flip(x) transform', function() { + // var ctm + // + // fx.transform({flip: 'x'}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(0.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(1) + // expect(ctm.e).toBe(75) + // expect(ctm.f).toBe(0) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(-1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(1) + // expect(ctm.e).toBe(300) + // expect(ctm.f).toBe(0) + // }) + + // it('animate a flip(x) transform with an offset', function() { + // var ctm + // + // fx.transform({flip: 'x', offset: 20}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(0.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(1) + // expect(ctm.e).toBe(10) + // expect(ctm.f).toBe(0) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(-1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(1) + // expect(ctm.e).toBe(40) + // expect(ctm.f).toBe(0) + // }) + + // it('animate a flip(y) transform', function() { + // var ctm + // + // fx.transform({flip: 'y'}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(0.5) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(75) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(-1) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(300) + // }) + + // it('animate a flip(y) transform with an offset', function() { + // var ctm + // + // fx.transform({flip: 'y', offset: 20}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(0.5) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(10) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(-1) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(40) + // }) + + // it('animate a flip() transform', function() { + // var ctm + // + // fx.transform({flip: 'both'}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(0.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(0.5) + // expect(ctm.e).toBe(75) + // expect(ctm.f).toBe(75) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(-1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(-1) + // expect(ctm.e).toBe(300) + // expect(ctm.f).toBe(300) + // }) + + // it('animate a flip() transform with an offset', function() { + // var ctm + // + // fx.transform({flip: 'both', offset: 20}).start() + // + // jasmine.clock().tick(125) // Have the animation be 1/4 of the way (not halfway as usual because of a bug in the node method getCTM on Firefox) + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(0.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(0.5) + // expect(ctm.e).toBe(10) + // expect(ctm.f).toBe(10) + // + // jasmine.clock().tick(475) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(-1) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(-1) + // expect(ctm.e).toBe(40) + // expect(ctm.f).toBe(40) + // }) + + // it('animate relative matrix transform', function(){ + // var ctm + // + // fx.transform(new SVG.Matrix().scale(2,0,0), true) + // + // jasmine.clock().tick(250) // Have the animation be half way + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(1.5) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(1.5) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(0) + // + // jasmine.clock().tick(250) // Have the animation reach its end + // fx.step() + // + // ctm = rect.ctm() + // expect(ctm.a).toBe(2) + // expect(ctm.b).toBe(0) + // expect(ctm.c).toBe(0) + // expect(ctm.d).toBe(2) + // expect(ctm.e).toBe(0) + // expect(ctm.f).toBe(0) + // }) describe('when animating plots', function() { it('should allow plot animations to be chained', function() { @@ -2154,7 +2154,7 @@ describe('FX', function() { var path = 'M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100' var textPath = text.path(path).font({ size: 42.5, family: 'Verdana' }) - + textPath.attr('startOffset', startValue) fx = textPath.animate(1000).attr('startOffset', endValue) @@ -2684,72 +2684,72 @@ describe('FX', function() { }) }) - describe('transform()', function() { - it('returns itself when no valid transformation was found', function() { - expect(fx.transform({})).toBe(fx) - }) - it('gets the current transforms', function() { - expect(fx.transform()).toEqual(new SVG.Matrix(rect).extract()) - }) - it('gets a certain transformation if used with an argument', function() { - expect(fx.transform('x')).toEqual(0) - }) - it('adds an entry to transforms when matrix given', function() { - var matrix = new SVG.Matrix(1,2,3,4,5,6) - fx.transform(matrix) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(matrix)) - }) - it('sets relative flag when given', function() { - var matrix = new SVG.Matrix(1,2,3,4,5,6) - fx.transform(matrix, true) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(matrix)) - expect(fx.situation.transforms[0].relative).toBe(true) - }) - it('adds an entry to transforms when rotation given', function() { - fx.transform({rotation: 30, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Rotate(30, 0, 0))) - }) - it('adds an entry to transforms when scale given', function() { - fx.transform({scale: 2, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(2, 2, 0, 0))) - }) - it('adds an entry to transforms when scaleX given', function() { - fx.transform({scaleX: 2, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(2, 1, 0, 0))) - }) - it('adds an entry to transforms when scaleY given', function() { - fx.transform({scaleY: 2, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(1, 2, 0, 0))) - }) - it('adds an entry to transforms when skewX given', function() { - fx.transform({skewX: 2, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Skew(2, 0, 0, 0))) - }) - it('adds an entry to transforms when skewY given', function() { - fx.transform({skewY: 2, cx:0, cy:0}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Skew(0, 2, 0, 0))) - }) - it('adds an entry to transforms when flip x given', function() { - fx.transform({flip: 'x'}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('x', 150))) - }) - it('adds an entry to transforms when flip x with offset given', function() { - fx.transform({flip: 'x', offset: 100}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('x', 100))) - }) - it('adds an entry to transforms when flip y given', function() { - fx.transform({flip: 'y'}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('y', 150))) - }) - it('adds an entry to transforms when x given', function() { - fx.transform({x:20}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Translate(20, undefined))) - }) - it('adds an entry to transforms when y given', function() { - fx.transform({y:20}) - expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Translate(undefined, 20))) - }) - }) + // describe('transform()', function() { + // it('returns itself when no valid transformation was found', function() { + // expect(fx.transform({})).toBe(fx) + // }) + // it('gets the current transforms', function() { + // expect(fx.transform()).toEqual(new SVG.Matrix(rect).extract()) + // }) + // it('gets a certain transformation if used with an argument', function() { + // expect(fx.transform('x')).toEqual(0) + // }) + // it('adds an entry to transforms when matrix given', function() { + // var matrix = new SVG.Matrix(1,2,3,4,5,6) + // fx.transform(matrix) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(matrix)) + // }) + // it('sets relative flag when given', function() { + // var matrix = new SVG.Matrix(1,2,3,4,5,6) + // fx.transform(matrix, true) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(matrix)) + // expect(fx.situation.transforms[0].relative).toBe(true) + // }) + // it('adds an entry to transforms when rotation given', function() { + // fx.transform({rotation: 30, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Rotate(30, 0, 0))) + // }) + // it('adds an entry to transforms when scale given', function() { + // fx.transform({scale: 2, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(2, 2, 0, 0))) + // }) + // it('adds an entry to transforms when scaleX given', function() { + // fx.transform({scaleX: 2, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(2, 1, 0, 0))) + // }) + // it('adds an entry to transforms when scaleY given', function() { + // fx.transform({scaleY: 2, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Scale(1, 2, 0, 0))) + // }) + // it('adds an entry to transforms when skewX given', function() { + // fx.transform({skewX: 2, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Skew(2, 0, 0, 0))) + // }) + // it('adds an entry to transforms when skewY given', function() { + // fx.transform({skewY: 2, cx:0, cy:0}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Skew(0, 2, 0, 0))) + // }) + // it('adds an entry to transforms when flip x given', function() { + // fx.transform({flip: 'x'}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('x', 150))) + // }) + // it('adds an entry to transforms when flip x with offset given', function() { + // fx.transform({flip: 'x', offset: 100}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('x', 100))) + // }) + // it('adds an entry to transforms when flip y given', function() { + // fx.transform({flip: 'y'}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining((new SVG.Matrix()).flip('y', 150))) + // }) + // it('adds an entry to transforms when x given', function() { + // fx.transform({x:20}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Translate(20, undefined))) + // }) + // it('adds an entry to transforms when y given', function() { + // fx.transform({y:20}) + // expect(fx.situation.transforms[0]).toEqual(jasmine.objectContaining(new SVG.Translate(undefined, 20))) + // }) + // }) /* shortcuts for animation */ describe('animate()', function() { diff --git a/spec/spec/group.js b/spec/spec/group.js deleted file mode 100644 index 4d5ff36..0000000 --- a/spec/spec/group.js +++ /dev/null @@ -1,116 +0,0 @@ -describe('Group', function() { - var group - - beforeEach(function() { - group = draw.group().move(50, 50) - group.rect(100,100) - }) - - afterEach(function() { - draw.clear() - }) - - describe('x()', function() { - it('returns the value of x without an argument', function() { - expect(group.x()).toBe(50) - }) - it('sets the value of x with the first argument', function() { - group.x(123) - var box = group.gbox() - expect(box.x).toBe(123) - }) - it('sets the value of x correctly when called multiple times', function() { - group.x(10).x(100).x(13) - var box = group.gbox() - expect(box.x).toBe(13) - }) - it('sets the value of x correctly when the first argument is a string number', function(){ - group.x('123') - var box = group.gbox() - expect(box.x).toBe(123) - }) - }) - - describe('y()', function() { - it('returns the value of y without an argument', function() { - expect(group.y()).toBe(50) - }) - it('sets the value of y with the first argument', function() { - group.y(345) - var box = group.gbox() - expect(box.y).toBe(345) - }) - it('sets the value of y correctly when called multiple times', function() { - group.y(1).y(10).y(15) - var box = group.gbox() - expect(box.y).toBe(15) - }) - it('sets the value of y correctly when the first argument is a string number', function(){ - group.y('124') - var box = group.gbox() - expect(box.y).toBe(124) - }) - }) - - describe('cx()', function() { - it('returns the value of cx without an argument', function() { - expect(group.cx()).toBe(100) - }) - it('sets the value of cx with the first argument', function() { - group.cx(123) - var box = group.gbox() - expect(box.cx).toBe(123) - }) - }) - - describe('cy()', function() { - it('returns the value of cy without an argument', function() { - expect(group.cy()).toBe(100) - }) - it('sets the value of cy with the first argument', function() { - group.cy(345) - var box = group.gbox() - expect(box.cy).toBe(345) - }) - }) - - describe('move()', function() { - it('sets the x and y position', function() { - group.move(123,456) - expect(group.node.getAttribute('transform')).toBe('matrix(1,0,0,1,123,456)') - }) - }) - - describe('center()', function() { - it('sets the cx and cy position', function() { - group.center(321,567) - var box = group.gbox() - expect(box.cx).toBe(321) - expect(box.cy).toBe(567) - }) - }) - - describe('dx()', function() { - it('moves the x positon of the element relative to the current position', function() { - group.move(50,60) - group.dx(100) - expect(group.node.getAttribute('transform')).toBe('matrix(1,0,0,1,150,60)') - }) - }) - - describe('dy()', function() { - it('moves the y positon of the element relative to the current position', function() { - group.move(50,60) - group.dy(120) - expect(group.node.getAttribute('transform')).toBe('matrix(1,0,0,1,50,180)') - }) - }) - - describe('dmove()', function() { - it('moves the x and y positon of the element relative to the current position', function() { - group.move(50, 60) - group.dmove(80, 25) - expect(group.node.getAttribute('transform')).toBe('matrix(1,0,0,1,130,85)') - }) - }) -}) diff --git a/spec/spec/helper.js b/spec/spec/helper.js index 3dd6aff..a77b3e7 100644 --- a/spec/spec/helper.js +++ b/spec/spec/helper.js @@ -10,23 +10,23 @@ if(typeof exports === 'object'){ drawing = document.documentElement imageUrl = 'spec/fixtures/pixel.png' parserInDoc = true - + function tag(name, attrs, children) { var el = document.createElement(name) for(var i in attrs){ el.setAttribute(i, attrs[i]) } - + for(var i in children){ if(typeof children[i] == 'string') children[i] = document.createTextNode(children[i]) - + el.appendChild(children[i]) } - + return el } - + // create fixtures in svgdom var el = tag('svg', { height:0, @@ -122,9 +122,9 @@ if(typeof exports === 'object'){ tag('polygon', {points: '200,10 250,190 160,210'}), tag('polyline', {points: '20,20 40,25 60,40 80,120 120,140 200,180'}) ]) - + document.appendChild(el) - + }else{ drawing = document.createElement('div') document.getElementsByTagName('body')[0].appendChild(drawing) @@ -175,3 +175,15 @@ window.roundBox = function(box) { Math.round(box.height) ) } + +// Same thing here with matrices +window.roundMatrix = function (mat) { + return new SVG.Matrix( + +(mat.a.toFixed(5)), + +(mat.b.toFixed(5)), + +(mat.c.toFixed(5)), + +(mat.d.toFixed(5)), + +(mat.e.toFixed(5)), + +(mat.f.toFixed(5)), + ) +} diff --git a/spec/spec/line.js b/spec/spec/line.js index 219043d..48b1c8b 100644 --- a/spec/spec/line.js +++ b/spec/spec/line.js @@ -202,7 +202,7 @@ describe('Line', function() { describe('translate()', function() { it('should set the translation of an element', function() { - line.transform({ x: 12, y: 12 }) + line.transform({ tx: 12, ty: 12 }) expect(line.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) diff --git a/spec/spec/matrix.js b/spec/spec/matrix.js index 0816f66..42ac1fe 100644 --- a/spec/spec/matrix.js +++ b/spec/spec/matrix.js @@ -1,156 +1,87 @@ describe('Matrix', function() { - var matrix + let comp = {a:2, b:0, c:0, d:2, e:100, f:50} describe('initialization', function() { - describe('without a source', function() { - - beforeEach(function() { - matrix = new SVG.Matrix - }) - - it('creates a new matrix with default values', function() { - expect(matrix.a).toBe(1) - expect(matrix.b).toBe(0) - expect(matrix.c).toBe(0) - expect(matrix.d).toBe(1) - expect(matrix.e).toBe(0) - expect(matrix.f).toBe(0) - }) - - describe('extract()', function() { - var extract - - beforeEach(function() { - extract = matrix.extract() - }) - - it('parses translation values', function() { - expect(extract.x).toBe(0) - expect(extract.y).toBe(0) - }) - it('parses skew values', function() { - expect(extract.skewX).toBe(0) - expect(extract.skewY).toBe(0) - }) - it('parses scale values', function() { - expect(extract.scaleX).toBe(1) - expect(extract.scaleY).toBe(1) - }) - it('parses rotatoin value', function() { - expect(extract.rotation).toBe(0) - }) - }) - - describe('toString()' , function() { - it('exports correctly to a string', function() { - expect(matrix.toString()).toBe('matrix(1,0,0,1,0,0)') - }) - }) + it('creates a new matrix with default values', function() { + let matrix = new SVG.Matrix() + expect(matrix).toEqual(jasmine.objectContaining( + {a:1, b:0, c:0, d:1, e:0, f:0} + )) }) - describe('with an element given', function() { - var rect - - beforeEach(function() { - rect = draw.rect(100, 100) - .transform({ rotation: -10 }, true) - .transform({ x: 40, y: 50 }, true) - .transform({ scale: 2 }, true) - - matrix = new SVG.Matrix(rect) - }) - - it('parses the current transform matrix from an element', function() { - expect(matrix.a).toBeCloseTo(1.9696155786514282) - expect(matrix.b).toBeCloseTo(-0.3472963869571686) - expect(matrix.c).toBeCloseTo(0.3472963869571686) - expect(matrix.d).toBeCloseTo(1.9696155786514282) - expect(matrix.e).toBeCloseTo(-17.770875930786133) - expect(matrix.f).toBeCloseTo(11.178505897521973) - }) - - describe('extract()', function() { - - it('parses translation values', function() { - var extract = new SVG.Matrix(draw.rect(100, 100).translate(40, 50)).extract() - expect(extract.x).toBeCloseTo(40) - expect(extract.y).toBeCloseTo(50) - }) - it('parses skewX value', function() { - var extract = new SVG.Matrix(draw.rect(100, 100).skew(25, 0)).extract() - expect(extract.skewX).toBeCloseTo(25) - }) - it('parses skewY value', function() { - var extract = new SVG.Matrix(draw.rect(100, 100).skew(0, 20)).extract() - expect(extract.skewY).toBeCloseTo(20) - }) - it('parses scale values', function() { - var extract = new SVG.Matrix(draw.rect(100, 100).scale(2, 3)).extract() - expect(extract.scaleX).toBeCloseTo(2) - expect(extract.scaleY).toBeCloseTo(3) - }) - it('parses rotatoin value', function() { - var extract = new SVG.Matrix(draw.rect(100, 100).rotate(-100)).extract() - expect(extract.rotation).toBeCloseTo(-100) - }) - - }) - + it('parses the current transform matrix from an element', function() { + let rect = draw.rect(100, 100).transform(comp) + let matrix = new SVG.Matrix(rect) + expect(matrix).toEqual(jasmine.objectContaining(comp)) }) - describe('with a string given', function() { - it('parses the string value correctly', function() { - var matrix = new SVG.Matrix('2, 0, 0, 2, 100, 50') - - expect(matrix.a).toBe(2) - expect(matrix.b).toBe(0) - expect(matrix.c).toBe(0) - expect(matrix.d).toBe(2) - expect(matrix.e).toBe(100) - expect(matrix.f).toBe(50) - }) + it('parses a string value correctly', function() { + let matrix = new SVG.Matrix('2, 0, 0, 2, 100, 50') + expect(matrix).toEqual(jasmine.objectContaining(comp)) }) - describe('with an array given', function() { - it('parses the array correctly', function() { - var matrix = new SVG.Matrix([2, 0, 0, 2, 100, 50]) + it('parses an array correctly', function() { + let matrix = new SVG.Matrix([2, 0, 0, 2, 100, 50]) + expect(matrix).toEqual(jasmine.objectContaining(comp)) + }) - expect(matrix.a).toBe(2) - expect(matrix.b).toBe(0) - expect(matrix.c).toBe(0) - expect(matrix.d).toBe(2) - expect(matrix.e).toBe(100) - expect(matrix.f).toBe(50) - }) + it('parses an object correctly', function() { + let matrix = new SVG.Matrix(comp) + expect(matrix).toEqual(jasmine.objectContaining(comp)) }) - describe('with an object given', function() { - it('parses the object correctly', function() { - var matrix = new SVG.Matrix({a:2, b:0, c:0, d:2, e:100, f:50}) + it('parses a transform object correctly', function() { + let matrix = new SVG.Matrix({scale: 2, translate: [100, 50]}) + expect(matrix).toEqual(jasmine.objectContaining(comp)) + }) - expect(matrix.a).toBe(2) - expect(matrix.b).toBe(0) - expect(matrix.c).toBe(0) - expect(matrix.d).toBe(2) - expect(matrix.e).toBe(100) - expect(matrix.f).toBe(50) - }) + it('parses 6 arguments correctly', function() { + let matrix = new SVG.Matrix(2, 0, 0, 2, 100, 50) + expect(matrix).toEqual(jasmine.objectContaining(comp)) }) + }) - describe('with 6 arguments given', function() { - it('parses the arguments correctly', function() { - var matrix = new SVG.Matrix(2, 0, 0, 2, 100, 50) + describe('toString()' , function() { + it('exports correctly to a string', function() { + expect(new SVG.Matrix().toString()).toBe('matrix(1,0,0,1,0,0)') + }) + }) - expect(matrix.a).toBe(2) - expect(matrix.b).toBe(0) - expect(matrix.c).toBe(0) - expect(matrix.d).toBe(2) - expect(matrix.e).toBe(100) - expect(matrix.f).toBe(50) + describe('compose()', function() { + it('composes a matrix to form the correct result', function() { + let composed = new SVG.Matrix().compose({ + scaleX: 3, scaleY: 20, shear: 4, rotate: 50, translateX: 23, translateY: 52, }) + + let expected = new SVG.Matrix().scale(3, 20).shear(4).rotate(50).translate(23, 52) + expect(composed).toEqual(expected) }) + }) + describe('decompose()', function () { + it('decomposes a matrix properly', function () { + var matrix = new SVG.Matrix().scale(3, 2.5).shear(4).rotate(30).translate(20, 30) + var decomposed = matrix.decompose() + expect(decomposed.scaleX).toBeCloseTo(3) + expect(decomposed.scaleY).toBeCloseTo(2.5) + expect(decomposed.shear).toBeCloseTo(4) + expect(decomposed.rotate).toBeCloseTo(30) + expect(decomposed.translateX).toBeCloseTo(20) + expect(decomposed.translateY).toBeCloseTo(30) + }) + + it('can be recomposed to the same matrix', function () { + var matrix = new SVG.Matrix().scale(3, 2.5).shear(4).rotate(30).translate(20, 30) + var decomposed = matrix.decompose() + var composed = new SVG.Matrix().compose(decomposed) + expect(matrix.a).toBeCloseTo(composed.a) + expect(matrix.b).toBeCloseTo(composed.b) + expect(matrix.c).toBeCloseTo(composed.c) + expect(matrix.d).toBeCloseTo(composed.d) + expect(matrix.e).toBeCloseTo(composed.e) + expect(matrix.f).toBeCloseTo(composed.f) + }) }) describe('clone()', function() { @@ -164,57 +95,23 @@ describe('Matrix', function() { }) }) - describe('morph()', function() { - it('stores a given matrix for morphing', function() { - var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0) - , matrix2 = new SVG.Matrix(1, 0, 0, 1, 4, 3) - - matrix1.morph(matrix2) - - expect(matrix1.destination).toEqual(matrix2) - }) - it('stores a clone, not the given matrix itself', function() { - var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0) - , matrix2 = new SVG.Matrix(1, 0, 0, 1, 4, 3) - - matrix1.morph(matrix2) - - expect(matrix1.destination).not.toBe(matrix2) - }) - }) - - describe('at()', function() { - it('returns a morphed array at a given position', function() { - var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0) - , matrix2 = new SVG.Matrix(1, 0, 0, 1, 4, 3) - , matrix3 = matrix1.morph(matrix2).at(0.5) - - expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)') - expect(matrix2.toString()).toBe('matrix(1,0,0,1,4,3)') - expect(matrix3.toString()).toBe('matrix(1.5,0,0,3,2,1.5)') - }) - it('returns itself when no destination specified', function() { - var matrix = new SVG.Matrix(2, 0, 0, 5, 0, 0) - expect(matrix.at(0.5)).toBe(matrix) - }) - }) - describe('multiply()', function() { - it('multiplies two matices', function() { - var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0) - , matrix2 = new SVG.Matrix(1, 0, 0, 1, 4, 3) + it('multiplies two matrices', function() { + var matrix1 = new SVG.Matrix(1, 4, 2, 5, 3, 6) + , matrix2 = new SVG.Matrix(7, 8, 8, 7, 9, 6) , matrix3 = matrix1.multiply(matrix2) - expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)') - expect(matrix2.toString()).toBe('matrix(1,0,0,1,4,3)') - expect(matrix3.toString()).toBe('matrix(2,0,0,5,8,15)') + expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)') + expect(matrix2.toString()).toBe('matrix(7,8,8,7,9,6)') + expect(matrix3.toString()).toBe('matrix(23,68,22,67,24,72)') }) + it('accepts matrices in any form', function() { - var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0) - , matrix2 = matrix1.multiply('1,0,0,1,4,3') + var matrix1 = new SVG.Matrix(1, 4, 2, 5, 3, 6) + , matrix2 = matrix1.multiply('7,8,8,7,9,6') - expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)') - expect(matrix2.toString()).toBe('matrix(2,0,0,5,8,15)') + expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)') + expect(matrix2.toString()).toBe('matrix(23,68,22,67,24,72)') }) }) @@ -223,9 +120,7 @@ describe('Matrix', function() { var matrix1 = new SVG.Matrix(2, 0, 0, 5, 4, 3) , matrix2 = matrix1.inverse() - , abcdef = [0.5,0,0,0.2,-2,-0.6] - - expect(matrix1.toString()).toBe('matrix(2,0,0,5,4,3)') + , abcdef = [0.5, 0, 0, 0.2, -2, -0.6] for(var i in 'abcdef') { expect(matrix2['abcdef'[i]]).toBeCloseTo(abcdef[i]) @@ -236,10 +131,15 @@ describe('Matrix', function() { describe('translate()', function() { it('translates matrix by given x and y values', function() { var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).translate(10, 12.5) - expect(matrix.e).toBe(14) expect(matrix.f).toBe(15.5) }) + + it('does nothing if you give it no x or y value', function() { + var matrix = new SVG.Matrix(1, 2, 3, 4, 5, 6).translate() + expect(matrix.e).toBe(5) + expect(matrix.f).toBe(6) + }) }) describe('scale()', function() { @@ -248,51 +148,59 @@ describe('Matrix', function() { expect(matrix.a).toBe(3) expect(matrix.d).toBe(3) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.e).toBe(4 * 3) + expect(matrix.f).toBe(3 * 3) }) it('performs a non-uniformal scale with two values', function() { var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(2.5, 3.5) expect(matrix.a).toBe(2.5) expect(matrix.d).toBe(3.5) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.e).toBe(4 * 2.5) + expect(matrix.f).toBe(3 * 3.5) }) it('performs a uniformal scale at a given center point with three values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3, 150, 100) + var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 3) expect(matrix.a).toBe(3) - expect(matrix.d).toBe(3) - expect(matrix.e).toBe(-296) - expect(matrix.f).toBe(-197) + expect(matrix.b).toBe(9) + expect(matrix.c).toBe(6) + expect(matrix.d).toBe(9) + expect(matrix.e).toBe(8) + expect(matrix.f).toBe(3) }) it('performs a non-uniformal scale at a given center point with four values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3, 2, 150, 100) + var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 2, 3) expect(matrix.a).toBe(3) - expect(matrix.d).toBe(2) - expect(matrix.e).toBe(-296) - expect(matrix.f).toBe(-97) + expect(matrix.b).toBe(6) + expect(matrix.c).toBe(6) + expect(matrix.d).toBe(6) + expect(matrix.e).toBe(8) + expect(matrix.f).toBe(3) }) }) describe('rotate()', function() { it('performs a rotation with one argument', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).rotate(30) + var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).rotate(30) - expect(matrix.a).toBeCloseTo(0.8660254037844387) - expect(matrix.d).toBeCloseTo(0.8660254037844387) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.a).toBeCloseTo(-0.6339746) + expect(matrix.b).toBeCloseTo(3.09807621) + expect(matrix.c).toBeCloseTo(0.23205081) + expect(matrix.d).toBeCloseTo(3.59807621) + expect(matrix.e).toBeCloseTo(1.96410162) + expect(matrix.f).toBeCloseTo(4.59807621) }) - it('performs a rotation on a given point with three arguments', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).rotate(30, 150, 100) + it('performs a rotation around a given point with three arguments', function() { + var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).rotate(30, 2, 3) - expect(matrix.a).toBeCloseTo(0.8660254037844387) - expect(matrix.d).toBeCloseTo(0.8660254037844387) - expect(matrix.e).toBeCloseTo(74.0961894323342) - expect(matrix.f).toBeCloseTo(-58.60254037844388) + expect(matrix.a).toBeCloseTo(-0.633974596216) + expect(matrix.b).toBeCloseTo(3.09807621135) + expect(matrix.c).toBeCloseTo(0.232050807569) + expect(matrix.d).toBeCloseTo(3.59807621135) + expect(matrix.e).toBeCloseTo(3.73205080757) + expect(matrix.f).toBeCloseTo(4.0) }) }) @@ -303,7 +211,7 @@ describe('Matrix', function() { expect(matrix.a).toBe(-1) expect(matrix.d).toBe(1) - expect(matrix.e).toBe(4) + expect(matrix.e).toBe(-4) expect(matrix.f).toBe(3) }) it('performs a flip over the horizontal axis over a given point with two arguments', function() { @@ -311,7 +219,7 @@ describe('Matrix', function() { expect(matrix.a).toBe(-1) expect(matrix.d).toBe(1) - expect(matrix.e).toBe(304) + expect(matrix.e).toBe(296) expect(matrix.f).toBe(3) }) }) @@ -322,7 +230,7 @@ describe('Matrix', function() { expect(matrix.a).toBe(1) expect(matrix.d).toBe(-1) expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.f).toBe(-3) }) it('performs a flip over the vertical axis over a given point with two arguments', function() { var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip('y', 100) @@ -330,7 +238,7 @@ describe('Matrix', function() { expect(matrix.a).toBe(1) expect(matrix.d).toBe(-1) expect(matrix.e).toBe(4) - expect(matrix.f).toBe(203) + expect(matrix.f).toBe(197) }) }) describe('with no axis given', function() { @@ -339,126 +247,129 @@ describe('Matrix', function() { expect(matrix.a).toBe(-1) expect(matrix.d).toBe(-1) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.e).toBe(-4) + expect(matrix.f).toBe(-3) }) it('performs a flip over the horizontal and vertical axis over a given point with one argument that represent both coordinates', function() { var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip(100) expect(matrix.a).toBe(-1) expect(matrix.d).toBe(-1) - expect(matrix.e).toBe(204) - expect(matrix.f).toBe(203) + expect(matrix.e).toBe(196) + expect(matrix.f).toBe(197) }) it('performs a flip over the horizontal and vertical axis over a given point with two arguments', function() { var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip(50, 100) expect(matrix.a).toBe(-1) expect(matrix.d).toBe(-1) - expect(matrix.e).toBe(104) - expect(matrix.f).toBe(203) + expect(matrix.e).toBe(96) + expect(matrix.f).toBe(197) }) }) }) describe('skew()', function() { it('performs a uniformal skew with one value', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(14) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30) expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.24932800284318) - expect(matrix.c).toBeCloseTo(0.24932800284318) + expect(matrix.b).toBeCloseTo(0.57735026919) + expect(matrix.c).toBeCloseTo(0.57735026919) expect(matrix.d).toBe(1) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.e).toBeCloseTo(5.73205080757) + expect(matrix.f).toBeCloseTo(5.30940107676) }) + it('performs a non-uniformal skew with two values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(8, 5) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 20) expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.087488663525924) - expect(matrix.c).toBeCloseTo(0.14054083470239) + expect(matrix.b).toBeCloseTo(0.363970234266) + expect(matrix.c).toBeCloseTo(0.57735026919) expect(matrix.d).toBe(1) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.e).toBeCloseTo(5.73205080757) + expect(matrix.f).toBeCloseTo(4.45588093706) }) + it('performs a uniformal skew at a given center point with three values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(3, 150, 100) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 150, 100) expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.052407779283041) - expect(matrix.c).toBeCloseTo(0.052407779283041) + expect(matrix.b).toBeCloseTo(0.57735026919) + expect(matrix.c).toBeCloseTo(0.57735026919) expect(matrix.d).toBe(1) - expect(matrix.e).toBeCloseTo(-1.2407779283) - expect(matrix.f).toBeCloseTo(-4.8611668924562) + expect(matrix.e).toBeCloseTo(-52.0029761114) + expect(matrix.f).toBeCloseTo(-81.2931393017) }) + it('performs a non-uniformal skew at a given center point with four values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(9, 7, 150, 100) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 20, 150, 100) - expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.1227845609029) - expect(matrix.c).toBeCloseTo(0.15838444032454) - expect(matrix.d).toBe(1) - expect(matrix.e).toBeCloseTo(-11.83844403245) - expect(matrix.f).toBeCloseTo(-15.417684135435) + expect(matrix.a).toBe(1.0) + expect(matrix.b).toBeCloseTo(0.363970234266) + expect(matrix.c).toBeCloseTo(0.57735026919) + expect(matrix.d).toBe(1.0) + expect(matrix.e).toBeCloseTo(-52.0029761114) + expect(matrix.f).toBeCloseTo(-50.1396542029) }) - it('can be chained', function(){ - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(9, 7).skew(20, 40) - expect(matrix.a).toBeCloseTo(1.1329003254605) - expect(matrix.b).toBeCloseTo(0.96188419208018) - expect(matrix.c).toBeCloseTo(0.52235467459074) - expect(matrix.d).toBeCloseTo(1.0446899253961) - expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + it('can be chained', function(){ + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(20, 30).skew(30, 20) + expect(matrix.a).toBeCloseTo(1.33333333333) + expect(matrix.b).toBeCloseTo(0.941320503456) + expect(matrix.c).toBeCloseTo(0.941320503456) + expect(matrix.d).toBeCloseTo(1.13247433143) + expect(matrix.e).toBeCloseTo(8.1572948437) + expect(matrix.f).toBeCloseTo(7.16270500812) }) }) describe('skewX', function(){ it('performs a skew along the x axis with one value', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(12) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(30) expect(matrix.a).toBe(1) expect(matrix.b).toBe(0) - expect(matrix.c).toBeCloseTo(0.21255656167002) + expect(matrix.c).toBeCloseTo(0.57735026919) expect(matrix.d).toBe(1) - expect(matrix.e).toBe(4) + expect(matrix.e).toBeCloseTo(5.73205080757) expect(matrix.f).toBe(3) }) it('performs a skew along the x axis at a given center point with three values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(5, 150, 100) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(30, 150, 100) expect(matrix.a).toBe(1) expect(matrix.b).toBe(0) - expect(matrix.c).toBeCloseTo(0.087488663525924) + expect(matrix.c).toBeCloseTo(0.57735026919) expect(matrix.d).toBe(1) - expect(matrix.e).toBeCloseTo(-4.74886635259) + expect(matrix.e).toBeCloseTo(-52.0029761114) expect(matrix.f).toBe(3) }) }) describe('skewY', function(){ it('performs a skew along the y axis with one value', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(12) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(30) expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.21255656167002) + expect(matrix.b).toBeCloseTo(0.57735026919) expect(matrix.c).toBe(0) expect(matrix.d).toBe(1) expect(matrix.e).toBe(4) - expect(matrix.f).toBe(3) + expect(matrix.f).toBeCloseTo(5.30940107676) }) it('performs a skew along the y axis at a given center point with three values', function() { - var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(5, 150, 100) + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(30, 150, 100) expect(matrix.a).toBe(1) - expect(matrix.b).toBeCloseTo(0.087488663525924) + expect(matrix.b).toBeCloseTo(0.57735026919) expect(matrix.c).toBe(0) expect(matrix.d).toBe(1) expect(matrix.e).toBe(4) - expect(matrix.f).toBeCloseTo(-10.123299528889) + expect(matrix.f).toBeCloseTo(-81.2931393017) }) }) diff --git a/spec/spec/morphing.js b/spec/spec/morphing.js new file mode 100644 index 0000000..4074d7e --- /dev/null +++ b/spec/spec/morphing.js @@ -0,0 +1,161 @@ +describe('Morphing', function () { + describe('constructors', function () { + + it('SVG.Morphable with Number', function () { + var morpher = new SVG.Morphable().from(10).to(5) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Number) + expect(morpher.at(0.5) instanceof SVG.Number).toBe(true) + expect(morpher.at(0.5).valueOf()).toBe(7.5) + }) + + it('SVG.Morphable with String', function () { + var morpher = new SVG.Morphable().from('foo').to('bar') + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Morphable.NonMorphable) + expect(morpher.at(0.5) instanceof SVG.Morphable.NonMorphable).toBe(true) + expect(morpher.at(0.5).valueOf()).toBe('foo') + expect(morpher.at(1).valueOf()).toBe('bar') + }) + + it('SVG.Morphable with Object', function () { + var morpher = new SVG.Morphable().from({a:5, b: 10}).to({a: 10, b: 20}) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Morphable.ObjectBag) + expect(morpher.at(0.5) instanceof Object).toBe(true) + expect(morpher.at(0.5).valueOf()).toEqual(jasmine.objectContaining({a: 7.5, b: 15})) + }) + + it(`Creates a morphable out of an SVG.Number`, function () { + var morpher = new SVG.Number(5).to(10) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Number) + expect(morpher.at(0.5) instanceof SVG.Number).toBe(true) + expect(morpher.at(0.5).valueOf()).toBe(7.5) + }) + + it(`Creates a morphable out of an SVG.Color`, function () { + var morpher = new SVG.Color('#fff').to('#000') + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Color) + expect(morpher.at(0.5) instanceof SVG.Color).toBe(true) + expect(morpher.at(0.5).toHex()).toBe('#808080') + }) + + it(`Creates a morphable out of an SVG.Box`, function () { + var morpher = new SVG.Box(1, 2, 3, 4).to([5, 6, 7, 8]) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Box) + expect(morpher.at(0.5) instanceof SVG.Box).toBe(true) + expect(morpher.at(0.5)).toEqual(jasmine.objectContaining({x: 3, y: 4, width: 5, height: 6})) + }) + + it(`Creates a morphable out of an SVG.Matrix`, function () { + var morpher = new SVG.Matrix(1, 2, 3, 4, 5, 6).to([3, 4, 5, 6, 7, 8]) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Matrix) + expect(morpher.at(0.5) instanceof SVG.Matrix).toBe(true) + expect(morpher.at(0.5)).toEqual(jasmine.objectContaining(new SVG.Matrix(2, 3, 4, 5, 6, 7))) + }) + + it(`Creates a morphable out of an SVG.Array`, function () { + var morpher = new SVG.Array([1,2,3,4,5,6]).to([3,4,5,6,7,8]) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Array) + expect(morpher.at(0.5) instanceof SVG.Array).toBe(true) + expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining([2, 3, 4, 5, 6, 7])) + }) + + it(`Creates a morphable out of an SVG.PointArray`, function () { + var morpher = new SVG.PointArray([1, 2, 3, 4, 5, 6]).to([3, 4, 5, 6, 7, 8]) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.PointArray) + expect(morpher.at(0.5) instanceof SVG.PointArray).toBe(true) + expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining([2, 3, 4, 5, 6, 7])) + }) + + it(`Creates a morphable out of an SVG.PathArray`, function () { + var morpher = new SVG.PathArray(['M', 1, 2, 'L', 3, 4, 'L', 5, 6]).to(['M', 3, 4, 'L', 5, 6, 'L', 7, 8]) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.PathArray) + expect(morpher.at(0.5) instanceof SVG.PathArray).toBe(true) + expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining(['M', 2, 3, 'L', 4, 5, 'L', 6, 7])) + }) + + it(`Creates a morphable out of an SVG.Morphable.NonMorphable`, function () { + var morpher = new SVG.Morphable.NonMorphable('foo').to('bar') + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Morphable.NonMorphable) + expect(morpher.at(0.5) instanceof SVG.Morphable.NonMorphable).toBe(true) + expect(morpher.at(0.5).valueOf()).toBe('foo') + expect(morpher.at(1).valueOf()).toBe('bar') + }) + + it(`Creates a morphable out of an SVG.Morphable.TransformBag`, function () { + var morpher = new SVG.Morphable.TransformBag({rotate: 0, translateX: 0}) + .to({rotate: 50, translateX: 20}) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Morphable.TransformBag) + expect(morpher.at(0.5) instanceof SVG.Morphable.TransformBag).toBe(true) + + expect(morpher.at(0.5)).toEqual(jasmine.objectContaining({rotate: 25, translateX: 10})) + }) + + it(`Creates a morphable out of an SVG.Morphable.ObjectBag`, function () { + var morpher = new SVG.Morphable.ObjectBag({a:5, b: 10}).to({a: 10, b: 20}) + + expect(morpher instanceof SVG.Morphable).toBe(true) + expect(morpher.type()).toBe(SVG.Morphable.ObjectBag) + expect(morpher.at(0.5) instanceof Object).toBe(true) + expect(morpher.at(0.5).valueOf()).toEqual(jasmine.objectContaining({a: 7.5, b: 15})) + }) + }) + + describe('from()', function () { + it('sets the type of the runner', function () { + var morpher = new SVG.Morphable().from(5) + expect(morpher.type()).toBe(SVG.Number) + }) + + it('sets the from attribute to an array representation of the morphable type', function () { + var morpher = new SVG.Morphable().from(5) + expect(morpher.from()).toEqual(jasmine.arrayContaining([5])) + }) + }) + + describe('type()', function () { + it('sets the type of the runner', function () { + var morpher = new SVG.Morphable().type(SVG.Number) + expect(morpher._type).toBe(SVG.Number) + }) + + it('gets the type of the runner', function () { + var morpher = new SVG.Morphable().type(SVG.Number) + expect(morpher.type()).toBe(SVG.Number) + }) + }) + + describe('to()', function () { + it('sets the type of the runner', function () { + var morpher = new SVG.Morphable().to(5) + expect(morpher.type()).toBe(SVG.Number) + }) + + it('sets the from attribute to an array representation of the morphable type', function () { + var morpher = new SVG.Morphable().to(5) + expect(morpher.to()).toEqual(jasmine.arrayContaining([5])) + }) + }) +}) diff --git a/spec/spec/path.js b/spec/spec/path.js index e0b5f25..9a78b25 100644 --- a/spec/spec/path.js +++ b/spec/spec/path.js @@ -185,7 +185,7 @@ describe('Path', function() { describe('translate()', function() { it('sets the translation of an element', function() { - path.transform({ x: 12, y: 12 }) + path.transform({ tx: 12, ty: 12 }) expect(path.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) diff --git a/spec/spec/point.js b/spec/spec/point.js index 8eacb84..a41f2ee 100644 --- a/spec/spec/point.js +++ b/spec/spec/point.js @@ -26,11 +26,11 @@ describe('Point', function() { }) describe('with only x given', function() { - it('creates a point using the given value for both x and y', function() { + it('sets the y value to 0', function() { var point = new SVG.Point(7) expect(point.x).toBe(7) - expect(point.y).toBe(7) + expect(point.y).toBe(0) }) }) diff --git a/spec/spec/polygon.js b/spec/spec/polygon.js index 789c3b9..4cd2ea8 100644 --- a/spec/spec/polygon.js +++ b/spec/spec/polygon.js @@ -180,7 +180,7 @@ describe('Polygon', function() { describe('translate()', function() { it('sets the translation of an element', function() { - polygon.transform({ x: 12, y: 12 }) + polygon.transform({ tx: 12, ty: 12 }) expect(polygon.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) diff --git a/spec/spec/polyline.js b/spec/spec/polyline.js index ca516bd..7fbea18 100644 --- a/spec/spec/polyline.js +++ b/spec/spec/polyline.js @@ -180,7 +180,7 @@ describe('Polyline', function() { describe('translate()', function() { it('sets the translation of an element', function() { - polyline.transform({ x: 12, y: 12 }) + polyline.transform({ tx: 12, ty: 12 }) expect(polyline.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) diff --git a/spec/spec/queue.js b/spec/spec/queue.js new file mode 100644 index 0000000..738831c --- /dev/null +++ b/spec/spec/queue.js @@ -0,0 +1,111 @@ + +describe ('SVG.Queue()', function () { + + describe('first ()', function () { + + it('returns null if no item in the queue', function () { + var queue = new SVG.Queue() + expect(queue.first()).toEqual(null) + }) + + it ('returns the first value in the queue', function () { + var queue = new SVG.Queue() + queue.push(1) + expect(queue.first()).toBe(1) + queue.push(2) + expect(queue.first()).toBe(1) + }) + }) + + describe('last ()', function () { + + it ('returns null if no item in the queue', function () { + var queue = new SVG.Queue() + expect(queue.last()).toEqual(null) + }) + + it ('returns the last value added', function () { + var queue = new SVG.Queue() + queue.push(1) + expect(queue.last()).toBe(1) + queue.push(2) + expect(queue.last()).toBe(2) + }) + }) + + describe('push ()', function () { + + it ('adds an element to the end of the queue', function () { + var queue = new SVG.Queue() + queue.push(1) + queue.push(2) + queue.push(3) + + expect(queue.first()).toBe(1) + expect(queue.last()).toBe(3) + }) + + it ('changes the length when you add things', function () { + var queue = new SVG.Queue() + queue.push(1) + expect(queue.length).toBe(1) + queue.push(2) + expect(queue.length).toBe(2) + }) + }) + + describe('remove ()', function () { + it('removes an item from the queue which matches the matcher', function () { + var queue = new SVG.Queue() + queue.push(1) + queue.push(2) + queue.push(3) + + queue.remove(function(item) { + return item.value == 3 + }) + + expect(queue.length).toBe(2) + expect(queue.last()).toBe(2) + expect(queue.first()).toBe(1) + }) + + it('removes no item from the queue if nothing is matched', function () { + var queue = new SVG.Queue() + queue.push(1) + queue.push(2) + queue.push(3) + + queue.remove(function(item) { + return item.value == 4 + }) + + expect(queue.length).toBe(3) + expect(queue.last()).toBe(3) + expect(queue.first()).toBe(1) + }) + }) + + describe('shift ()', function () { + it('returns nothing if queue is empty', function () { + var queue = new SVG.Queue() + var val = queue.shift() + expect(val).toBeFalsy() + }) + + it('returns the first item of the queue and removes it', function () { + var queue = new SVG.Queue() + queue.push(1) + queue.push(2) + queue.push(3) + + var val = queue.shift() + + expect(queue.length).toBe(2) + expect(queue.last()).toBe(3) + expect(queue.first()).toBe(2) + + expect(val).toBe(1) + }) + }) +}) diff --git a/spec/spec/rect.js b/spec/spec/rect.js index 5ce65c0..b07e10b 100644 --- a/spec/spec/rect.js +++ b/spec/spec/rect.js @@ -1,14 +1,14 @@ describe('Rect', function() { var rect - + beforeEach(function() { rect = draw.rect(220,100) }) - + afterEach(function() { draw.clear() }) - + describe('x()', function() { it('should return the value of x without an argument', function() { expect(rect.x()).toBe(0) @@ -18,7 +18,7 @@ describe('Rect', function() { expect(rect.node.getAttribute('x')).toBe('123') }) }) - + describe('y()', function() { it('should return the value of y without an argument', function() { expect(rect.y()).toBe(0) @@ -28,7 +28,7 @@ describe('Rect', function() { expect(rect.node.getAttribute('y')).toBe('345') }) }) - + describe('cx()', function() { it('should return the value of cx without an argument', function() { expect(rect.cx()).toBe(110) @@ -39,7 +39,7 @@ describe('Rect', function() { expect(box.cx).toBe(123) }) }) - + describe('cy()', function() { it('should return the value of cy without an argument', function() { expect(rect.cy()).toBe(50) @@ -63,7 +63,7 @@ describe('Rect', function() { expect(rect.node.getAttribute('ry')).toBe('30') }) }) - + describe('move()', function() { it('should set the x and y position', function() { rect.move(123,456) @@ -96,7 +96,7 @@ describe('Rect', function() { expect(rect.node.getAttribute('y')).toBe('85') }) }) - + describe('center()', function() { it('should set the cx and cy position', function() { rect.center(321,567) @@ -105,7 +105,7 @@ describe('Rect', function() { expect(box.cy).toBe(567) }) }) - + describe('width()', function() { it('sets the width of the element', function() { rect.width(789) @@ -145,17 +145,17 @@ describe('Rect', function() { expect(rect.width() / rect.height()).toBe(box.width / box.height) }) }) - + describe('scale()', function() { it('should scale the element universally with one argument', function() { var box = rect.scale(2).rbox() - + expect(box.width).toBe(rect.attr('width') * 2) expect(box.height).toBe(rect.attr('height') * 2) }) it('should scale the element over individual x and y axes with two arguments', function() { var box = rect.scale(2, 3.5).rbox() - + expect(box.width).toBe(rect.attr('width') * 2) expect(box.height).toBe(rect.attr('height') * 3.5) }) @@ -163,17 +163,9 @@ describe('Rect', function() { describe('translate()', function() { it('should set the translation of an element', function() { - rect.transform({ x: 12, y: 12 }) + rect.transform({ tx: 12, ty: 12 }) expect(rect.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) - -}) - - - - - - - +}) diff --git a/spec/spec/runner.js b/spec/spec/runner.js new file mode 100644 index 0000000..c1c5972 --- /dev/null +++ b/spec/spec/runner.js @@ -0,0 +1,874 @@ +describe('SVG.Runner', function () { + + var initFn = jasmine.createSpy('initFn') + var runFn = jasmine.createSpy('runFn') + + beforeEach(function () { + initFn.calls.reset() + runFn.calls.reset() + }) + + describe('sanitise()', function () { + it('can handle all form of input', function () { + var fn = SVG.Runner.sanitise + + expect(fn(200, 200, 'now')).toEqual(jasmine.objectContaining({ + duration: 200, + delay: 200, + when: 'now', + times: 1, + wait: 0, + swing: false + })) + + expect(fn(200, 200)).toEqual(jasmine.objectContaining({ + duration: 200, + delay: 200, + when: 'last', + times: 1, + wait: 0, + swing: false + })) + + expect(fn(200)).toEqual(jasmine.objectContaining({ + duration: 200, + delay: SVG.defaults.timeline.delay, + when: 'last', + times: 1, + wait: 0, + swing: false + })) + + expect(fn(runFn)).toEqual(jasmine.objectContaining({ + duration: runFn, + delay: SVG.defaults.timeline.delay, + when: 'last', + times: 1, + wait: 0, + swing: false + })) + + expect(fn({delay: 200})).toEqual(jasmine.objectContaining({ + duration: SVG.defaults.timeline.duration, + delay: 200, + when: 'last', + times: 1, + wait: 0, + swing: false + })) + + expect(fn({times: 3, delay: 200, when: 'now', swing: true, wait: 200})).toEqual(jasmine.objectContaining({ + duration: SVG.defaults.timeline.duration, + delay: 200, + when: 'now', + times: 3, + wait: 200, + swing: true + })) + }) + }) + + describe('())', function () { + it('creates a runner with defaults', function () { + var runner = new SVG.Runner() + expect(runner instanceof SVG.Runner).toBe(true) + expect(runner._duration).toBe(SVG.defaults.timeline.duration) + expect(runner._stepper instanceof SVG.Ease).toBe(true) + }) + + it('creates a runner with duration set', function () { + var runner = new SVG.Runner(1000) + expect(runner instanceof SVG.Runner).toBe(true) + expect(runner._duration).toBe(1000) + expect(runner._stepper instanceof SVG.Ease).toBe(true) + }) + + it('creates a runner with controller set', function () { + var runner = new SVG.Runner(runFn) + expect(runner instanceof SVG.Runner).toBe(true) + expect(runner._duration).toBeFalsy() + expect(runner._stepper instanceof SVG.Controller).toBe(true) + }) + }) + + describe('constructors', function () { + describe('animate()', function () { + it('creates a runner with the element set and schedules it on the timeline', function () { + var orginalRunner = SVG.Runner + spyOn(SVG, 'Runner').and.callFake(function() { + return new orginalRunner() + }) + + var element = SVG('<rect>') + var runner = element.animate() + expect(SVG.Runner).toHaveBeenCalled(); + expect(runner instanceof SVG.Runner) + expect(runner.element()).toBe(element) + expect(runner.timeline()).toBe(element.timeline()) + }) + }) + + describe('delay()', function () { + it('calls animate with correct parameters', function () { + var element = SVG('<rect>') + + spyOn(element, 'animate') + element.delay(100, 'now') + expect(element.animate).toHaveBeenCalledWith(0, 100, 'now') + }) + }) + }) + + describe('queue()', function () { + it('adds another closure to the runner', function () { + var runner = new SVG.Runner() + runner.queue(initFn, runFn, true) + + expect(runner._queue[0]).toEqual(jasmine.objectContaining({ + initialiser: initFn, + initialised: false, + runner: runFn, + finished: false + })) + }) + }) + + describe('tag()', function () { + it('acts as a getter', function () { + var runner = new SVG.Runner() + + runner.tags = {foo: true} + expect(runner.tag()).toEqual(jasmine.arrayContaining(['foo'])) + }) + + it('sets one tag with a string given', function () { + var runner = new SVG.Runner() + + runner.tag('foo') + expect(runner.tags).toEqual(jasmine.objectContaining({foo: true})) + }) + + it('sets multiple tags with an array given', function () { + var runner = new SVG.Runner() + + runner.tag(['foo', 'bar', 'baz']) + expect(runner.tags).toEqual(jasmine.objectContaining({foo: true, bar: true, baz: true})) + }) + }) + + describe('untag()', function () { + it('untags with a string given', function () { + var runner = new SVG.Runner() + + runner.tag('foo') + runner.untag('foo') + expect(runner.tags).toEqual(jasmine.objectContaining({})) + }) + + it('untags multiple tags with an array given', function () { + var runner = new SVG.Runner() + + runner.tag(['foo', 'bar', 'baz']) + runner.untag(['bar', 'baz']) + expect(runner.tags).toEqual(jasmine.objectContaining({foo: true})) + }) + }) + + + describe('step()', function () { + + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.step()).toBe(runner) + }) + + it('calls initFn once and runFn at every step', function() { + var runner = new SVG.Runner() + runner.queue(initFn, runFn, false) + + runner.step() + expect(initFn).toHaveBeenCalled() + expect(runFn).toHaveBeenCalled() + + runner.step() + expect(initFn.calls.count()).toBe(1) + expect(runFn.calls.count()).toBe(2) + }) + + it('calls initFn on every step if its declaritive', function() { + var runner = new SVG.Runner(new SVG.Controller()) + runner.queue(initFn, runFn, true) + + runner.step() + expect(initFn).toHaveBeenCalled() + expect(runFn).toHaveBeenCalled() + + runner.step() + expect(initFn.calls.count()).toBe(2) + expect(runFn.calls.count()).toBe(2) + }) + + function getLoop(r) { + var loopDuration = r._duration + r._wait + var loopsDone = Math.floor(r._time / loopDuration) + return loopsDone + } + + // step in time + it('steps forward a certain time', function () { + var spy = jasmine.createSpy('stepper') + var r = new SVG.Runner(1000).loop(10, false, 100) + r.queue(null, spy) + + r.step(300) // should be 0.3s + expect(spy).toHaveBeenCalledWith(0.3) + expect(getLoop(r)).toBe(0) + + r.step(300) // should be 0.6s + expect(spy).toHaveBeenCalledWith(0.6) + expect(getLoop(r)).toBe(0) + + r.step(600) // should be 0.1s + expect(spy).toHaveBeenCalledWith(0.1) + expect(getLoop(r)).toBe(1) + + r.step(-300) // should be 0.9s + expect(spy).toHaveBeenCalledWith(0.9) + expect(getLoop(r)).toBe(0) + + r.step(2000) // should be 0.7s + expect(spy).toHaveBeenCalledWith(0.7) + expect(getLoop(r)).toBe(2) + + r.step(-2000) // should be 0.9s + expect(spy).toHaveBeenCalledWith(0.9) + expect(getLoop(r)).toBe(0) + }) + + it('handles dts which are bigger than the animation time', function () { + var runner = new SVG.Runner(1000) + runner.queue(initFn, runFn, true) + + runner.step(1100) + expect(initFn).toHaveBeenCalled() + expect(runFn).toHaveBeenCalledWith(1) + }) + + + describe('looping', function () { + describe('without wait', function () { + describe('unreversed', function () { + describe('nonswinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, false) + runner.queue(null, spy) + + runner.step(5750) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, false) + runner.queue(null, spy) + + runner.step(4750) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + }) + + describe('swinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, true) + runner.queue(null, spy) + + runner.step(5750) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true) + runner.queue(null, spy) + + runner.step(4750) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + }) + }) + + describe('reversed', function () { + describe('nonswinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, false).reverse() + runner.queue(null, spy) + + runner.step(5750) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, false).reverse() + runner.queue(null, spy) + + runner.step(4750) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + }) + + describe('swinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, true).reverse() + runner.queue(null, spy) + + runner.step(5750) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true).reverse() + runner.queue(null, spy) + + runner.step(4750) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + }) + }) + }) + + + describe('with wait', function () { + describe('unreversed', function () { + describe('nonswinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, false, 100) + runner.queue(null, spy) + + runner.step(5450) + expect(spy).toHaveBeenCalledWith(1) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, false, 100) + runner.queue(null, spy) + + runner.step(4350) + expect(spy).toHaveBeenCalledWith(1) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + }) + + describe('swinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, true, 100) + runner.queue(null, spy) + + runner.step(5450) + expect(spy).toHaveBeenCalledWith(1) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true, 100) + runner.queue(null, spy) + + runner.step(4350) + expect(spy).toHaveBeenCalledWith(0) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.75) + + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + }) + }) + + describe('reversed', function () { + describe('nonswinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, false, 100).reverse() + runner.queue(null, spy) + + runner.step(5450) + expect(spy).toHaveBeenCalledWith(0) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, false, 100).reverse() + runner.queue(null, spy) + + runner.step(4350) + expect(spy).toHaveBeenCalledWith(0) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + }) + + describe('swinging', function () { + it('does behave correctly at the end of an even loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(6, true, 100).reverse() + runner.queue(null, spy) + + runner.step(5450) + expect(spy).toHaveBeenCalledWith(0) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.75) + runner.step(250) + expect(spy).toHaveBeenCalledWith(1) + }) + + it('does behave correctly at the end of an uneven loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true, 100).reverse() + runner.queue(null, spy) + + runner.step(4350) + expect(spy).toHaveBeenCalledWith(1) + spy.calls.reset() + + runner.step(800) + expect(spy).toHaveBeenCalledWith(0.25) + runner.step(250) + expect(spy).toHaveBeenCalledWith(0) + }) + }) + }) + }) + }) + + + }) + + + describe('active()', function () { + it('acts as a getter without parameters', function () { + var runner = new SVG.Runner() + expect(runner.active()).toBe(true) + }) + + it('disables the runner when false is passed', function () { + var runner = new SVG.Runner() + expect(runner.active(false)).toBe(runner) + expect(runner.active()).toBe(false) + }) + + it('enables the runner when true is passed', function () { + var runner = new SVG.Runner() + expect(runner.active(false)).toBe(runner) + expect(runner.active(true)).toBe(runner) + expect(runner.active()).toBe(true) + }) + }) + + describe('duration()', function () { + it('return the full duration of the runner including all loops and waits', function () { + var runner = new SVG.Runner(800).loop(10, true, 200) + expect(runner.duration()).toBe(9800) + }) + }) + + describe('loop()', function () { + it('makes this runner looping', function () { + var runner = new SVG.Runner(1000).loop(5) + expect(runner.duration()).toBe(5000) + }) + }) + + describe('time()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.time(0)).toBe(runner) + }) + + it('acts as a getter with no parameter passed', function () { + var runner = new SVG.Runner() + expect(runner.time()).toBe(0) + }) + + it('reschedules the runner to a new time', function () { + var runner = new SVG.Runner() + runner.time(10) + + expect(runner.time()).toBe(10) + }) + + it('calls step to reschedule', function () { + var runner = new SVG.Runner() + spyOn(runner, 'step') + runner.time(10) + + expect(runner.step).toHaveBeenCalledWith(10) + }) + }) + + describe('loops()', function () { + it('get the loops of a runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + runner.step(300) + expect(spy).toHaveBeenCalledWith(0.3) + + expect(runner.loops()).toBe(0.3) + }) + it('sets the loops of the runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + expect(runner.loops(0.5).loops()).toBe(0.5) + expect(spy).toHaveBeenCalledWith(0.5) + + expect(runner.loops(0.1).loops()).toBe(0.1) + expect(spy).toHaveBeenCalledWith(0.1) + + expect(runner.loops(1.5).loops()).toBe(1) + expect(spy).toHaveBeenCalledWith(1) + }) + it('sets the loops of the runner in a loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true, 500).queue(null, spy) + + expect(runner.loops(1.3).loops()).toBe(1.3) + expect(spy).toHaveBeenCalledWith(0.7) + + expect(runner.loops(0.3).loops()).toBe(0.3) + }) + }) + + describe('progress()', function () { + it('gets the progress of a runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + runner.step(300) + expect(spy).toHaveBeenCalledWith(0.3) + + expect(runner.progress()).toBe(0.3) + }) + + it('gets the progress of a runner when looping', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(800).queue(null, spy).loop(10, false, 200) // duration should be 9800 + + // middle of animation, in the middle of wait time + runner.step(4900) + expect(runner.progress()).toBe(0.5) + expect(spy).toHaveBeenCalledWith(1) + + // start of next loop + runner.step(100) + expect(spy).toHaveBeenCalledWith(0) + + // move 400 into current loop which is 0.5 progress + // the progress value is 5400 / 9800 + runner.step(400) + expect(spy).toHaveBeenCalledWith(0.5) + expect(runner.progress()).toBe(5400 / 9800) + }) + + it('sets the progress of a runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + expect(runner.progress(0.5).progress()).toBe(0.5) + expect(spy).toHaveBeenCalledWith(0.5) + }) + + it('sets the progress of a runner when looping', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(800).queue(null, spy).loop(10, false, 200) + + // progress 0.5 somewhere in the middle of wait time + expect(runner.progress(0.5).progress()).toBe(0.5) + expect(spy).toHaveBeenCalledWith(1) + + // start of next loop + runner.step(100) + expect(spy).toHaveBeenCalledWith(0) + + // should move 0.5 into the next loop + expect(runner.progress(5400 / 9800).progress()).toBe(5400 / 9800) + expect(spy.calls.mostRecent().args[0]).toBeCloseTo(0.5) + }) + }) + + describe('position()', function () { + + it('gets the position of a runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + runner.step(300) + expect(spy).toHaveBeenCalledWith(0.3) + + expect(runner.position()).toBe(0.3) + }) + + it('gets the position of a runner when looping', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true, 100).queue(null, spy) + + runner.step(1200) + expect(spy).toHaveBeenCalledWith(0.9) + + expect(runner.position()).toBe(0.9) + }) + + it('sets the position of a runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).queue(null, spy) + + expect(runner.position(0.5).position()).toBe(0.5) + expect(spy).toHaveBeenCalledWith(0.5) + }) + + it('sets the position of a runner in a loop', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).loop(5, true, 100).queue(null, spy) + + runner.step(1200) + expect(runner.position(0.4).position()).toBe(0.4) + expect(spy).toHaveBeenCalledWith(0.4) + + expect(runner.position(0).position()).toBe(0) + expect(spy).toHaveBeenCalledWith(0) + + expect(runner.position(1).position()).toBe(1) + expect(spy).toHaveBeenCalledWith(1) + }) + }) + + describe('element()', function () { + it('returns the element bound to this runner if any', function () { + var runner1 = new SVG.Runner() + expect(runner1.element()).toBe(null) + + var element = SVG('<rect>') + var runner2 = element.animate() + expect(runner2.element()).toBe(element) + }) + + it('sets an element to be bound to the runner', function () { + var runner = new SVG.Runner() + var element = SVG('<rect>') + expect(runner.element(element)).toBe(runner) + expect(runner.element()).toBe(element) + }) + }) + + describe('timeline()', function () { + it('returns the timeline bound to this runner if any', function () { + var runner1 = new SVG.Runner() + expect(runner1.element()).toBe(null) + + var element = SVG('<rect>') + var runner2 = element.animate() + expect(runner2.timeline()).toBe(element.timeline()) + }) + + it('sets a timeline to be bound to the runner', function () { + var runner = new SVG.Runner() + var timeline = new SVG.Timeline() + expect(runner.timeline(timeline)).toBe(runner) + expect(runner.timeline()).toBe(timeline) + }) + }) + + describe('schedule()', function () { + it('schedules the runner on a timeline', function () { + var runner = new SVG.Runner() + var timeline = new SVG.Timeline() + var spy = spyOn(timeline, 'schedule').and.callThrough() + + expect(runner.schedule(timeline, 200, 'now')).toBe(runner) + expect(runner.timeline()).toBe(timeline) + expect(spy).toHaveBeenCalledWith(runner, 200, 'now') + }) + + it('schedules the runner on its own timeline', function () { + var runner = new SVG.Runner() + var timeline = new SVG.Timeline() + var spy = spyOn(timeline, 'schedule') + runner.timeline(timeline) + + expect(runner.schedule(200, 'now')).toBe(runner) + expect(runner.timeline()).toBe(timeline) + expect(spy).toHaveBeenCalledWith(runner, 200, 'now') + }) + }) + + describe('unschedule()', function () { + it('unschedules this runner from its timeline', function () { + var runner = new SVG.Runner() + var timeline = new SVG.Timeline() + var spy = spyOn(timeline, 'unschedule').and.callThrough() + + expect(runner.schedule(timeline, 200, 'now')).toBe(runner) + expect(runner.unschedule()).toBe(runner) + expect(spy).toHaveBeenCalledWith(runner) + expect(runner.timeline()).toBe(null) + }) + }) + + + describe('animate()', function () { + it('creates a new runner scheduled after the first', function () { + var runner = new SVG.Runner(1000) + var timeline = new SVG.Timeline() + + runner.schedule(timeline) + + var runner2 = runner.animate(500, 1000) + + expect(runner2.timeline()).toBe(timeline) + expect(runner2.time()).toBe(-1000) + + expect(timeline.schedule()).toEqual(jasmine.objectContaining([ + jasmine.objectContaining({start: 0, duration: 1000, end: 1000, runner: runner}), + jasmine.objectContaining({start: 1000, duration: 500, end: 1500, runner: runner2}) + ])) + }) + }) + + describe('delay()', function () { + it('calls animate with delay parameters', function () { + var runner = new SVG.Runner(1000) + spyOn(runner, 'animate') + + runner.delay(500) + expect(runner.animate).toHaveBeenCalledWith(0, 500) + }) + }) + + describe('during()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.during(runFn)).toBe(runner) + }) + + it('calls queue passing only a function to call on every step', function () { + var runner = new SVG.Runner() + spyOn(runner, 'queue') + runner.during(runFn) + + expect(runner.queue).toHaveBeenCalledWith(null, runFn) + }) + }) + + describe('after()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.after(runFn)).toBe(runner) + }) + + it('binds a function to the after event', function () { + var runner = new SVG.Runner() + spyOn(runner, 'on') + runner.after(runFn) + + expect(runner.on).toHaveBeenCalledWith('finish', runFn) + }) + }) + + describe('finish()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.finish()).toBe(runner) + }) + + it('calls step with Infinity as argument', function () { + var runner = new SVG.Runner() + spyOn(runner, 'step') + runner.finish() + + expect(runner.step).toHaveBeenCalledWith(Infinity) + }) + }) + + describe('reverse()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.reverse()).toBe(runner) + }) + + it('reverses the runner', function () { + var spy = jasmine.createSpy('stepper') + var runner = new SVG.Runner(1000).reverse().queue(null, spy) + runner.step(750) + expect(spy).toHaveBeenCalledWith(0.25) + }) + }) + + describe('ease()', function () { + it('returns itself', function () { + var runner = new SVG.Runner() + expect(runner.ease(function () {})).toBe(runner) + }) + + it('creates an easing Controller from the easing function', function () { + var runner = new SVG.Runner() + runner.ease(function () {}) + + expect(runner._stepper instanceof SVG.Ease).toBe(true) + }) + }) +}) diff --git a/spec/spec/sugar.js b/spec/spec/sugar.js index d550886..c695970 100644 --- a/spec/spec/sugar.js +++ b/spec/spec/sugar.js @@ -56,7 +56,7 @@ describe('Sugar', function() { it('redirects to transform()', function() { rect.rotate(1,2,3) - expect(rect.transform).toHaveBeenCalledWith({ rotation: 1, cx: 2, cy: 3 }) + expect(rect.transform).toHaveBeenCalledWith({ rotate: 1, ox: 2, oy:3 }, true) }) }) @@ -75,27 +75,27 @@ describe('Sugar', function() { it('redirects to transform() with no argument', function() { rect.skew() - expect(rect.transform).toHaveBeenCalledWith({ skewX: undefined, skewY: undefined, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ skew: [undefined, undefined], ox: undefined, oy: undefined }, true) }) it('redirects to transform() with one argument', function() { rect.skew(5) - expect(rect.transform).toHaveBeenCalledWith({ skew: 5, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ skew: 5, ox: undefined, oy: undefined }, true) }) it('redirects to transform() with two argument', function() { rect.skew(5, 6) - expect(rect.transform).toHaveBeenCalledWith({ skewX: 5, skewY: 6, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ skew: [5, 6], ox: undefined, oy: undefined}, true) }) it('redirects to transform() with three arguments', function() { rect.skew(5, 6, 7) - expect(rect.transform).toHaveBeenCalledWith({ skew: 5, cx: 6, cy: 7 }) + expect(rect.transform).toHaveBeenCalledWith({ skew: 5, ox: 6, oy: 7 }, true) }) it('redirects to transform() with four arguments', function() { rect.skew(5, 6, 7, 8) - expect(rect.transform).toHaveBeenCalledWith({ skewX: 5, skewY: 6, cx: 7, cy: 8 }) + expect(rect.transform).toHaveBeenCalledWith({ skew: [5, 6], ox: 7, oy: 8 }, true) }) }) @@ -114,27 +114,27 @@ describe('Sugar', function() { it('redirects to transform() with no argument', function() { rect.scale() - expect(rect.transform).toHaveBeenCalledWith({ scaleX: undefined, scaleY: undefined, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ scale: [undefined, undefined], ox: undefined, oy: undefined }, true) }) it('redirects to transform() with one argument', function() { rect.scale(5) - expect(rect.transform).toHaveBeenCalledWith({ scale: 5, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ scale: 5, ox: undefined, oy: undefined}, true) }) it('redirects to transform() with two argument', function() { rect.scale(5, 6) - expect(rect.transform).toHaveBeenCalledWith({ scaleX: 5, scaleY: 6, cx: undefined, cy: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ scale: [5, 6], ox: undefined, oy: undefined }, true) }) it('redirects to transform() with three arguments', function() { rect.scale(5, 6, 7) - expect(rect.transform).toHaveBeenCalledWith({ scale: 5, cx: 6, cy: 7 }) + expect(rect.transform).toHaveBeenCalledWith({ scale: 5, ox: 6, oy: 7 }, true) }) it('redirects to transform() with four arguments', function() { rect.scale(5, 6, 7, 8) - expect(rect.transform).toHaveBeenCalledWith({ scaleX: 5, scaleY: 6, cx: 7, cy: 8 }) + expect(rect.transform).toHaveBeenCalledWith({ scale: [5, 6], ox: 7, oy: 8 }, true) }) }) @@ -153,7 +153,7 @@ describe('Sugar', function() { it('redirects to transform()', function() { rect.translate(1,2) - expect(rect.transform).toHaveBeenCalledWith({ x: 1, y: 2 }) + expect(rect.transform).toHaveBeenCalledWith({ translate: [1, 2] }, true) }) }) @@ -171,19 +171,19 @@ describe('Sugar', function() { }) it('redirects to transform()', function() { - rect.flip('x',2) - expect(rect.transform).toHaveBeenCalledWith({ flip: 'x', offset: 2 }) + rect.flip('x', 2) + expect(rect.transform).toHaveBeenCalledWith({ flip: 'x', origin: [2, 0] }, true) }) it('sets flip to "both" when calling without anything', function() { rect.flip() - expect(rect.transform).toHaveBeenCalledWith({ flip: 'both', offset: undefined }) + expect(rect.transform).toHaveBeenCalledWith({ flip: 'both', origin: [0, 0] }, true) }) // this works because only x and y are valid flip values. Evereything else flips on both axis it('sets flip to number and offset to number when called with offset only', function() { rect.flip(5) - expect(rect.transform).toHaveBeenCalledWith({ flip: 5, offset: 5 }) + expect(rect.transform).toHaveBeenCalledWith({ flip: "both", origin: [5, 5] }, true) }) }) diff --git a/spec/spec/text.js b/spec/spec/text.js index 2a3f3f8..a17009e 100644 --- a/spec/spec/text.js +++ b/spec/spec/text.js @@ -135,7 +135,7 @@ describe('Text', function() { describe('translate()', function() { it('sets the translation of an element', function() { - text.transform({ x: 12, y: 12 }) + text.transform({ tx: 12, ty: 12 }) expect(text.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') }) }) diff --git a/spec/spec/transformations.js b/spec/spec/transformations.js index 3399981..242e798 100644 --- a/spec/spec/transformations.js +++ b/spec/spec/transformations.js @@ -1,282 +1,281 @@ -describe('Transformations:', function() { - var translated, scaled, rotated, skewed - - beforeEach(function() { - translated = draw.rect(100,100).translate(100,100) - scaled = draw.rect(100,100).scale(2) - rotated = draw.rect(100,100).rotate(45, 50, 50) - skewed = draw.rect(100,100).skew(30) - }) - - /* SVG.Transformation is not tested because it is an abstract prototype */ - - describe('SVG.Transformation', function() { - it('marks the transformation as inversed when inverse flag given', function() { - var trans = new SVG.Transformation([], true) - expect(trans.inversed).toBeTruthy() - }) - }) - - describe('SVG.Translate', function() { - var trans - - beforeEach(function(){ - trans = new SVG.Translate(translated.transform()) - }) - - - it('creates an object of type SVG.Transformation', function() { - expect(trans instanceof SVG.Transformation).toBeTruthy() - }) - - it('uses transformedX and transformedY as arguments', function() { - expect(trans.arguments).toEqual(['transformedX', 'transformedY']) - }) - - it('s method is translate()', function() { - expect(trans.method).toEqual('translate') - }) - - it('sets the necessary parameters at creation', function() { - expect(trans.transformedX).toBe(100) - expect(trans.transformedY).toBe(100) - }) - - describe('undo', function() { - it('sets the undo matrix which can undo the translation', function() { - var extracted = (new SVG.Matrix(1,0,0,1,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-20,-20)') - - var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-2,-2)') - - var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.e).toBeCloseTo(-extracted.transformedX) - expect(trans._undo.f).toBeCloseTo(-extracted.transformedY) - }) - }) - - describe('at', function() { - it('creates a matrix at a certain position', function() { - expect(trans.at(0.3).toString()).toEqual('matrix(1,0,0,1,30,30)') - }) - it('returns the inversed matrix from a specific position when created with inverse flag', function() { - expect((new SVG.Translate(translated.transform(), true)).at(0.3).toString()).toEqual('matrix(1,0,0,1,-30,-30)') - }) - it('returns the resulting transformation which has to be made to set an absolute translation', function() { - trans.undo(new SVG.Matrix(10,50,50,30,20,20).extract()) - - expect(trans.at(0.4).a).toEqual(1) - expect(trans.at(0.4).b).toEqual(0) - expect(trans.at(0.4).c).toEqual(0) - expect(trans.at(0.4).d).toEqual(1) - expect(trans.at(0.4).e).toBeCloseTo(100 * 0.4 + trans._undo.e * 0.4) - expect(trans.at(0.4).f).toBeCloseTo(100 * 0.4 + trans._undo.f * 0.4) - }) - }) - }) - - describe('SVG.Rotate', function() { - var trans - - beforeEach(function(){ - trans = new SVG.Rotate(45, 50, 50) - }) - - - it('creates an object of type SVG.Transformation', function() { - expect(trans instanceof SVG.Transformation).toBeTruthy() - }) - - it('uses rotation, cx and cy as arguments', function() { - expect(trans.arguments).toEqual(['rotation', 'cx', 'cy']) - }) - - it('s method is rotate()', function() { - expect(trans.method).toEqual('rotate') - }) - - it('sets the necessary parameters at creation', function() { - expect(trans.rotation).toBe(45) - expect(trans.cx).toBe(50) - expect(trans.cy).toBe(50) - }) - - describe('undo', function() { - it('sets an undo object which holds rotation', function() { - var extracted = (new SVG.Matrix(1,0,0,1,0,0)).rotate(20, 50, 50).extract() - trans.undo(extracted) - expect(trans._undo.rotation).toBeCloseTo(20) - }) - }) - - describe('at', function() { - it('creates a matrix at a certain position', function() { - expect(trans.at(0.3).toString()).toEqual((new SVG.Matrix()).rotate(0.3 * 45, 50, 50).toString()) - }) - it('returns the resulting transformation which has to be made to set an absolute translation', function() { - trans.undo((new SVG.Matrix()).rotate(20, 50, 50).extract()) - - expect(trans.at(0.4).a).toBeCloseTo(1,1) - expect(trans.at(0.4).b).toEqual(jasmine.any(Number)) - expect(trans.at(0.4).c).toEqual(jasmine.any(Number)) - expect(trans.at(0.4).d).toBeCloseTo(1,1) - expect(trans.at(0.4).e).toEqual(jasmine.any(Number)) - expect(trans.at(0.4).f).toEqual(jasmine.any(Number)) - }) - }) - }) - - - describe('SVG.Scale', function() { - var trans - - beforeEach(function(){ - trans = new SVG.Scale(2,2,50,50) - }) - - - it('creates an object of type SVG.Transformation', function() { - expect(trans instanceof SVG.Transformation).toBeTruthy() - }) - - it('uses scaleX, scaleY, cx and cy as arguments', function() { - expect(trans.arguments).toEqual(['scaleX', 'scaleY', 'cx', 'cy']) - }) - - it('s method is scale()', function() { - expect(trans.method).toEqual('scale') - }) - - it('sets the necessary parameters at creation', function() { - expect(trans.scaleX).toBe(2) - expect(trans.scaleY).toBe(2) - expect(trans.cx).toBe(50) - expect(trans.cy).toBe(50) - }) - - describe('undo', function() { - it('sets the undo matrix which can undo the translation', function() { - var extracted = (new SVG.Matrix(4,0,0,4,0,0)).extract() - trans.undo(extracted) - expect(trans._undo.toString()).toEqual('matrix(0.25,0,0,0.25,37.5,37.5)') - - var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX) - expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY) - expect(trans._undo.e).toBeCloseTo(45) - expect(trans._undo.f).toBeCloseTo(45) - - var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX) - expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY) - }) - }) - - describe('at', function() { - it('creates a matrix at a certain position', function() { - expect(trans.at(0.75).toString()).toEqual('matrix(1.75,0,0,1.75,-37.5,-37.5)') - }) - it('returns the inversed matrix from a specific position when created with inverse flag', function() { - var morphed = (new SVG.Scale(scaled.transform(2,2,50,50), true)).at(0.25) - - expect(morphed.a).toBeCloseTo(0.8) - expect(morphed.d).toBeCloseTo(0.8) - }) - it('returns the resulting transformation which has to be made to set an absolute translation', function() { - - var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).extract()).at(0.5) - - expect(morphed.a).toBeCloseTo(0.6) - expect(morphed.b).toEqual(0) - expect(morphed.c).toEqual(0) - expect(morphed.d).toBeCloseTo(0.6) - expect(morphed.e).toBeCloseTo(20) - expect(morphed.f).toBeCloseTo(20) - }) - }) - }) - - describe('SVG.Skew', function() { - var trans - - beforeEach(function(){ - trans = new SVG.Skew(30,-30,50,50) - }) - - - it('creates an object of type SVG.Transformation', function() { - expect(trans instanceof SVG.Transformation).toBeTruthy() - }) - - it('uses scaleX, scaleY, cx and cy as arguments', function() { - expect(trans.arguments).toEqual(['skewX', 'skewY', 'cx', 'cy']) - }) - - it('s method is skew()', function() { - expect(trans.method).toEqual('skew') - }) - - it('sets the necessary parameters at creation', function() { - expect(trans.skewX).toBe(30) - expect(trans.skewY).toBe(-30) - expect(trans.cx).toBe(50) - expect(trans.cy).toBe(50) - }) - - describe('undo', function() { - it('sets the undo matrix which can undo the translation', function() { - var extracted = (new SVG.Matrix()).skew(90, 90, 0, 0).extract() - trans.undo(extracted) - expect(trans._undo.a).toBeCloseTo(0) - expect(trans._undo.b).toBeCloseTo(0) - expect(trans._undo.c).toBeCloseTo(0) - expect(trans._undo.d).toBeCloseTo(0) - expect(trans._undo.e).toBeCloseTo(50) - expect(trans._undo.f).toBeCloseTo(50) - - var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() - trans.undo(extracted) - expect(trans._undo.a).toBeCloseTo(1) - expect(trans._undo.b).toBeCloseTo(0) - expect(trans._undo.c).toBeCloseTo(0) - expect(trans._undo.d).toBeCloseTo(1) - expect(trans._undo.e).toBeCloseTo(0) - expect(trans._undo.f).toBeCloseTo(0) - }) - }) - - describe('at', function() { - it('creates a matrix at a certain position', function() { - expect(trans.at(0.75)).toEqual((new SVG.Matrix()).morph((new SVG.Matrix()).skew(30, -30, 50, 50)).at(0.75)) - }) - it('returns the inversed matrix from a specific position when created with inverse flag', function() { - var morphed = (new SVG.Scale(skewed.transform(20,-20,50,50), true)).at(0.25) - - expect(morphed.a).toBeCloseTo(0.963) - expect(morphed.b).toBeCloseTo(0) - expect(morphed.c).toBeCloseTo(0) - expect(morphed.d).toBeCloseTo(0.963) - expect(morphed.e).toBeCloseTo(0) - expect(morphed.f).toBeCloseTo(0) - }) - it('returns the resulting transformation which has to be made to set an absolute translation', function() { - - var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).skew(20, 30, 20, 10).extract()).at(0.5) - - expect(morphed.a).toBeCloseTo(1.266) - expect(morphed.b).toBeCloseTo(-0.7310) - expect(morphed.c).toBeCloseTo(0.1351) - expect(morphed.d).toBeCloseTo(0.9220) - expect(morphed.e).toBeCloseTo(-20.05593) - expect(morphed.f).toBeCloseTo(40.4468) - }) - }) - }) - -}) +// describe('Transformations:', function() { +// var translated, scaled, rotated, skewed +// +// beforeEach(function() { +// translated = draw.rect(100,100).translate(100,100) +// scaled = draw.rect(100,100).scale(2) +// rotated = draw.rect(100,100).rotate(45, 50, 50) +// skewed = draw.rect(100,100).skew(30) +// }) +// +// /* SVG.Transformation is not tested because it is an abstract prototype */ +// +// describe('SVG.Transformation', function() { +// it('marks the transformation as inversed when inverse flag given', function() { +// var trans = new SVG.Transformation([], true) +// expect(trans.inversed).toBeTruthy() +// }) +// }) +// +// describe('SVG.Translate', function() { +// var trans +// +// beforeEach(function(){ +// trans = new SVG.Translate(translated.transform()) +// }) +// +// +// it('creates an object of type SVG.Transformation', function() { +// expect(trans instanceof SVG.Transformation).toBeTruthy() +// }) +// +// it('uses transformedX and transformedY as arguments', function() { +// expect(trans.arguments).toEqual(['transformedX', 'transformedY']) +// }) +// +// it('s method is translate()', function() { +// expect(trans.method).toEqual('translate') +// }) +// +// it('sets the necessary parameters at creation', function() { +// expect(trans.transformedX).toBe(100) +// expect(trans.transformedY).toBe(100) +// }) +// +// describe('undo', function() { +// it('sets the undo matrix which can undo the translation', function() { +// var extracted = (new SVG.Matrix(1,0,0,1,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-20,-20)') +// +// var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-2,-2)') +// +// var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.e).toBeCloseTo(-extracted.transformedX) +// expect(trans._undo.f).toBeCloseTo(-extracted.transformedY) +// }) +// }) +// +// describe('at', function() { +// it('creates a matrix at a certain position', function() { +// expect(trans.at(0.3).toString()).toEqual('matrix(1,0,0,1,30,30)') +// }) +// it('returns the inversed matrix from a specific position when created with inverse flag', function() { +// expect((new SVG.Translate(translated.transform(), true)).at(0.3).toString()).toEqual('matrix(1,0,0,1,-30,-30)') +// }) +// it('returns the resulting transformation which has to be made to set an absolute translation', function() { +// trans.undo(new SVG.Matrix(10,50,50,30,20,20).extract()) +// +// expect(trans.at(0.4).a).toEqual(1) +// expect(trans.at(0.4).b).toEqual(0) +// expect(trans.at(0.4).c).toEqual(0) +// expect(trans.at(0.4).d).toEqual(1) +// expect(trans.at(0.4).e).toBeCloseTo(100 * 0.4 + trans._undo.e * 0.4) +// expect(trans.at(0.4).f).toBeCloseTo(100 * 0.4 + trans._undo.f * 0.4) +// }) +// }) +// }) +// +// describe('SVG.Rotate', function() { +// var trans +// +// beforeEach(function(){ +// trans = new SVG.Rotate(45, 50, 50) +// }) +// +// +// it('creates an object of type SVG.Transformation', function() { +// expect(trans instanceof SVG.Transformation).toBeTruthy() +// }) +// +// it('uses rotation, cx and cy as arguments', function() { +// expect(trans.arguments).toEqual(['rotation', 'cx', 'cy']) +// }) +// +// it('s method is rotate()', function() { +// expect(trans.method).toEqual('rotate') +// }) +// +// it('sets the necessary parameters at creation', function() { +// expect(trans.rotation).toBe(45) +// expect(trans.cx).toBe(50) +// expect(trans.cy).toBe(50) +// }) +// +// describe('undo', function() { +// it('sets an undo object which holds rotation', function() { +// var extracted = (new SVG.Matrix(1,0,0,1,0,0)).rotate(20, 50, 50).extract() +// trans.undo(extracted) +// expect(trans._undo.rotation).toBeCloseTo(20) +// }) +// }) +// +// describe('at', function() { +// it('creates a matrix at a certain position', function() { +// expect(trans.at(0.3).toString()).toEqual((new SVG.Matrix()).rotate(0.3 * 45, 50, 50).toString()) +// }) +// it('returns the resulting transformation which has to be made to set an absolute translation', function() { +// trans.undo((new SVG.Matrix()).rotate(20, 50, 50).extract()) +// +// expect(trans.at(0.4).a).toBeCloseTo(1,1) +// expect(trans.at(0.4).b).toEqual(jasmine.any(Number)) +// expect(trans.at(0.4).c).toEqual(jasmine.any(Number)) +// expect(trans.at(0.4).d).toBeCloseTo(1,1) +// expect(trans.at(0.4).e).toEqual(jasmine.any(Number)) +// expect(trans.at(0.4).f).toEqual(jasmine.any(Number)) +// }) +// }) +// }) +// +// +// describe('SVG.Scale', function() { +// var trans +// +// beforeEach(function(){ +// trans = new SVG.Scale(2,2,50,50) +// }) +// +// +// it('creates an object of type SVG.Transformation', function() { +// expect(trans instanceof SVG.Transformation).toBeTruthy() +// }) +// +// it('uses scaleX, scaleY, cx and cy as arguments', function() { +// expect(trans.arguments).toEqual(['scaleX', 'scaleY', 'cx', 'cy']) +// }) +// +// it('s method is scale()', function() { +// expect(trans.method).toEqual('scale') +// }) +// +// it('sets the necessary parameters at creation', function() { +// expect(trans.scaleX).toBe(2) +// expect(trans.scaleY).toBe(2) +// expect(trans.cx).toBe(50) +// expect(trans.cy).toBe(50) +// }) +// +// describe('undo', function() { +// it('sets the undo matrix which can undo the translation', function() { +// var extracted = (new SVG.Matrix(4,0,0,4,0,0)).extract() +// trans.undo(extracted) +// expect(trans._undo.toString()).toEqual('matrix(0.25,0,0,0.25,37.5,37.5)') +// +// var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX) +// expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY) +// expect(trans._undo.e).toBeCloseTo(45) +// expect(trans._undo.f).toBeCloseTo(45) +// +// var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX) +// expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY) +// }) +// }) +// +// describe('at', function() { +// it('creates a matrix at a certain position', function() { +// expect(trans.at(0.75).toString()).toEqual('matrix(1.75,0,0,1.75,-37.5,-37.5)') +// }) +// it('returns the inversed matrix from a specific position when created with inverse flag', function() { +// var morphed = (new SVG.Scale(scaled.transform(2,2,50,50), true)).at(0.25) +// +// expect(morphed.a).toBeCloseTo(0.8) +// expect(morphed.d).toBeCloseTo(0.8) +// }) +// it('returns the resulting transformation which has to be made to set an absolute translation', function() { +// +// var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).extract()).at(0.5) +// +// expect(morphed.a).toBeCloseTo(0.6) +// expect(morphed.b).toEqual(0) +// expect(morphed.c).toEqual(0) +// expect(morphed.d).toBeCloseTo(0.6) +// expect(morphed.e).toBeCloseTo(20) +// expect(morphed.f).toBeCloseTo(20) +// }) +// }) +// }) +// +// describe('SVG.Skew', function() { +// var trans +// +// beforeEach(function(){ +// trans = new SVG.Skew(30,-30,50,50) +// }) +// +// +// it('creates an object of type SVG.Transformation', function() { +// expect(trans instanceof SVG.Transformation).toBeTruthy() +// }) +// +// it('uses scaleX, scaleY, cx and cy as arguments', function() { +// expect(trans.arguments).toEqual(['skewX', 'skewY', 'cx', 'cy']) +// }) +// +// it('s method is skew()', function() { +// expect(trans.method).toEqual('skew') +// }) +// +// it('sets the necessary parameters at creation', function() { +// expect(trans.skewX).toBe(30) +// expect(trans.skewY).toBe(-30) +// expect(trans.cx).toBe(50) +// expect(trans.cy).toBe(50) +// }) +// +// describe('undo', function() { +// it('sets the undo matrix which can undo the translation', function() { +// var extracted = (new SVG.Matrix()).skew(90, 90, 0, 0).extract() +// trans.undo(extracted) +// expect(trans._undo.a).toBeCloseTo(0) +// expect(trans._undo.b).toBeCloseTo(0) +// expect(trans._undo.c).toBeCloseTo(0) +// expect(trans._undo.d).toBeCloseTo(0) +// expect(trans._undo.e).toBeCloseTo(50) +// expect(trans._undo.f).toBeCloseTo(50) +// +// var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract() +// trans.undo(extracted) +// expect(trans._undo.a).toBeCloseTo(1) +// expect(trans._undo.b).toBeCloseTo(0) +// expect(trans._undo.c).toBeCloseTo(0) +// expect(trans._undo.d).toBeCloseTo(1) +// expect(trans._undo.e).toBeCloseTo(0) +// expect(trans._undo.f).toBeCloseTo(0) +// }) +// }) +// +// describe('at', function() { +// it('creates a matrix at a certain position', function() { +// expect(trans.at(0.75)).toEqual((new SVG.Matrix()).morph((new SVG.Matrix()).skew(30, -30, 50, 50)).at(0.75)) +// }) +// it('returns the inversed matrix from a specific position when created with inverse flag', function() { +// var morphed = (new SVG.Scale(skewed.transform(20,-20,50,50), true)).at(0.25) +// +// expect(morphed.a).toBeCloseTo(0.963) +// expect(morphed.b).toBeCloseTo(0) +// expect(morphed.c).toBeCloseTo(0) +// expect(morphed.d).toBeCloseTo(0.963) +// expect(morphed.e).toBeCloseTo(0) +// expect(morphed.f).toBeCloseTo(0) +// }) +// it('returns the resulting transformation which has to be made to set an absolute translation', function() { +// +// var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).skew(20, 30, 20, 10).extract()).at(0.5) +// +// expect(morphed.a).toBeCloseTo(1.266) +// expect(morphed.b).toBeCloseTo(-0.7310) +// expect(morphed.c).toBeCloseTo(0.1351) +// expect(morphed.d).toBeCloseTo(0.9220) +// expect(morphed.e).toBeCloseTo(-20.05593) +// expect(morphed.f).toBeCloseTo(40.4468) +// }) +// }) +// }) +// }) diff --git a/src/HtmlNode.js b/src/HtmlNode.js index e7dae10..e04b731 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -1,6 +1,7 @@ /* global createElement */ SVG.HtmlNode = SVG.invent({ + inherit: SVG.EventTarget, create: function (element) { this.node = element }, @@ -19,6 +20,10 @@ SVG.HtmlNode = SVG.invent({ put: function (element, i) { this.add(element, i) return element + }, + + getEventTarget: function () { + return this.node } } }) diff --git a/src/animator.js b/src/animator.js new file mode 100644 index 0000000..eb8ca72 --- /dev/null +++ b/src/animator.js @@ -0,0 +1,83 @@ +/* global requestAnimationFrame */ + +SVG.Animator = { + nextDraw: null, + frames: new SVG.Queue(), + timeouts: new SVG.Queue(), + timer: window.performance || window.Date, + transforms: [], + + frame: function (fn) { + // Store the node + var node = SVG.Animator.frames.push({ run: fn }) + + // Request an animation frame if we don't have one + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + // Return the node so we can remove it easily + return node + }, + + transform_frame: function (fn, id) { + SVG.Animator.transforms[id] = fn + }, + + timeout: function (fn, delay) { + delay = delay || 0 + + // Work out when the event should fire + var time = SVG.Animator.timer.now() + delay + + // Add the timeout to the end of the queue + var node = SVG.Animator.timeouts.push({ run: fn, time: time }) + + // Request another animation frame if we need one + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + return node + }, + + cancelFrame: function (node) { + SVG.Animator.frames.remove(node) + }, + + clearTimeout: function (node) { + SVG.Animator.timeouts.remove(node) + }, + + _draw: function (now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null
+ var lastTimeout = SVG.Animator.timeouts.last() + while ((nextTimeout = SVG.Animator.timeouts.shift())) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run() + } else { + SVG.Animator.timeouts.push(nextTimeout) + } + + // If we hit the last item, we should stop shifting out more items + if (nextTimeout === lastTimeout) break + } + + // Run all of the animation frames + var nextFrame = null + var lastFrame = SVG.Animator.frames.last() + while ((nextFrame !== lastFrame) && (nextFrame = SVG.Animator.frames.shift())) { + nextFrame.run() + } + + SVG.Animator.transforms.forEach(function (el) { el() }) + + // If we have remaining timeouts or frames, draw until we don't anymore + SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first() + ? requestAnimationFrame(SVG.Animator._draw) + : null + } +} diff --git a/src/array.js b/src/array.js index ca51d8e..aa43d5c 100644 --- a/src/array.js +++ b/src/array.js @@ -58,6 +58,9 @@ SVG.extend(SVG.Array, { return new SVG.Array(array) }, + toArray: function () { + return this.value + }, // Convert array to string toString: function () { return this.value.join(' ') diff --git a/src/bare.js b/src/bare.js index 44b762c..393ce6e 100644 --- a/src/bare.js +++ b/src/bare.js @@ -3,7 +3,7 @@ SVG.Bare = SVG.invent({ // Initialize create: function (element, inherit) { // construct element - this.constructor(SVG.create(element)) + SVG.Element.call(this, SVG.create(element)) // inherit custom methods if (inherit) { diff --git a/src/boxes.js b/src/boxes.js index f0154bd..a9247ef 100644 --- a/src/boxes.js +++ b/src/boxes.js @@ -68,6 +68,9 @@ SVG.Box = SVG.invent({ toString: function () { return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height }, + toArray: function () { + return [this.x, this.y, this.width, this.height] + }, morph: function (x, y, width, height) { this.destination = new SVG.Box(x, y, width, height) return this diff --git a/src/color.js b/src/color.js index 8f47f70..43bafcb 100644 --- a/src/color.js +++ b/src/color.js @@ -1,7 +1,36 @@ /* globals fullHex, compToHex */ +/* + +Color { + constructor (a, b, c, space) { + space: 'hsl' + a: 30 + b: 20 + c: 10 + }, + + toRgb () { return new Color in rgb space } + toHsl () { return new Color in hsl space } + toLab () { return new Color in lab space } + + toArray () { [space, a, b, c] } + fromArray () { convert it back } +} + +// Conversions aren't always exact because of monitor profiles etc... +new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl() +new Color(100, 100, 100, [space]) +new Color('hsl(30, 20, 10)') + +// Sugar +SVG.rgb(30, 20, 50).lab() +SVG.hsl() +SVG.lab('rgb(100, 100, 100)') +*/ + // Module for color convertions -SVG.Color = function (color) { +SVG.Color = function (color, g, b) { var match // initialize defaults @@ -30,10 +59,18 @@ SVG.Color = function (color) { this.g = parseInt(match[2], 16) this.b = parseInt(match[3], 16) } + } else if (Array.isArray(color)) { + this.r = color[0] + this.g = color[1] + this.b = color[2] } else if (typeof color === 'object') { this.r = color.r this.g = color.g this.b = color.b + } else if (arguments.length === 3) { + this.r = color + this.g = g + this.b = b } } @@ -42,12 +79,18 @@ SVG.extend(SVG.Color, { toString: function () { return this.toHex() }, + toArray: function () { + return [this.r, this.g, this.b] + }, + fromArray: function (a) { + return new SVG.Color(a) + }, // Build hex value toHex: function () { return '#' + - compToHex(this.r) + - compToHex(this.g) + - compToHex(this.b) + compToHex(Math.round(this.r)) + + compToHex(Math.round(this.g)) + + compToHex(Math.round(this.b)) }, // Build rgb value toRgb: function () { diff --git a/src/container.js b/src/container.js index 90e8f26..8b324bd 100644 --- a/src/container.js +++ b/src/container.js @@ -1,7 +1,7 @@ SVG.Container = SVG.invent({ // Initialize node create: function (node) { - this.constructor(node) + SVG.Element.call(this, node) }, // Inherit from diff --git a/src/controller.js b/src/controller.js new file mode 100644 index 0000000..842c772 --- /dev/null +++ b/src/controller.js @@ -0,0 +1,193 @@ + +// c = { +// finished: Whether or not we are finished +// } + +/*** +Base Class +========== +The base stepper class that will be +***/ + +function makeSetterGetter (k, f) { + return function (v) { + if (v == null) return this[v] + this[k] = v + if (f) f.call(this) + return this + } +} + +SVG.Stepper = SVG.invent({ + create: function () {} +}) + +/*** +Easing Functions +================ +***/ + +SVG.Ease = SVG.invent({ + inherit: SVG.Stepper, + + create: function (fn) { + SVG.Stepper.call(this, fn) + + this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn + }, + + extend: { + + step: function (from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to + } + return from + (to - from) * this.ease(pos) + }, + + done: function (dt, c) { + return false + } + } +}) + +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, + bezier: function (t0, x0, t1, x1) { + return function (t) { + // TODO: FINISH + } + } +} + +/*** +Controller Types +================ +***/ + +SVG.Controller = SVG.invent({ + inherit: SVG.Stepper, + + create: function (fn) { + SVG.Stepper.call(this, fn) + this.stepper = fn + }, + + extend: { + + step: function (current, target, dt, c) { + return this.stepper(current, target, dt, c) + }, + + done: function (c) { + return c.done + } + } +}) + +function recalculate () { + // Apply the default parameters + var duration = (this._duration || 500) / 1000 + var overshoot = this._overshoot || 0 + + // Calculate the PID natural response + var eps = 1e-10 + var pi = Math.PI + var os = Math.log(overshoot / 100 + eps) + var zeta = -os / Math.sqrt(pi * pi + os * os) + var wn = 3.9 / (zeta * duration) + + // Calculate the Spring values + this.d = 2 * zeta * wn + this.k = wn * wn +} + +SVG.Spring = SVG.invent({ + inherit: SVG.Controller, + + create: function (duration, overshoot) { + this.duration(duration || 500) + .overshoot(overshoot || 0) + }, + + extend: { + step: function (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + if (dt === Infinity) return target + if (dt === 0) return current + + if (dt > 100) dt = 16 + + dt /= 1000 + + // Get the previous velocity + var velocity = c.velocity || 0 + + // Apply the control to get the new position and store it + var acceleration = -this.d * velocity - this.k * (current - target) + var newPosition = current + + velocity * dt + + acceleration * dt * dt / 2 + + // Store the velocity + c.velocity = velocity + acceleration * dt + + // Figure out if we have converged, and if so, pass the value + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 + return c.done ? target : newPosition + }, + + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) + } +}) + +SVG.PID = SVG.invent({ + inherit: SVG.Controller, + + create: function (p, i, d, windup) { + SVG.Controller.call(this) + + p = p == null ? 0.1 : p + i = i == null ? 0.01 : i + d = d == null ? 0 : d + windup = windup == null ? 1000 : windup + this.p(p).i(i).d(d).windup(windup) + }, + + extend: { + step: function (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + + if (dt === Infinity) return target + if (dt === 0) return current + + var p = target - current + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt + var windup = this.windup + + // antiwindup + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) + } + + c.error = p + c.integral = i + + c.done = Math.abs(p) < 0.001 + + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) + }, + + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') + } +}) diff --git a/src/default.js b/src/default.js index c77b028..e82d1db 100644 --- a/src/default.js +++ b/src/default.js @@ -1,6 +1,15 @@ +SVG.void = function () {} + SVG.defaults = { + // Default animation values + timeline: { + duration: 400, + ease: '>', + delay: 0 + }, + // Default attribute values attrs: { @@ -1,7 +1,7 @@ SVG.Doc = SVG.invent({ // Initialize node create: function (node) { - this.constructor(node || SVG.create('svg')) + SVG.Element.call(this, node || SVG.create('svg')) // set svg element attributes and ensure defs node this.namespace() diff --git a/src/element.js b/src/element.js index 0d08579..f0d9e8e 100644 --- a/src/element.js +++ b/src/element.js @@ -1,6 +1,8 @@ /* global proportionalSize, assignNewId, createElement, matches, is */ SVG.Element = SVG.invent({ + inherit: SVG.EventTarget, + // Initialize node create: function (node) { // event listener @@ -42,7 +44,9 @@ SVG.Element = SVG.invent({ // Move by center over y-axis cy: function (y) { - return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2) + return y == null + ? this.y() + this.height() / 2 + : this.y(y - this.height() / 2) }, // Move element to given x and y values @@ -304,6 +308,9 @@ SVG.Element = SVG.invent({ }, is: function (obj) { return is(this, obj) + }, + getEventTarget: function () { + return this.node } } }) diff --git a/src/elemnts-svg.js b/src/elemnts-svg.js new file mode 100644 index 0000000..082ccd5 --- /dev/null +++ b/src/elemnts-svg.js @@ -0,0 +1,34 @@ + // Import raw svg + svg: function (svg) { + var well, len + + // act as getter if no svg string is given + if(svg == null || svg === true) { + // write svgjs data to the dom + this.writeDataToDom() + + // return outer or inner content + return svg + ? this.node.innerHTML + : this.node.outerHTML + } + + // act as setter if we got a string + + // make sure we are on a parent when trying to import + if(!(this instanceof SVG.Parent)) + throw Error('Cannot import svg into non-parent element') + + // create temporary holder + well = document.createElementNS(SVG.ns, 'svg') + + // dump raw svg + well.innerHTML = svg + + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) + } + + return this + },
\ No newline at end of file diff --git a/src/ellipse.js b/src/ellipse.js index eb310f9..8a8f027 100644 --- a/src/ellipse.js +++ b/src/ellipse.js @@ -16,7 +16,7 @@ SVG.Circle = SVG.invent({ } }) -SVG.extend([SVG.Circle, SVG.FX], { +SVG.extend([SVG.Circle, SVG.Timeline], { // Radius x value rx: function (rx) { return this.attr('r', rx) @@ -43,7 +43,7 @@ SVG.Ellipse = SVG.invent({ } }) -SVG.extend([SVG.Ellipse, SVG.Rect, SVG.FX], { +SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], { // Radius x value rx: function (rx) { return this.attr('rx', rx) diff --git a/src/event.js b/src/event.js index 65b13b0..64a791c 100644 --- a/src/event.js +++ b/src/event.js @@ -1,5 +1,5 @@ // Add events to elements - +/* ;[ 'click', 'dblclick', 'mousedown', @@ -21,23 +21,30 @@ return this } }) +*/ SVG.listenerId = 0 // Add event binder in the SVG namespace SVG.on = function (node, events, listener, binding, options) { var l = listener.bind(binding || node) - var n = node instanceof SVG.Element ? node.node : node + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node + + // events can be an array of events or a string of events + events = Array.isArray(events) ? events : events.split(SVG.regex.delimiter) // ensure instance object for nodes which are not adopted n.instance = n.instance || {events: {}} + // pull event handlers from the element var bag = n.instance.events // add id to listener - if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++SVG.listenerId } + if (!listener._svgjsListenerId) { + listener._svgjsListenerId = ++SVG.listenerId + } - events.split(SVG.regex.delimiter).forEach(function (event) { + events.forEach(function (event) { var ev = event.split('.')[0] var ns = event.split('.')[1] || '*' @@ -55,7 +62,7 @@ SVG.on = function (node, events, listener, binding, options) { // Add event unbinder in the SVG namespace SVG.off = function (node, events, listener, options) { - var n = node instanceof SVG.Element ? node.node : node + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node if (!n.instance) return // listener can be a function or a number @@ -64,9 +71,13 @@ SVG.off = function (node, events, listener, options) { if (!listener) return } + // pull event handlers from the element var bag = n.instance.events - ;(events || '').split(SVG.regex.delimiter).forEach(function (event) { + // events can be an array of events or a string or undefined + events = Array.isArray(events) ? events : (events || '').split(SVG.regex.delimiter) + + events.forEach(function (event) { var ev = event && event.split('.')[0] var ns = event && event.split('.')[1] var namespace, l @@ -109,29 +120,39 @@ SVG.off = function (node, events, listener, options) { }) } -SVG.extend(SVG.Element, { - // Bind given event to listener - on: function (event, listener, binding, options) { - SVG.on(this, event, listener, binding, options) - return this - }, - // Unbind event from listener - off: function (event, listener) { - SVG.off(this.node, event, listener) - return this - }, - dispatch: function (event, data) { - // Dispatch event - if (event instanceof window.Event) { - this.node.dispatchEvent(event) - } else { - this.node.dispatchEvent(event = new window.CustomEvent(event, {detail: data, cancelable: true})) +SVG.dispatch = function (node, event, data) { + var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node + + // Dispatch event + if (event instanceof window.Event) { + n.dispatchEvent(event) + } else { + event = new window.CustomEvent(event, {detail: data, cancelable: true}) + n.dispatchEvent(event) + } + return event +} + +SVG.EventTarget = SVG.invent({ + create: function () {}, + extend: { + // Bind given event to listener + on: function (event, listener, binding, options) { + SVG.on(this, event, listener, binding, options) + return this + }, + // Unbind event from listener + off: function (event, listener) { + SVG.off(this, event, listener) + return this + }, + dispatch: function (event, data) { + return SVG.dispatch(this, event, data) + }, + // Fire given event + fire: function (event, data) { + this.dispatch(event, data) + return this } - return event - }, - // Fire given event - fire: function (event, data) { - this.dispatch(event, data) - return this } }) @@ -11,890 +11,1358 @@ SVG.morph = function (pos) { } } -SVG.Situation = SVG.invent({ +let time = window.performance || window.Date - create: function (o) { - this.init = false - this.reversed = false - this.reversing = false +SVG.Timeline = SVG.invent ({ - this.duration = new SVG.Number(o.duration).valueOf() - this.delay = new SVG.Number(o.delay).valueOf() + create: function () { - this.start = +new Date() + this.delay - this.finish = this.start + this.duration - this.ease = o.ease + // Store all of the closures to animate + this._closures = [] - // this.loop is incremented from 0 to this.loops - // it is also incremented when in an infinite loop (when this.loops is true) - this.loop = 0 - this.loops = false + this._startTime = time.now() + this._duration = 0 + + this._running = true + + }, + + extend: { + + animate (duration, ease, delay, epoch) { + + } + + loop (times, reverse) { - this.animations = { - // functionToCall: [list of morphable objects] - // e.g. move: [SVG.Number, SVG.Number] } - this.attrs = { - // holds all attributes which are not represented from a function svg.js provides - // e.g. someAttr: SVG.Number + duration (time) { + this._duration = time } - this.styles = { - // holds all styles which should be animated - // e.g. fill-color: SVG.Color + delay (by, epoch) { + if (epoch) { + this._startTime = time.now() + } + this._duration = 0 + this._startTime += by } - this.transforms = [ - // holds all transformations as transformation objects - // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix] - ] + ease (fn) { - this.once = { - // functions to fire at a specific position - // e.g. "0.5": function foo(){} } - } -}) + play () + pause () + stop () + finish (all=true) + speed (newSpeed) + seek (dt) + persist (dt || forever) // 0 by default + reverse () -SVG.FX = SVG.invent({ - - create: function (element) { - this._target = element - this.situations = [] - this.active = false - this.situation = null - this.paused = false - this.lastPos = 0 - this.pos = 0 - // The absolute position of an animation is its position in the context of its complete duration (including delay and loops) - // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1 - this.absPos = 0 - this._speed = 1 - }, - extend: { - /** - * sets or returns the target of this animation - * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation - * @param ease function || string Function which should be used for easing or easing keyword - * @param delay Number indicating the delay before the animation starts - * @return target || this - */ - animate: function (o, ease, delay) { - if (typeof o === 'object') { - ease = o.ease - delay = o.delay - o = o.duration - } - var situation = new SVG.Situation({ - duration: o || 1000, - delay: delay || 0, - ease: SVG.easing[ease || '-'] || ease - }) - this.queue(situation) - return this - }, + // fn is a function that takes a position in range [0, 1] + schedule (fn) { // fn can not take parameters - /** - * sets a delay before the next element of the queue is called - * @param delay Duration of delay in milliseconds - * @return this.target() - */ - delay: function (delay) { - // The delay is performed by an empty situation with its duration - // attribute set to the duration of the delay - var situation = new SVG.Situation({ - duration: delay, - delay: 0, - ease: SVG.easing['-'] - }) - return this.queue(situation) - }, - /** - * sets or returns the target of this animation - * @param null || target SVG.Element which should be set as new target - * @return target || this - */ - target: function (target) { - if (target && target instanceof SVG.Element) { - this._target = target - return this - } - return this._target - }, - // returns the absolute position at a given time - timeToAbsPos: function (timestamp) { - return (timestamp - this.situation.start) / (this.situation.duration / this._speed) - }, - // returns the timestamp from a given absolute positon - absPosToTime: function (absPos) { - return this.situation.duration / this._speed * absPos + this.situation.start - }, +let declarative = rect.animate(300, '>', 200) + .loop().color('blue') + .animate(SVG.Spring(300)) - // starts the animationloop - startAnimFrame: function () { - this.stopAnimFrame() - this.animationFrame = window.requestAnimationFrame(function () { this.step() }.bind(this)) - }, +onmousemove() { + declarative.x(mouseX).y(mouseY) +} - // cancels the animationframe - stopAnimFrame: function () { - window.cancelAnimationFrame(this.animationFrame) - }, + SVG.MorphObj = SVG.invent({ - // kicks off the animation - only does something when the queue is currently not active and at least one situation is set - start: function () { - // dont start if already started - if (!this.active && this.situation) { - this.active = true - this.startCurrent() - } + create: function (from, to) { + // prepare color for morphing + if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to) + // prepare value list for morphing + if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) + // prepare number for morphing + if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) - return this - }, + // prepare for plain morphing + this.value = from + this.destination = to + }, - // start the current situation - startCurrent: function () { - this.situation.start = +new Date() + this.situation.delay / this._speed - this.situation.finish = this.situation.start + this.situation.duration / this._speed - return this.initAnimations().step() - }, + extend: { + at: function (pos, real) { + return real < 1 ? this.value : this.destination + }, - /** - * adds a function / Situation to the animation queue - * @param fn function / situation to add - * @return this - */ - queue: function (fn) { - if (typeof fn === 'function' || fn instanceof SVG.Situation) { - this.situations.push(fn) - } + valueOf: function () { + return this.value + } + } - if (!this.situation) this.situation = this.situations.shift() + }) - return this - }, - /** - * pulls next element from the queue and execute it - * @return this - */ - dequeue: function () { - // stop current animation - this.stop() - - // get next animation from queue - this.situation = this.situations.shift() - - if (this.situation) { - if (this.situation instanceof SVG.Situation) { - this.start() - } else { - // If it is not a SVG.Situation, then it is a function, we execute it - this.situation(this) - } - } +add('fill-color', val) - return this - }, +add('x', val, 'animations') - // updates all animations to the current state of the element - // this is important when one property could be changed from another property - initAnimations: function () { - var i, j, source - var s = this.situation +add('x', val, 'styles') - if (s.init) return this +add('line-cap', val, 'attrs') - for (i in s.animations) { - source = this.target()[i]() +.style(name, val) { - if (!Array.isArray(source)) { - source = [source] - } - if (!Array.isArray(s.animations[i])) { - s.animations[i] = [s.animations[i]] - } + styleAttr ('style', name, val) +} - // if(s.animations[i].length > source.length) { - // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length)) - // } +.animate(spring) - for (j = source.length; j--;) { - // The condition is because some methods return a normal number instead - // of a SVG.Number - if (s.animations[i][j] instanceof SVG.Number) { - source[j] = new SVG.Number(source[j]) - } +onmousemove(() => { + el.animate(SVG.Spring(500)) + .move(event.pointX, event.pointY) + .finish() +}) - s.animations[i][j] = source[j].morph(s.animations[i][j]) - } - } - for (i in s.attrs) { - s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i]) - } - for (i in s.styles) { - s.styles[i] = new SVG.MorphObj(this.target().css(i), s.styles[i]) - } +Morphable () - s.initialTransformation = this.target().matrixify() +Controlable () - s.init = true - return this - }, +new Controller(target, controller) - clearQueue: function () { - this.situations = [] - return this - }, - clearCurrent: function () { - this.situation = null - return this - }, - /** stops the animation immediately - * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately. - * @param clearQueue A Boolean indicating whether to remove queued animation as well. - * @return this - */ - stop: function (jumpToEnd, clearQueue) { - var active = this.active - this.active = false - - if (clearQueue) { - this.clearQueue() - } - if (jumpToEnd && this.situation) { - // initialize the situation if it was not - !active && this.startCurrent() - this.atEnd() - } +Number +Array +PathArray +ViewBox +PointArray +Color - this.stopAnimFrame() - return this.clearCurrent() - }, - /** resets the element to the state where the current element has started - * @return this - */ - reset: function () { - if (this.situation) { - var temp = this.situation - this.stop() - this.situation = temp - this.atStart() - } - return this - }, - // Stop the currently-running animation, remove all queued animations, and complete all animations for the element. - finish: function () { - this.stop(true, false) - while (this.dequeue().situation && this.stop(true, false)); - this.clearQueue().clearCurrent() - return this - }, - // set the internal animation pointer at the start position, before any loops, and updates the visualisation - atStart: function () { - return this.at(0, true) - }, - // set the internal animation pointer at the end position, after all the loops, and updates the visualisation - atEnd: function () { - if (this.situation.loops === true) { - // If in a infinite loop, we end the current iteration - this.situation.loops = this.situation.loop + 1 - } - if (typeof this.situation.loops === 'number') { - // If performing a finite number of loops, we go after all the loops - return this.at(this.situation.loops, true) - } else { - // If no loops, we just go at the end - return this.at(1, true) - } +SVG.Timeline = { + styleAttr (type, name, val) { + let morpher = new Morph(val).controller(this.controller) + queue ( + ()=> { + morpher = morpher.morph(element[type]('name')) + }, + morpher.at + ) + } +} + +.styleAttr (type, name, val) { + + let morpher = declarative ? new Controller(target) : new Morph().to(val) + queue ( + ()=> { + morpher = morpher.from(element[type](name)) }, + () => { + this.element[type](name, morpher.at(pos)) + } + ) +} - // set the internal animation pointer to the specified position and updates the visualisation - // if isAbsPos is true, pos is treated as an absolute position - at: function (pos, isAbsPos) { - var durDivSpd = this.situation.duration / this._speed +viewbox(box) { + new Box + let morpher = new Morph().to(box) // box: {width, heught, x, y} +} - this.absPos = pos - // If pos is not an absolute position, we convert it into one - if (!isAbsPos) { - if (this.situation.reversed) this.absPos = 1 - this.absPos - this.absPos += this.situation.loop - } - this.situation.start = +new Date() - this.absPos * durDivSpd - this.situation.finish = this.situation.start + durDivSpd +new Morph(from, to) - return this.step(true) - }, - /** - * sets or returns the speed of the animations - * @param speed null || Number The new speed of the animations - * @return Number || this - */ - speed: function (speed) { - if (speed === 0) return this.pause() - - if (speed) { - this._speed = speed - // We use an absolute position here so that speed can affect the delay before the animation - return this.at(this.absPos, true) - } else return this._speed - }, +new Morpg(from, to, controller = (from, to, pos) => {from + pos * (to - from)}) - // Make loopable - loop: function (times, reverse) { - var c = this.last() - // store total loops - c.loops = (times != null) ? times : true - c.loop = 0 +// Something line +path = "a, b, c" - if (reverse) c.reversing = true - return this - }, +SVG.color { + toArray: [r, g, b] + fromArray: new Color({r, g, b}) +} - // pauses the animation - pause: function () { - this.paused = true - this.stopAnimFrame() - return this - }, - // unpause the animation - play: function () { - if (!this.paused) return this - this.paused = false - // We use an absolute position here so that the delay before the animation can be paused - return this.at(this.absPos, true) - }, - /** - * toggle or set the direction of the animation - * true sets direction to backwards while false sets it to forwards - * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status) - * @return this - */ - reverse: function (reversed) { - var c = this.last() - if (typeof reversed === 'undefined') c.reversed = !c.reversed - else c.reversed = reversed - return this - }, +morph: function (pathArray) { + pathArray = new SVG.PathArray(pathArray) - /** - * returns a float from 0-1 indicating the progress of the current animation - * @param eased Boolean indicating whether the returned position should be eased or not - * @return number - */ - progress: function (easeIt) { - return easeIt ? this.situation.ease(this.pos) : this.pos - }, + if (this.equalCommands(pathArray)) { + this.destination = pathArray + } else { + this.destination = null + } - /** - * adds a callback function which is called when the current animation is finished - * @param fn Function which should be executed as callback - * @return number - */ - after: function (fn) { - var c = this.last() - function wrapper (e) { - if (e.detail.situation === c) { - fn.call(this, c) - this.off('finished.fx', wrapper) // prevent memory leak - } - } + return this +}, - this.target().on('finished.fx', wrapper) +[['M', 3, 5], ['L', 5, 6]] - return this._callStart() - }, +['M', 3, 4, 'L', ...] - // adds a callback which is called whenever one animation step is performed - during: function (fn) { - var c = this.last() - function wrapper (e) { - if (e.detail.situation === c) { - fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c) - } - } - // see above - this.target().off('during.fx', wrapper).on('during.fx', wrapper) - this.after(function () { - this.off('during.fx', wrapper) - }) - return this._callStart() - }, +function detectSomething (item) { + if(from instanceof SVG.Morphable) return from.controller(controller) + // prepare color for morphing + if (SVG.Color.isColor(to)) return new SVG.Color(from, controller) + // prepare value list for morphing + if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) + // prepare number for morphing + if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) - // calls after ALL animations in the queue are finished - afterAll: function (fn) { - var wrapper = function wrapper (e) { - fn.call(this) - this.off('allfinished.fx', wrapper) - } + return item +} - // see above - this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper) +foo->bar - return this._callStart() - }, - // calls on every animation step for all animations - duringAll: function (fn) { - var wrapper = function (e) { - fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation) - } +all of these things implement - this.target().off('during.fx', wrapper).on('during.fx', wrapper) +interface Morphable { + from: (thing)=> {} + to: (thing)=> {} + at: (pos)=> {} + controller: (fn (nowOrFrom, target, pos))=> {} +} - this.afterAll(function () { - this.off('during.fx', wrapper) - }) - return this._callStart() - }, +new SVG.MorphObj(el.attr(name)) - last: function () { - return this.situations.length ? this.situations[this.situations.length - 1] : this.situation - }, +animate().attr('line-joint', 5) - // adds one property to the animations - add: function (method, args, type) { - this.last()[type || 'animations'][method] = args - return this._callStart() +SVG.MorphObj = SVG.invent({ + + create: function (from, to) { + // prepare color for morphing + if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to) + // prepare value list for morphing + if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) + // prepare number for morphing + if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) + + // prepare for plain morphing + this.value = from + this.destination = to + }, + + extend: { + at: function (pos, real) { + return real < 1 ? this.value : this.destination }, - /** perform one step of the animation - * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time - * @return this - */ - step: function (ignoreTime) { - // convert current time to an absolute position - if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date()) - - // This part convert an absolute position to a position - if (this.situation.loops !== false) { - var absPos, absPosInt, lastLoop - - // If the absolute position is below 0, we just treat it as if it was 0 - absPos = Math.max(this.absPos, 0) - absPosInt = Math.floor(absPos) - - if (this.situation.loops === true || absPosInt < this.situation.loops) { - this.pos = absPos - absPosInt - lastLoop = this.situation.loop - this.situation.loop = absPosInt - } else { - this.absPos = this.situation.loops - this.pos = 1 - // The -1 here is because we don't want to toggle reversed when all the loops have been completed - lastLoop = this.situation.loop - 1 - this.situation.loop = this.situation.loops - } + valueOf: function () { + return this.value + } + } - if (this.situation.reversing) { - // Toggle reversed if an odd number of loops as occured since the last call of step - this.situation.reversed = this.situation.reversed !== Boolean((this.situation.loop - lastLoop) % 2) - } - } else { - // If there are no loop, the absolute position must not be above 1 - this.absPos = Math.min(this.absPos, 1) - this.pos = this.absPos - } +}) - // while the absolute position can be below 0, the position must not be below 0 - if (this.pos < 0) this.pos = 0 - if (this.situation.reversed) this.pos = 1 - this.pos +// Only works with a single number +new MorphObj { - // apply easing - var eased = this.situation.ease(this.pos) + constr: (control= (from, to, c)=> {from + pos * (to - from)}) { + } - // call once-callbacks - for (var i in this.situation.once) { - if (i > this.lastPos && i <= eased) { - this.situation.once[i].call(this.target(), this.pos, eased) - delete this.situation.once[i] - } - } + _detect: // Gets the user input and returns the right kind of object - // fire during callback with position, eased position and current situation as parameter - if (this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation}) + from: (from) => { - // the user may call stop or finish in the during callback - // so make sure that we still have a valid situation - if (!this.situation) { - return this - } + if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to) + // prepare value list for morphing + if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) + // prepare number for morphing + if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) - // apply the actual animation to every property - this.eachAt() + // prepare for plain morphing + this.value = from + this.destination = to + } - // do final code when situation is finished - if ((this.pos === 1 && !this.situation.reversed) || (this.situation.reversed && this.pos === 0)) { - // stop animation callback - this.stopAnimFrame() + to: (val) => { - // fire finished callback with current situation as parameter - this.target().fire('finished', {fx: this, situation: this.situation}) + } + at (pos) { - if (!this.situations.length) { - this.target().fire('allfinished') + let type = from.type + let from = from.toArray() + let to = to.toArray() + result = [] + for (i) + result[i] = this.controller(from[i], to[i], pos) : to[i] - // Recheck the length since the user may call animate in the afterAll callback - if (!this.situations.length) { - this.target().off('.fx') // there shouldnt be any binding left, but to make sure... - this.active = false - } - } + type.fromArray(result) + } +} - // start next animation - if (this.active) this.dequeue() - else this.clearCurrent() - } else if (!this.paused && this.active) { - // we continue animating when we are not at the end - this.startAnimFrame() - } +if(declartive) { + mropher.init() + morpher.at(pos/fn) +} - // save last eased position for once callback triggering - this.lastPos = eased - return this - }, - // calculates the step for every property and calls block with it - eachAt: function () { - var i, len, at - var self = this - var target = this.target() - var s = this.situation - // apply animations which can be called trough a method - for (i in s.animations) { - at = [].concat(s.animations[i]).map(function (el) { - return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el - }) +controller(currentPos, target) - target[i].apply(target, at) - } - // apply animation which has to be applied with attr() - for (i in s.attrs) { - at = [i].concat(s.attrs[i]).map(function (el) { - return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el - }) +morph interface +detect type function - target.attr.apply(target, at) - } - // apply animation which has to be applied with css() - for (i in s.styles) { - at = [i].concat(s.styles[i]).map(function (el) { - return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el - }) +if (mouse in box) + move box + animate(spring) - target.css.apply(target, at) - } +zoom(level, point) { + let morpher = SVG.Number(level).controller(this.controller) + this.queue( + () => {morpher = morpher.from(element.zoom())}, + (pos) => {element.zoom(morpher.at(pos), point)} + ) +} - // animate initialTransformation which has to be chained - if (s.transforms.length) { - // get initial initialTransformation - at = s.initialTransformation - for (i = 0, len = s.transforms.length; i < len; i++) { - // get next transformation in chain - var a = s.transforms[i] - - // multiply matrix directly - if (a instanceof SVG.Matrix) { - if (a.relative) { - at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos))) - } else { - at = at.morph(a).at(s.ease(this.pos)) - } - continue - } +x (x) { - // when transformation is absolute we have to reset the needed transformation first - if (!a.relative) { - a.undo(at.extract()) - } +} + +this.queue(fn, morpher) - // and reapply it after - at = at.multiply(a.at(s.ease(this.pos))) +new Morph(x(), xGiven) + + x: function (x, relative) { + if (this.target() instanceof SVG.G) { + this.transform({x: x}, relative) + return this } - // set new matrix on element - target.matrix(at) + var num = new SVG.Number(x) + num.relative = relative + return this.add('x', num) + }, + + + viewbox: function(box) { + var m = SVG.Box(box) } - return this - }, - // adds an once-callback which is called at a specific position and never again - once: function (pos, fn, isEased) { - var c = this.last() - if (!isEased) pos = c.ease(pos) + new Runner (function(time) { - c.once[pos] = fn - return this - }, + }) - _callStart: function () { - setTimeout(function () { this.start() }.bind(this), 0) - return this - } - }, + var closure = function (time) { + + // If it is time to do something, act now. + var running = start < time && time < end + if (running && this._running) { + closure.position = (time - closure.start) / closure.duration + fn (time) + } - parent: SVG.Element, + // If we are not paused or stopped, request another frame + if (this._running) SVG.Animator.frame(closure, this._startTime) - // Add method to parent elements - construct: { - // Get fx module or create a new one, then animate with given duration and ease - animate: function (o, ease, delay) { - return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay) - }, - delay: function (delay) { - return (this.fx || (this.fx = new SVG.FX(this))).delay(delay) - }, - stop: function (jumpToEnd, clearQueue) { - if (this.fx) { - this.fx.stop(jumpToEnd, clearQueue) - } + // Tell the caller whether this animation is finished + closure.finished = !running - return this - }, - finish: function () { - if (this.fx) { - this.fx.finish() - } + }.bind(this) - return this - }, - // Pause current animation - pause: function () { - if (this.fx) { - this.fx.pause() - } + closure.stop() // toggles a stop flag + closure.pause() + closure.run(t) // If it was paused, it - return this - }, - // Play paused current animation - play: function () { - if (this.fx) { this.fx.play() } - return this - }, - // Set/Get the speed of the animations - speed: function (speed) { - if (this.fx) { - if (speed == null) { return this.fx.speed() } else { this.fx.speed(speed) } - } + closure.start = this._startTime + closure.end = this._startTime + this._duration + closure.positon = + var forwards = true // Decide if running forward based on looping - return this + + // TODO: Store a list of closures + + SVG.Animator.timeout(closure, this._startTime) + _continue() } - } -}) + _step (dt) { -// MorphObj is used whenever no morphable object is given -SVG.MorphObj = SVG.invent({ + } - create: function (from, to) { - // prepare color for morphing - if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to) - // prepare value list for morphing - if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) - // prepare number for morphing - if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) + // Checks if we are running and continues the animation + _continue () { + , continue: function () { + if (this.paused) return + if (!this.nextFrame) + this.step() + return this + } - // prepare for plain morphing - this.value = from - this.destination = to + } }, - extend: { - at: function (pos, real) { - return real < 1 ? this.value : this.destination - }, - valueOf: function () { - return this.value + construct: { + animate: function(o, ease, delay, epoch) { + return (this.timeline = this.timeline || new SVG.Timeline(o, ease, delay, epoch)) } } - }) -SVG.extend(SVG.FX, { - // Add animatable attributes - attr: function (a, v, relative) { - // apply attributes individually - if (typeof a === 'object') { - for (var key in a) { - this.attr(key, a[key]) - } - } else { - this.add(a, v, 'attrs') - } - return this - }, - // Add animatable styles - css: function (s, v) { - if (typeof s === 'object') { - for (var key in s) { - this.css(key, s[key]) - } - } else { - this.add(s, v, 'styles') - } - return this - }, - // Animatable x-axis - x: function (x, relative) { - if (this.target() instanceof SVG.G) { - this.transform({x: x}, relative) - return this - } - var num = new SVG.Number(x) - num.relative = relative - return this.add('x', num) - }, - // Animatable y-axis - y: function (y, relative) { - if (this.target() instanceof SVG.G) { - this.transform({y: y}, relative) - return this - } - var num = new SVG.Number(y) - num.relative = relative - return this.add('y', num) - }, - // Animatable center x-axis - cx: function (x) { - return this.add('cx', new SVG.Number(x)) - }, - // Animatable center y-axis - cy: function (y) { - return this.add('cy', new SVG.Number(y)) - }, - // Add animatable move - move: function (x, y) { - return this.x(x).y(y) - }, - // Add animatable center - center: function (x, y) { - return this.cx(x).cy(y) - }, - // Add animatable size - size: function (width, height) { - if (this.target() instanceof SVG.Text) { - // animate font size for Text elements - this.attr('font-size', width) - } else { - // animate bbox based size for all other elements - var box - - if (!width || !height) { - box = this.target().bbox() - } - if (!width) { - width = box.width / box.height * height - } - if (!height) { - height = box.height / box.width * width - } - this.add('width', new SVG.Number(width)) - .add('height', new SVG.Number(height)) - } - return this - }, - // Add animatable width - width: function (width) { - return this.add('width', new SVG.Number(width)) - }, - // Add animatable height - height: function (height) { - return this.add('height', new SVG.Number(height)) - }, - // Add animatable plot - plot: function (a, b, c, d) { - // Lines can be plotted with 4 arguments - if (arguments.length === 4) { - return this.plot([a, b, c, d]) - } - return this.add('plot', new (this.target().MorphArray)(a)) - }, - // Add leading method - leading: function (value) { - return this.target().leading - ? this.add('leading', new SVG.Number(value)) - : this - }, - // Add animatable viewbox - viewbox: function (x, y, width, height) { - if (this.target() instanceof SVG.Container) { - this.add('viewbox', new SVG.Box(x, y, width, height)) - } - return this - }, - update: function (o) { - if (this.target() instanceof SVG.Stop) { - if (typeof o === 'number' || o instanceof SVG.Number) { - return this.update({ - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }) - } - if (o.opacity != null) this.attr('stop-opacity', o.opacity) - if (o.color != null) this.attr('stop-color', o.color) - if (o.offset != null) this.attr('offset', o.offset) - } - return this - } -}) + + + + + + + + + + + + + + + + + + + + + + + + +// SVG.Situation = SVG.invent({ +// +// create: function (o) { +// this.init = false +// this.reversed = false +// this.reversing = false +// +// this.duration = new SVG.Number(o.duration).valueOf() +// this.delay = new SVG.Number(o.delay).valueOf() +// +// this.start = +new Date() + this.delay +// this.finish = this.start + this.duration +// this.ease = o.ease +// +// // this.loop is incremented from 0 to this.loops +// // it is also incremented when in an infinite loop (when this.loops is true) +// this.loop = 0 +// this.loops = false +// +// this.animations = { +// // functionToCall: [list of morphable objects] +// // e.g. move: [SVG.Number, SVG.Number] +// } +// +// this.attrs = { +// // holds all attributes which are not represented from a function svg.js provides +// // e.g. someAttr: SVG.Number +// } +// +// this.styles = { +// // holds all styles which should be animated +// // e.g. fill-color: SVG.Color +// } +// +// this.transforms = [ +// // holds all transformations as transformation objects +// // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix] +// ] +// +// this.once = { +// // functions to fire at a specific position +// // e.g. "0.5": function foo(){} +// } +// } +// +// }) +// +// SVG.Timeline = SVG.invent({ +// +// create: function (element) { +// this._target = element +// this.situations = [] +// this.active = false +// this.situation = null +// this.paused = false +// this.lastPos = 0 +// this.pos = 0 +// // The absolute position of an animation is its position in the context of its complete duration (including delay and loops) +// // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1 +// this.absPos = 0 +// this._speed = 1 +// }, +// +// extend: { +// +// /** +// * sets or returns the target of this animation +// * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation +// * @param ease function || string Function which should be used for easing or easing keyword +// * @param delay Number indicating the delay before the animation starts +// * @return target || this +// */ +// animate: function (o, ease, delay) { +// if (typeof o === 'object') { +// ease = o.ease +// delay = o.delay +// o = o.duration +// } +// +// var situation = new SVG.Situation({ +// duration: o || 1000, +// delay: delay || 0, +// ease: SVG.easing[ease || '-'] || ease +// }) +// +// this.queue(situation) +// +// return this +// }, +// +// /** +// * sets a delay before the next element of the queue is called +// * @param delay Duration of delay in milliseconds +// * @return this.target() +// */ +// delay: function (delay) { +// // The delay is performed by an empty situation with its duration +// // attribute set to the duration of the delay +// var situation = new SVG.Situation({ +// duration: delay, +// delay: 0, +// ease: SVG.easing['-'] +// }) +// +// return this.queue(situation) +// }, +// +// /** +// * sets or returns the target of this animation +// * @param null || target SVG.Element which should be set as new target +// * @return target || this +// */ +// target: function (target) { +// if (target && target instanceof SVG.Element) { +// this._target = target +// return this +// } +// +// return this._target +// }, +// +// // returns the absolute position at a given time +// timeToAbsPos: function (timestamp) { +// return (timestamp - this.situation.start) / (this.situation.duration / this._speed) +// }, +// +// // returns the timestamp from a given absolute positon +// absPosToTime: function (absPos) { +// return this.situation.duration / this._speed * absPos + this.situation.start +// }, +// +// // starts the animationloop +// startAnimFrame: function () { +// this.stopAnimFrame() +// this.animationFrame = window.requestAnimationFrame(function () { this.step() }.bind(this)) +// }, +// +// // cancels the animationframe +// stopAnimFrame: function () { +// window.cancelAnimationFrame(this.animationFrame) +// }, +// +// // kicks off the animation - only does something when the queue is currently not active and at least one situation is set +// start: function () { +// // dont start if already started +// if (!this.active && this.situation) { +// this.active = true +// this.startCurrent() +// } +// +// return this +// }, +// +// // start the current situation +// startCurrent: function () { +// this.situation.start = +new Date() + this.situation.delay / this._speed +// this.situation.finish = this.situation.start + this.situation.duration / this._speed +// return this.initAnimations().step() +// }, +// +// /** +// * adds a function / Situation to the animation queue +// * @param fn function / situation to add +// * @return this +// */ +// queue: function (fn) { +// if (typeof fn === 'function' || fn instanceof SVG.Situation) { +// this.situations.push(fn) +// } +// +// if (!this.situation) this.situation = this.situations.shift() +// +// return this +// }, +// +// /** +// * pulls next element from the queue and execute it +// * @return this +// */ +// dequeue: function () { +// // stop current animation +// this.stop() +// +// // get next animation from queue +// this.situation = this.situations.shift() +// +// if (this.situation) { +// if (this.situation instanceof SVG.Situation) { +// this.start() +// } else { +// // If it is not a SVG.Situation, then it is a function, we execute it +// this.situation(this) +// } +// } +// +// return this +// }, +// +// // updates all animations to the current state of the element +// // this is important when one property could be changed from another property +// initAnimations: function () { +// var i, j, source +// var s = this.situation +// +// if (s.init) return this +// +// for (i in s.animations) { +// source = this.target()[i]() +// +// if (!Array.isArray(source)) { +// source = [source] +// } +// +// if (!Array.isArray(s.animations[i])) { +// s.animations[i] = [s.animations[i]] +// } +// +// // if(s.animations[i].length > source.length) { +// // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length)) +// // } +// +// for (j = source.length; j--;) { +// // The condition is because some methods return a normal number instead +// // of a SVG.Number +// if (s.animations[i][j] instanceof SVG.Number) { +// source[j] = new SVG.Number(source[j]) +// } +// +// s.animations[i][j] = source[j].morph(s.animations[i][j]) +// } +// } +// +// for (i in s.attrs) { +// s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i]) +// } +// +// for (i in s.styles) { +// s.styles[i] = new SVG.MorphObj(this.target().css(i), s.styles[i]) +// } +// +// s.initialTransformation = this.target().matrixify() +// +// s.init = true +// return this +// }, +// +// clearQueue: function () { +// this.situations = [] +// return this +// }, +// +// clearCurrent: function () { +// this.situation = null +// return this +// }, +// +// /** stops the animation immediately +// * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately. +// * @param clearQueue A Boolean indicating whether to remove queued animation as well. +// * @return this +// */ +// stop: function (jumpToEnd, clearQueue) { +// var active = this.active +// this.active = false +// +// if (clearQueue) { +// this.clearQueue() +// } +// +// if (jumpToEnd && this.situation) { +// // initialize the situation if it was not +// !active && this.startCurrent() +// this.atEnd() +// } +// +// this.stopAnimFrame() +// +// return this.clearCurrent() +// }, +// +// /** resets the element to the state where the current element has started +// * @return this +// */ +// reset: function () { +// if (this.situation) { +// var temp = this.situation +// this.stop() +// this.situation = temp +// this.atStart() +// } +// return this +// }, +// +// // Stop the currently-running animation, remove all queued animations, and complete all animations for the element. +// finish: function () { +// this.stop(true, false) +// +// while (this.dequeue().situation && this.stop(true, false)); +// +// this.clearQueue().clearCurrent() +// +// return this +// }, +// +// // set the internal animation pointer at the start position, before any loops, and updates the visualisation +// atStart: function () { +// return this.at(0, true) +// }, +// +// // set the internal animation pointer at the end position, after all the loops, and updates the visualisation +// atEnd: function () { +// if (this.situation.loops === true) { +// // If in a infinite loop, we end the current iteration +// this.situation.loops = this.situation.loop + 1 +// } +// +// if (typeof this.situation.loops === 'number') { +// // If performing a finite number of loops, we go after all the loops +// return this.at(this.situation.loops, true) +// } else { +// // If no loops, we just go at the end +// return this.at(1, true) +// } +// }, +// +// // set the internal animation pointer to the specified position and updates the visualisation +// // if isAbsPos is true, pos is treated as an absolute position +// at: function (pos, isAbsPos) { +// var durDivSpd = this.situation.duration / this._speed +// +// this.absPos = pos +// // If pos is not an absolute position, we convert it into one +// if (!isAbsPos) { +// if (this.situation.reversed) this.absPos = 1 - this.absPos +// this.absPos += this.situation.loop +// } +// +// this.situation.start = +new Date() - this.absPos * durDivSpd +// this.situation.finish = this.situation.start + durDivSpd +// +// return this.step(true) +// }, +// +// /** +// * sets or returns the speed of the animations +// * @param speed null || Number The new speed of the animations +// * @return Number || this +// */ +// speed: function (speed) { +// if (speed === 0) return this.pause() +// +// if (speed) { +// this._speed = speed +// // We use an absolute position here so that speed can affect the delay before the animation +// return this.at(this.absPos, true) +// } else return this._speed +// }, +// +// // Make loopable +// loop: function (times, reverse) { +// var c = this.last() +// +// // store total loops +// c.loops = (times != null) ? times : true +// c.loop = 0 +// +// if (reverse) c.reversing = true +// return this +// }, +// +// // pauses the animation +// pause: function () { +// this.paused = true +// this.stopAnimFrame() +// +// return this +// }, +// +// // unpause the animation +// play: function () { +// if (!this.paused) return this +// this.paused = false +// // We use an absolute position here so that the delay before the animation can be paused +// return this.at(this.absPos, true) +// }, +// +// /** +// * toggle or set the direction of the animation +// * true sets direction to backwards while false sets it to forwards +// * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status) +// * @return this +// */ +// reverse: function (reversed) { +// var c = this.last() +// +// if (typeof reversed === 'undefined') c.reversed = !c.reversed +// else c.reversed = reversed +// +// return this +// }, +// +// /** +// * returns a float from 0-1 indicating the progress of the current animation +// * @param eased Boolean indicating whether the returned position should be eased or not +// * @return number +// */ +// progress: function (easeIt) { +// return easeIt ? this.situation.ease(this.pos) : this.pos +// }, +// +// /** +// * adds a callback function which is called when the current animation is finished +// * @param fn Function which should be executed as callback +// * @return number +// */ +// after: function (fn) { +// var c = this.last() +// function wrapper (e) { +// if (e.detail.situation === c) { +// fn.call(this, c) +// this.off('finished.fx', wrapper) // prevent memory leak +// } +// } +// +// this.target().on('finished.fx', wrapper) +// +// return this._callStart() +// }, +// +// // adds a callback which is called whenever one animation step is performed +// during: function (fn) { +// var c = this.last() +// function wrapper (e) { +// if (e.detail.situation === c) { +// fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c) +// } +// } +// +// // see above +// this.target().off('during.fx', wrapper).on('during.fx', wrapper) +// +// this.after(function () { +// this.off('during.fx', wrapper) +// }) +// +// return this._callStart() +// }, +// +// // calls after ALL animations in the queue are finished +// afterAll: function (fn) { +// var wrapper = function wrapper (e) { +// fn.call(this) +// this.off('allfinished.fx', wrapper) +// } +// +// // see above +// this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper) +// +// return this._callStart() +// }, +// +// // calls on every animation step for all animations +// duringAll: function (fn) { +// var wrapper = function (e) { +// fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation) +// } +// +// this.target().off('during.fx', wrapper).on('during.fx', wrapper) +// +// this.afterAll(function () { +// this.off('during.fx', wrapper) +// }) +// +// return this._callStart() +// }, +// +// last: function () { +// return this.situations.length ? this.situations[this.situations.length - 1] : this.situation +// }, +// +// // adds one property to the animations +// add: function (method, args, type) { +// this.last()[type || 'animations'][method] = args +// return this._callStart() +// }, +// +// /** perform one step of the animation +// * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time +// * @return this +// */ +// step: function (ignoreTime) { +// // convert current time to an absolute position +// if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date()) +// +// // This part convert an absolute position to a position +// if (this.situation.loops !== false) { +// var absPos, absPosInt, lastLoop +// +// // If the absolute position is below 0, we just treat it as if it was 0 +// absPos = Math.max(this.absPos, 0) +// absPosInt = Math.floor(absPos) +// +// if (this.situation.loops === true || absPosInt < this.situation.loops) { +// this.pos = absPos - absPosInt +// lastLoop = this.situation.loop +// this.situation.loop = absPosInt +// } else { +// this.absPos = this.situation.loops +// this.pos = 1 +// // The -1 here is because we don't want to toggle reversed when all the loops have been completed +// lastLoop = this.situation.loop - 1 +// this.situation.loop = this.situation.loops +// } +// +// if (this.situation.reversing) { +// // Toggle reversed if an odd number of loops as occured since the last call of step +// this.situation.reversed = this.situation.reversed !== Boolean((this.situation.loop - lastLoop) % 2) +// } +// } else { +// // If there are no loop, the absolute position must not be above 1 +// this.absPos = Math.min(this.absPos, 1) +// this.pos = this.absPos +// } +// +// // while the absolute position can be below 0, the position must not be below 0 +// if (this.pos < 0) this.pos = 0 +// +// if (this.situation.reversed) this.pos = 1 - this.pos +// +// // apply easing +// var eased = this.situation.ease(this.pos) +// +// // call once-callbacks +// for (var i in this.situation.once) { +// if (i > this.lastPos && i <= eased) { +// this.situation.once[i].call(this.target(), this.pos, eased) +// delete this.situation.once[i] +// } +// } +// +// // fire during callback with position, eased position and current situation as parameter +// if (this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation}) +// +// // the user may call stop or finish in the during callback +// // so make sure that we still have a valid situation +// if (!this.situation) { +// return this +// } +// +// // apply the actual animation to every property +// this.eachAt() +// +// // do final code when situation is finished +// if ((this.pos === 1 && !this.situation.reversed) || (this.situation.reversed && this.pos === 0)) { +// // stop animation callback +// this.stopAnimFrame() +// +// // fire finished callback with current situation as parameter +// this.target().fire('finished', {fx: this, situation: this.situation}) +// +// if (!this.situations.length) { +// this.target().fire('allfinished') +// +// // Recheck the length since the user may call animate in the afterAll callback +// if (!this.situations.length) { +// this.target().off('.fx') // there shouldnt be any binding left, but to make sure... +// this.active = false +// } +// } +// +// // start next animation +// if (this.active) this.dequeue() +// else this.clearCurrent() +// } else if (!this.paused && this.active) { +// // we continue animating when we are not at the end +// this.startAnimFrame() +// } +// +// // save last eased position for once callback triggering +// this.lastPos = eased +// return this +// }, +// +// // calculates the step for every property and calls block with it +// eachAt: function () { +// var i, at +// var self = this +// var target = this.target() +// var s = this.situation +// +// // apply animations which can be called trough a method +// for (i in s.animations) { +// at = [].concat(s.animations[i]).map(function (el) { +// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el +// }) +// +// target[i].apply(target, at) +// } +// +// // apply animation which has to be applied with attr() +// for (i in s.attrs) { +// at = [i].concat(s.attrs[i]).map(function (el) { +// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el +// }) +// +// target.attr.apply(target, at) +// } +// +// // apply animation which has to be applied with css() +// for (i in s.styles) { +// at = [i].concat(s.styles[i]).map(function (el) { +// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el +// }) +// +// target.css.apply(target, at) +// } +// +// // animate initialTransformation which has to be chained +// if (s.transforms.length) { +// +// // TODO: ANIMATE THE TRANSFORMS +// +// // // get initial initialTransformation +// // at = s.initialTransformation +// // for(i = 0, len = s.transforms.length; i < len; i++){ +// // +// // // get next transformation in chain +// // var a = s.transforms[i] +// // +// // // multiply matrix directly +// // if(a instanceof SVG.Matrix){ +// // +// // if(a.relative){ +// // at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos))) +// // }else{ +// // at = at.morph(a).at(s.ease(this.pos)) +// // } +// // continue +// // } +// // +// // // when transformation is absolute we have to reset the needed transformation first +// // if(!a.relative) +// // a.undo(at.decompose()) +// // +// // // and reapply it after +// // at = at.multiply(a.at(s.ease(this.pos))) +// // +// // } +// // +// // // set new matrix on element +// // target.matrix(at) +// } +// +// return this +// }, +// +// // adds an once-callback which is called at a specific position and never again +// once: function (pos, fn, isEased) { +// var c = this.last() +// if (!isEased) pos = c.ease(pos) +// +// c.once[pos] = fn +// +// return this +// }, +// +// _callStart: function () { +// setTimeout(function () { this.start() }.bind(this), 0) +// return this +// } +// +// }, +// +// parent: SVG.Element, +// +// // Add method to parent elements +// construct: { +// // Get fx module or create a new one, then animate with given duration and ease +// animate: function (o, ease, delay) { +// return (this.fx || (this.fx = new SVG.Timeline(this))).animate(o, ease, delay) +// }, +// delay: function (delay) { +// return (this.fx || (this.fx = new SVG.Timeline(this))).delay(delay) +// }, +// stop: function (jumpToEnd, clearQueue) { +// if (this.fx) { +// this.fx.stop(jumpToEnd, clearQueue) +// } +// +// return this +// }, +// finish: function () { +// if (this.fx) { +// this.fx.finish() +// } +// +// return this +// }, +// // Pause current animation +// pause: function () { +// if (this.fx) { +// this.fx.pause() +// } +// +// return this +// }, +// // Play paused current animation +// play: function () { +// if (this.fx) { this.fx.play() } +// +// return this +// }, +// // Set/Get the speed of the animations +// speed: function (speed) { +// if (this.fx) { +// if (speed == null) { return this.fx.speed() } else { this.fx.speed(speed) } +// } +// +// return this +// } +// } +// +// }) +// +// // MorphObj is used whenever no morphable object is given +// SVG.MorphObj = SVG.invent({ +// +// create: function (from, to) { +// // prepare color for morphing +// if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to) +// // prepare value list for morphing +// if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to) +// // prepare number for morphing +// if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to) +// +// // prepare for plain morphing +// this.value = from +// this.destination = to +// }, +// +// extend: { +// at: function (pos, real) { +// return real < 1 ? this.value : this.destination +// }, +// +// valueOf: function () { +// return this.value +// } +// } +// +// }) +// +// SVG.extend(SVG.Timeline, { +// // Add animatable attributes +// attr: function (a, v, relative) { +// // apply attributes individually +// if (typeof a === 'object') { +// for (var key in a) { +// this.attr(key, a[key]) +// } +// } else { +// this.add(a, v, 'attrs') +// } +// +// return this +// }, +// // Add animatable styles +// css: function (s, v) { +// if (typeof s === 'object') { +// for (var key in s) { +// this.css(key, s[key]) +// } +// } else { +// this.add(s, v, 'styles') +// } +// +// return this +// }, +// // Animatable x-axis +// x: function (x, relative) { +// if (this.target() instanceof SVG.G) { +// this.transform({x: x}, relative) +// return this +// } +// +// var num = new SVG.Number(x) +// num.relative = relative +// return this.add('x', num) +// }, +// // Animatable y-axis +// y: function (y, relative) { +// if (this.target() instanceof SVG.G) { +// this.transform({y: y}, relative) +// return this +// } +// +// var num = new SVG.Number(y) +// num.relative = relative +// return this.add('y', num) +// }, +// // Animatable center x-axis +// cx: function (x) { +// return this.add('cx', new SVG.Number(x)) +// }, +// // Animatable center y-axis +// cy: function (y) { +// return this.add('cy', new SVG.Number(y)) +// }, +// // Add animatable move +// move: function (x, y) { +// return this.x(x).y(y) +// }, +// // Add animatable center +// center: function (x, y) { +// return this.cx(x).cy(y) +// }, +// // Add animatable size +// size: function (width, height) { +// if (this.target() instanceof SVG.Text) { +// // animate font size for Text elements +// this.attr('font-size', width) +// } else { +// // animate bbox based size for all other elements +// var box +// +// if (!width || !height) { +// box = this.target().bbox() +// } +// +// if (!width) { +// width = box.width / box.height * height +// } +// +// if (!height) { +// height = box.height / box.width * width +// } +// +// this.add('width', new SVG.Number(width)) +// .add('height', new SVG.Number(height)) +// } +// +// return this +// }, +// // Add animatable width +// width: function (width) { +// return this.add('width', new SVG.Number(width)) +// }, +// // Add animatable height +// height: function (height) { +// return this.add('height', new SVG.Number(height)) +// }, +// // Add animatable plot +// plot: function (a, b, c, d) { +// // Lines can be plotted with 4 arguments +// if (arguments.length === 4) { +// return this.plot([a, b, c, d]) +// } +// +// return this.add('plot', new (this.target().MorphArray)(a)) +// }, +// // Add leading method +// leading: function (value) { +// return this.target().leading +// ? this.add('leading', new SVG.Number(value)) +// : this +// }, +// // Add animatable viewbox +// viewbox: function (x, y, width, height) { +// if (this.target() instanceof SVG.Container) { +// this.add('viewbox', new SVG.Box(x, y, width, height)) +// } +// +// return this +// }, +// update: function (o) { +// if (this.target() instanceof SVG.Stop) { +// if (typeof o === 'number' || o instanceof SVG.Number) { +// return this.update({ +// offset: arguments[0], +// color: arguments[1], +// opacity: arguments[2] +// }) +// } +// +// if (o.opacity != null) this.attr('stop-opacity', o.opacity) +// if (o.color != null) this.attr('stop-color', o.color) +// if (o.offset != null) this.attr('offset', o.offset) +// } +// +// return this +// } +// }) diff --git a/src/gradient.js b/src/gradient.js index ea2197b..45a4e08 100644 --- a/src/gradient.js +++ b/src/gradient.js @@ -1,7 +1,7 @@ SVG.Gradient = SVG.invent({ // Initialize node create: function (type) { - this.constructor(typeof type === 'object' ? type : SVG.create(type + 'Gradient')) + SVG.Element.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient')) }, // Inherit from @@ -50,7 +50,7 @@ SVG.Gradient = SVG.invent({ }) // Add animatable methods to both gradient and fx module -SVG.extend([SVG.Gradient, SVG.FX], { +SVG.extend([SVG.Gradient, SVG.Timeline], { // From position from: function (x, y) { return (this._target || this).type === 'radialGradient' @@ -101,5 +101,4 @@ SVG.Stop = SVG.invent({ return this } } - }) diff --git a/src/group.js b/src/group.js index f0d3d8b..0088a1c 100644 --- a/src/group.js +++ b/src/group.js @@ -7,36 +7,6 @@ SVG.G = SVG.invent({ // Add class methods extend: { - // Move over x-axis - x: function (x) { - return x == null ? this.transform('x') : this.transform({ x: x - this.x() }, true) - }, - // Move over y-axis - y: function (y) { - return y == null ? this.transform('y') : this.transform({ y: y - this.y() }, true) - }, - // Move by center over x-axis - cx: function (x) { - return x == null ? this.gbox().cx : this.x(x - this.gbox().width / 2) - }, - // Move by center over y-axis - cy: function (y) { - return y == null ? this.gbox().cy : this.y(y - this.gbox().height / 2) - }, - gbox: function () { - var bbox = this.bbox() - var trans = this.transform() - - bbox.x += trans.x - bbox.x2 += trans.x - bbox.cx += trans.x - - bbox.y += trans.y - bbox.y2 += trans.y - bbox.cy += trans.y - - return bbox - } }, // Add parent method diff --git a/src/helpers.js b/src/helpers.js index 9a7f47e..c2073cf 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -109,28 +109,11 @@ function proportionalSize (element, width, height) { } } -// Delta transform point -function deltaTransformPoint (matrix, x, y) { - return { - x: x * matrix.a + y * matrix.c + 0, - y: x * matrix.b + y * matrix.d + 0 - } -} - // Map matrix array to object function arrayToMatrix (a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } } -// Parse matrix if required -function parseMatrix (matrix) { - if (!(matrix instanceof SVG.Matrix)) { - matrix = new SVG.Matrix(matrix) - } - - return matrix -} - // Add centre point to transform object function ensureCentre (o, target) { o.cx = o.cx == null ? target.bbox().cx : o.cx @@ -216,3 +199,113 @@ function idFromReference (url) { // Create matrix array for looping var abcdef = 'abcdef'.split('') + +function closeEnough (a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6) +} + +function isMatrixLike (o) { + return ( + o.a != null || + o.b != null || + o.c != null || + o.d != null || + o.e != null || + o.f != null + ) +} + +// TODO: Refactor this to a static function of matrix.js +function formatTransforms (o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 + var skewX = o.skew && o.skew.length ? o.skew[0] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewX) ? o.skewX + : 0 + var skewY = o.skew && o.skew.length ? o.skew[1] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewY) ? o.skewY + : 0 + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX + : isFinite(o.scale) ? o.scale * flipX + : isFinite(o.scaleX) ? o.scaleX * flipX + : flipX + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY + : isFinite(o.scale) ? o.scale * flipY + : isFinite(o.scaleY) ? o.scaleY * flipY + : flipY + var shear = o.shear || 0 + var theta = o.rotate || o.theta || 0 + var origin = new SVG.Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) + var ox = origin.x + var oy = origin.y + var position = new SVG.Point(o.position || o.px || o.positionX, o.py || o.positionY) + var px = position.x + var py = position.y + var translate = new SVG.Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) + var tx = translate.x + var ty = translate.y + var relative = new SVG.Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) + var rx = relative.x + var ry = relative.y + + // Populate all of the values + return { + scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py + } +} + +// left matrix, right matrix, target matrix which is overwritten +function matrixMultiply (l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b + var b = l.b * r.a + l.d * r.b + var c = l.a * r.c + l.c * r.d + var d = l.b * r.c + l.d * r.d + var e = l.e + l.a * r.e + l.c * r.f + var f = l.f + l.b * r.e + l.d * r.f + + // make sure to use local variables because l/r and o could be the same + o.a = a + o.b = b + o.c = c + o.d = d + o.e = e + o.f = f + + return o +} + +function getOrigin (o, element) { + // Allow origin or around as the names + let origin = o.origin // o.around == null ? o.origin : o.around + let ox, oy + + // Allow the user to pass a string to rotate around a given point + if (typeof origin === 'string' || origin == null) { + // Get the bounding box of the element with no transformations applied + const string = (origin || 'center').toLowerCase().trim() + const { height, width, x, y } = element.bbox() + + // Calculate the transformed x and y coordinates + let bx = string.includes('left') ? x + : string.includes('right') ? x + width + : x + width / 2 + let by = string.includes('top') ? y + : string.includes('bottom') ? y + height + : y + height / 2 + + // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + ox = o.ox != null ? o.ox : bx + oy = o.oy != null ? o.oy : by + } else { + ox = origin[0] + oy = origin[1] + } + + // Return the origin as it is if it wasn't a string + return [ ox, oy ] +} diff --git a/src/line.js b/src/line.js index 100d625..da0c0ca 100644 --- a/src/line.js +++ b/src/line.js @@ -16,6 +16,7 @@ SVG.Line = SVG.invent({ [ this.attr('x2'), this.attr('y2') ] ]) }, + // Overwrite native plot() method plot: function (x1, y1, x2, y2) { if (x1 == null) { @@ -28,10 +29,12 @@ SVG.Line = SVG.invent({ return this.attr(x1) }, + // Move by left top corner move: function (x, y) { return this.attr(this.array().move(x, y).toLine()) }, + // Set element size to given width and height size: function (width, height) { var p = proportionalSize(this, width, height) diff --git a/src/matrix.js b/src/matrix.js index e823a81..666b898 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -1,76 +1,168 @@ -/* global abcdef, arrayToMatrix, deltaTransformPoint, parseMatrix */ +/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */ SVG.Matrix = SVG.invent({ // Initialize create: function (source) { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) - var i // ensure source as object source = source instanceof SVG.Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) - : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : Array.isArray(source) ? arrayToMatrix(source) - : typeof source === 'object' ? source + : (typeof source === 'object' && isMatrixLike(source)) ? source + : (typeof source === 'object') ? new SVG.Matrix().transform(source) + : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base - // merge source - for (i = abcdef.length - 1; i >= 0; --i) { - this[abcdef[i]] = source[abcdef[i]] != null - ? source[abcdef[i]] - : base[abcdef[i]] - } + // Merge the source matrix with the base matrix + this.a = source.a != null ? source.a : base.a + this.b = source.b != null ? source.b : base.b + this.c = source.c != null ? source.c : base.c + this.d = source.d != null ? source.d : base.d + this.e = source.e != null ? source.e : base.e + this.f = source.f != null ? source.f : base.f }, // Add methods extend: { - // Extract individual transformations - extract: function () { - // find delta transform points - var px = deltaTransformPoint(this, 0, 1) - var py = deltaTransformPoint(this, 1, 0) - var skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90 + // Clones this matrix + clone: function () { + return new SVG.Matrix(this) + }, + + // Transform a matrix into another matrix by manipulating the space + transform: function (o) { + // Check if o is a matrix and then left multiply it directly + if (isMatrixLike(o)) { + var matrix = new SVG.Matrix(o) + return matrix.multiplyO(this) + } + + // Get the proposed transformations and the current transformations + var t = formatTransforms(o) + var current = this + let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current) + + // Construct the resulting matrix + var transformer = new SVG.Matrix() + .translateO(t.rx, t.ry) + .lmultiplyO(current) + .translateO(-ox, -oy) + .scaleO(t.scaleX, t.scaleY) + .skewO(t.skewX, t.skewY) + .shearO(t.shear) + .rotateO(t.theta) + .translateO(ox, oy) + + // If we want the origin at a particular place, we force it there + if (isFinite(t.px) || isFinite(t.py)) { + const origin = new SVG.Point(ox, oy).transform(transformer) + // TODO: Replace t.px with isFinite(t.px) + const dx = t.px ? t.px - origin.x : 0 + const dy = t.py ? t.py - origin.y : 0 + transformer.translateO(dx, dy) + } + + // Translate now after positioning + transformer.translateO(t.tx, t.ty) + return transformer + }, + + // Applies a matrix defined by its affine parameters + compose: function (o) { + if (o.origin) { + o.originX = o.origin[0] + o.originY = o.origin[1] + } + // Get the parameters + var ox = o.originX || 0 + var oy = o.originY || 0 + var sx = o.scaleX || 1 + var sy = o.scaleY || 1 + var lam = o.shear || 0 + var theta = o.rotate || 0 + var tx = o.translateX || 0 + var ty = o.translateY || 0 + + // Apply the standard matrix + var result = new SVG.Matrix() + .translateO(-ox, -oy) + .scaleO(sx, sy) + .shearO(lam) + .rotateO(theta) + .translateO(tx, ty) + .lmultiplyO(this) + .translateO(ox, oy) + return result + }, + + // Decomposes this matrix into its affine parameters + decompose: function (cx = 0, cy = 0) { + // Get the parameters from the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Figure out if the winding direction is clockwise or counterclockwise + var determinant = a * d - b * c + var ccw = determinant > 0 ? 1 : -1 + + // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + var sx = ccw * Math.sqrt(a * a + b * b) + var thetaRad = Math.atan2(ccw * b, ccw * a) + var theta = 180 / Math.PI * thetaRad + var ct = Math.cos(thetaRad) + var st = Math.sin(thetaRad) + + // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + var lam = (a * c + b * d) / determinant + var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + + // Use the translations + let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) + let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) + + // Construct the decomposition and return it return { - // translation - x: this.e, - y: this.f, - transformedX: (this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b), - transformedY: (this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d), - // skew - skewX: -skewX, - skewY: 180 / Math.PI * Math.atan2(py.y, py.x), - // scale - scaleX: Math.sqrt(this.a * this.a + this.b * this.b), - scaleY: Math.sqrt(this.c * this.c + this.d * this.d), - // rotation - rotation: skewX, + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + + // Return the matrix parameters a: this.a, b: this.b, c: this.c, d: this.d, e: this.e, - f: this.f, - matrix: new SVG.Matrix(this) + f: this.f } }, - // Clone matrix - clone: function () { - return new SVG.Matrix(this) - }, + // Morph one matrix into another morph: function (matrix) { - // store new destination + // Store new destination this.destination = new SVG.Matrix(matrix) - return this }, + // Get morphed matrix at a given position at: function (pos) { - // make sure a destination is defined + // Make sure a destination is defined if (!this.destination) return this - // calculate morphed matrix at a given position + // Calculate morphed matrix at a given position var matrix = new SVG.Matrix({ a: this.a + (this.destination.a - this.a) * pos, b: this.b + (this.destination.b - this.b) * pos, @@ -82,76 +174,221 @@ SVG.Matrix = SVG.invent({ return matrix }, - // Multiplies by given matrix + + // Left multiplies by the given matrix multiply: function (matrix) { - return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native())) + return this.clone().multiplyO(matrix) + }, + + multiplyO: function (matrix) { + // Get the matrices + var l = this + var r = matrix instanceof SVG.Matrix + ? matrix + : new SVG.Matrix(matrix) + + return matrixMultiply(l, r, this) }, + + lmultiply: function (matrix) { + return this.clone().lmultiplyO(matrix) + }, + + lmultiplyO: function (matrix) { + var r = this + var l = matrix instanceof SVG.Matrix + ? matrix + : new SVG.Matrix(matrix) + + return matrixMultiply(l, r, this) + }, + // Inverses matrix + inverseO: function () { + // Get the current parameters out of the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Invert the 2x2 matrix in the top left + var det = a * d - b * c + if (!det) throw new Error('Cannot invert ' + this) + + // Calculate the top 2x2 matrix + var na = d / det + var nb = -b / det + var nc = -c / det + var nd = a / det + + // Apply the inverted matrix to the top right + var ne = -(na * e + nc * f) + var nf = -(nb * e + nd * f) + + // Construct the inverted matrix + this.a = na + this.b = nb + this.c = nc + this.d = nd + this.e = ne + this.f = nf + + return this + }, + inverse: function () { - return new SVG.Matrix(this.native().inverse()) + return this.clone().inverseO() }, + // Translate matrix translate: function (x, y) { - return new SVG.Matrix(this.native().translate(x || 0, y || 0)) + return this.clone().translateO(x, y) + }, + + translateO: function (x, y) { + this.e += x || 0 + this.f += y || 0 + return this }, + // Scale matrix scale: function (x, y, cx, cy) { - // support uniformal scale - if (arguments.length === 1) { - y = x - } else if (arguments.length === 3) { + return this.clone().scaleO(...arguments) + }, + + scaleO: function (x, y = x, cx = 0, cy = 0) { + // Support uniform scaling + if (arguments.length === 3) { cy = cx cx = y y = x } - return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0)) + let {a, b, c, d, e, f} = this + + this.a = a * x + this.b = b * y + this.c = c * x + this.d = d * y + this.e = e * x - cx * x + cx + this.f = f * y - cy * y + cy + + return this }, + // Rotate matrix rotate: function (r, cx, cy) { - // convert degrees to radians + return this.clone().rotateO(r, cx, cy) + }, + + rotateO: function (r, cx = 0, cy = 0) { + // Convert degrees to radians r = SVG.utils.radians(r) - return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0)) + let cos = Math.cos(r) + let sin = Math.sin(r) + + let {a, b, c, d, e, f} = this + + this.a = a * cos - b * sin + this.b = b * cos + a * sin + this.c = c * cos - d * sin + this.d = d * cos + c * sin + this.e = e * cos - f * sin + cy * sin - cx * cos + cx + this.f = f * cos + e * sin - cx * sin - cy * cos + cy + + return this }, + // Flip matrix on x or y, at a given offset - flip: function (a, o) { - return a === 'x' ? this.scale(-1, 1, o, 0) - : a === 'y' ? this.scale(1, -1, 0, o) - : this.scale(-1, -1, a, o != null ? o : a) + flip: function (axis, around) { + return this.clone().flipO(axis, around) + }, + + flipO: function (axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) + : axis === 'y' ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point }, - // Skew + + // Shear matrix + shear: function (a, cx, cy) { + return this.clone().shearO(a, cx, cy) + }, + + shearO: function (lx, cx = 0, cy = 0) { + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.c = c + d * lx + this.e = e + f * lx - cy * lx + + return this + }, + + // Skew Matrix skew: function (x, y, cx, cy) { + return this.clone().skewO(...arguments) + }, + + skewO: function (x, y = x, cx = 0, cy = 0) { // support uniformal skew - if (arguments.length === 1) { - y = x - } else if (arguments.length === 3) { + if (arguments.length === 3) { cy = cx cx = y y = x } - // convert degrees to radians + // Convert degrees to radians x = SVG.utils.radians(x) y = SVG.utils.radians(y) - return this.around(cx, cy, new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0)) + let lx = Math.tan(x) + let ly = Math.tan(y) + + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.b = b + a * ly + this.c = c + d * lx + this.d = d + c * ly + this.e = e + f * lx - cy * lx + this.f = f + e * ly - cx * ly + + return this }, + // SkewX skewX: function (x, cx, cy) { return this.skew(x, 0, cx, cy) }, + + skewXO: function (x, cx, cy) { + return this.skewO(x, 0, cx, cy) + }, + // SkewY skewY: function (y, cx, cy) { return this.skew(0, y, cx, cy) }, + + skewYO: function (y, cx, cy) { + return this.skewO(0, y, cx, cy) + }, + // Transform around a center point + aroundO: function (cx, cy, matrix) { + var dx = cx || 0 + var dy = cy || 0 + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) + }, + around: function (cx, cy, matrix) { - return this - .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0)) - .multiply(matrix) - .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0)) + return this.clone().aroundO(cx, cy, matrix) }, + // Convert to native SVGMatrix native: function () { // create new matrix @@ -164,9 +401,33 @@ SVG.Matrix = SVG.invent({ return matrix }, + + // Check if two matrices are equal + equals: function (other) { + var comp = new SVG.Matrix(other) + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && + closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && + closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) + }, + // Convert matrix to string toString: function () { return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + }, + + toArray: function () { + return [this.a, this.b, this.c, this.d, this.e, this.f] + }, + + valueOf: function () { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } } }, @@ -195,3 +456,17 @@ SVG.Matrix = SVG.invent({ } } }) + +// let extensions = {} +// ['rotate'].forEach((method) => { +// let methodO = method + 'O' +// extensions[method] = function (...args) { +// return new SVG.Matrix(this)[methodO](...args) +// } +// }) +// +// SVG.extend(SVG.Matrix, extensions) + +// function matrixMultiplyParams (matrix, a, b, c, d, e, f) { +// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix) +// } diff --git a/src/morph.js b/src/morph.js new file mode 100644 index 0000000..acb9e21 --- /dev/null +++ b/src/morph.js @@ -0,0 +1,231 @@ + +SVG.Morphable = SVG.invent({ + create: function (stepper) { + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new SVG.Ease('-') + + this._from = null + this._to = null + this._type = null + this._context = null + this._morphObj = null + }, + + extend: { + + from: function (val) { + if (val == null) { + return this._from + } + + this._from = this._set(val) + return this + }, + + to: function (val) { + if (val == null) { + return this._to + } + + this._to = this._set(val) + return this + }, + + type: function (type) { + // getter + if (type == null) { + return this._type + } + + // setter + this._type = type + return this + }, + + _set: function (value) { + if (!this._type) { + var type = typeof value + + if (type === 'number') { + this.type(SVG.Number) + } else if (type === 'string') { + if (SVG.Color.isColor(value)) { + this.type(SVG.Color) + } else if (SVG.regex.delimiter.test(value)) { + this.type(SVG.regex.pathLetters.test(value) + ? SVG.PathArray + : SVG.Array + ) + } else if (SVG.regex.numberAndUnit.test(value)) { + this.type(SVG.Number) + } else { + this.type(SVG.Morphable.NonMorphable) + } + } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor) + } else if (Array.isArray(value)) { + this.type(SVG.Array) + } else if (type === 'object') { + this.type(SVG.Morphable.ObjectBag) + } else { + this.type(SVG.Morphable.NonMorphable) + } + } + + var result = (new this._type(value)).toArray() + this._morphObj = this._morphObj || new this._type() + this._context = this._context || + Array.apply(null, Array(result.length)).map(Object) + return result + }, + + stepper: function (stepper) { + if (stepper == null) return this._stepper + this._stepper = stepper + return this + }, + + done: function () { + var complete = this._context + .map(this._stepper.done) + .reduce(function (last, curr) { + return last && curr + }, true) + return complete + }, + + at: function (pos) { + var _this = this + + return this._morphObj.fromArray( + this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) + }) + ) + } + } +}) + +SVG.Morphable.NonMorphable = SVG.invent({ + create: function (val) { + val = Array.isArray(val) ? val[0] : val + this.value = val + }, + + extend: { + valueOf: function () { + return this.value + }, + + toArray: function () { + return [this.value] + } + } +}) + +SVG.Morphable.TransformBag = SVG.invent({ + create: function (obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + } + } + + Object.assign(this, SVG.Morphable.TransformBag.defaults, obj) + }, + + extend: { + toArray: function () { + var v = this + + return [ + v.scaleX, + v.scaleY, + v.shear, + v.rotate, + v.translateX, + v.translateY, + v.originX, + v.originY + ] + } + } +}) + +SVG.Morphable.TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 +} + +SVG.Morphable.ObjectBag = SVG.invent({ + create: function (objOrArr) { + this.values = [] + + if (Array.isArray(objOrArr)) { + this.values = objOrArr + return + } + + var entries = Object.entries(objOrArr || {}).sort((a, b) => { + return a[0] - b[0] + }) + + this.values = entries.reduce((last, curr) => last.concat(curr), []) + }, + + extend: { + valueOf: function () { + var obj = {} + var arr = this.values + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1] + } + + return obj + }, + + toArray: function () { + return this.values + } + } +}) + +SVG.MorphableTypes = [ + SVG.Number, + SVG.Color, + SVG.Box, + SVG.Matrix, + SVG.Array, + SVG.PointArray, + SVG.PathArray, + SVG.Morphable.NonMorphable, + SVG.Morphable.TransformBag, + SVG.Morphable.ObjectBag +] + +SVG.extend(SVG.MorphableTypes, { + to: function (val, args) { + return new SVG.Morphable() + .type(this.constructor) + .from(this.valueOf()) + .to(val, args) + }, + fromArray: function (arr) { + this.constructor(arr) + return this + } +}) diff --git a/src/number.js b/src/number.js index 6413f94..7fef7f2 100644 --- a/src/number.js +++ b/src/number.js @@ -3,6 +3,9 @@ SVG.Number = SVG.invent({ // Initialize create: function (value, unit) { + unit = Array.isArray(value) ? value[1] : unit + value = Array.isArray(value) ? value[0] : value + // initialize defaults this.value = 0 this.unit = unit || '' @@ -45,6 +48,9 @@ SVG.Number = SVG.invent({ toJSON: function () { return this.toString() }, // Convert to primitive + toArray: function () { + return [this.value, this.unit] + }, valueOf: function () { return this.value }, @@ -99,6 +105,5 @@ SVG.Number = SVG.invent({ .times(pos) .plus(this) } - } }) diff --git a/src/parent.js b/src/parent.js index d48e086..6bdad58 100644 --- a/src/parent.js +++ b/src/parent.js @@ -3,7 +3,7 @@ SVG.Parent = SVG.invent({ // Initialize node create: function (node) { - this.constructor(node) + SVG.Element.call(this, node) }, // Inherit from diff --git a/src/patharray.js b/src/patharray.js index d9ffecd..4432df3 100644 --- a/src/patharray.js +++ b/src/patharray.js @@ -87,6 +87,11 @@ SVG.extend(SVG.PathArray, { toString: function () { return arrayToString(this.value) }, + toArray: function () { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + }, // Move path string move: function (x, y) { // get bounding box of current situation diff --git a/src/point.js b/src/point.js index 682092e..6c64ed6 100644 --- a/src/point.js +++ b/src/point.js @@ -1,19 +1,18 @@ SVG.Point = SVG.invent({ // Initialize - create: function (x, y) { - var base = {x: 0, y: 0} + create: function (x, y, base) { var source + base = base || {x: 0, y: 0} // ensure source as object source = Array.isArray(x) ? {x: x[0], y: x[1]} : typeof x === 'object' ? {x: x.x, y: x.y} - : x != null ? {x: x, y: (y != null ? y : x)} - : base // If y has no value, then x is used has its value + : {x: x, y: y} // merge source - this.x = source.x - this.y = source.y + this.x = source.x == null ? base.x : source.x + this.y = source.y == null ? base.y : source.y }, // Add methods @@ -22,13 +21,14 @@ SVG.Point = SVG.invent({ clone: function () { return new SVG.Point(this) }, + // Morph one point into another morph: function (x, y) { // store new destination this.destination = new SVG.Point(x, y) - return this }, + // Get morphed point at a given position at: function (pos) { // make sure a destination is defined @@ -39,9 +39,9 @@ SVG.Point = SVG.invent({ x: this.x + (this.destination.x - this.x) * pos, y: this.y + (this.destination.y - this.y) * pos }) - return point }, + // Convert to native SVGPoint native: function () { // create new point @@ -50,12 +50,17 @@ SVG.Point = SVG.invent({ // update with current values point.x = this.x point.y = this.y - return point }, + // transform point with matrix - transform: function (matrix) { - return new SVG.Point(this.native().matrixTransform(matrix.native())) + transform: function (m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e + var y = m.b * this.x + m.d * this.y + m.f + + // Return the required point + return new SVG.Point(x, y) } } }) @@ -66,5 +71,4 @@ SVG.extend(SVG.Element, { point: function (x, y) { return new SVG.Point(x, y).transform(this.screenCTM().inverse()) } - }) diff --git a/src/pointarray.js b/src/pointarray.js index ecf5c40..aa5f84a 100644 --- a/src/pointarray.js +++ b/src/pointarray.js @@ -19,6 +19,12 @@ SVG.extend(SVG.PointArray, { return array.join(' ') }, + toArray: function () { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + }, + // Convert array to line object toLine: function () { return { diff --git a/src/queue.js b/src/queue.js new file mode 100644 index 0000000..621c887 --- /dev/null +++ b/src/queue.js @@ -0,0 +1,61 @@ +SVG.Queue = SVG.invent({ + create: function () { + this._first = null + this._last = null + }, + + extend: { + push: function (value) { + // An item stores an id and the provided value + var item = value.next ? value : { value: value, next: null, prev: null } + + // Deal with the queue being empty or populated + if (this._last) { + item.prev = this._last + this._last.next = item + this._last = item + } else { + this._last = item + this._first = item + } + + // Update the length and return the current item + return item + }, + + shift: function () { + // Check if we have a value + var remove = this._first + if (!remove) return null + + // If we do, remove it and relink things + this._first = remove.next + if (this._first) this._first.prev = null + this._last = this._first ? this._last : null + return remove.value + }, + + // Shows us the first item in the list + first: function () { + return this._first && this._first.value + }, + + // Shows us the last item in the list + last: function () { + return this._last && this._last.value + }, + + // Removes the item that was returned from the push + remove: function (item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next + + // Invalidate item + item.prev = null + item.next = null + } + } +}) diff --git a/src/runner.js b/src/runner.js new file mode 100644 index 0000000..41280a0 --- /dev/null +++ b/src/runner.js @@ -0,0 +1,959 @@ +/* global isMatrixLike getOrigin */ + +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } +} + +SVG.Runner = SVG.invent({ + parent: SVG.Element, + + create: function (options) { + // Store a unique id on the runner, so that we can identify it later + this.id = SVG.Runner.id++ + + // Ensure a default value + options = options == null + ? SVG.defaults.timeline.duration + : options + + // Ensure that we get a controller + options = typeof options === 'function' + ? new SVG.Controller(options) + : options + + // Declare all of the variables + this._element = null + this._timeline = null + this.done = false + this._queue = [] + + // Work out the stepper and the duration + this._duration = typeof options === 'number' && options + this._isDeclarative = options instanceof SVG.Controller + this._stepper = this._isDeclarative ? options : new SVG.Ease() + + // We copy the current values from the timeline because they can change + this._history = {} + + // Store the state of the runner + this.enabled = true + this._time = 0 + this._last = 0 + this.tags = {} + + // Save transforms applied to this runner + this.transforms = new SVG.Matrix() + this.transformId = 1 + + // Looping variables + this._haveReversed = false + this._reverse = false + this._loopsDone = 0 + this._swing = false + this._wait = 0 + this._times = 1 + }, + + construct: { + + animate: function (duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when) + var timeline = this.timeline() + return new SVG.Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) + }, + + delay: function (by, when) { + return this.animate(0, by, when) + } + }, + + extend: { + + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ + + element: function (element) { + if (element == null) return this._element + this._element = element + element._prepareRunner() + return this + }, + + timeline: function (timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof timeline === 'undefined') return this._timeline + this._timeline = timeline + return this + }, + + animate: function (duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when) + var runner = new SVG.Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) + }, + + schedule: function (timeline, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline instanceof SVG.Timeline)) { + when = delay + delay = timeline + timeline = this.timeline() + } + + // If there is no timeline, yell at the user... + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') + } + + // Schedule the runner on the timeline provided + timeline.schedule(this, delay, when) + return this + }, + + unschedule: function () { + var timeline = this.timeline() + timeline && timeline.unschedule(this) + return this + }, + + loop: function (times, swing, wait) { + // Deal with the user passing in an object + if (typeof times === 'object') { + swing = times.swing + wait = times.wait + times = times.times + } + + // Sanitise the values and store them + this._times = times || Infinity + this._swing = swing || false + this._wait = wait || 0 + return this + }, + + delay: function (delay) { + return this.animate(0, delay) + }, + + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + + queue: function (initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || SVG.void, + runner: runFn || SVG.void, + isTransform: isTransform, + initialised: false, + finished: false + }) + var timeline = this.timeline() + timeline && this.timeline()._continue() + return this + }, + + during: function (fn) { + return this.queue(null, fn) + }, + + after (fn) { + return this.on('finish', fn) + }, + + /* + Runner animation methods + ======================== + Control how the animation plays + */ + + time: function (time) { + if (time == null) { + return this._time + } + let dt = time - this._time + this.step(dt) + return this + }, + + duration: function () { + return this._times * (this._wait + this._duration) - this._wait + }, + + loops: function (p) { + var loopDuration = this._duration + this._wait + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) + var position = relativeTime / this._duration + return Math.min(loopsDone + position, this._times) + } + var whole = Math.floor(p) + var partial = p % 1 + var time = loopDuration * whole + this._duration * partial + return this.time(time) + }, + + position: function (p) { + // Get all of the variables we need + var x = this._time + var d = this._duration + var w = this._wait + var t = this._times + var s = this._swing + var r = this._reverse + var position + + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + + // Figure out the value without thinking about the start or end time + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) + return clipped + } + + // Figure out the value by incorporating the start time + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) + return position + } + + // Work out the loops done and add the position to the loops done + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) + }, + + progress: function (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) + } + return this.time(p * this.duration()) + }, + + step: function (dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this + + // Update the time and get the new position + dt = dt == null ? 16 : dt + this._time += dt + var position = this.position() + + // Figure out if we need to run the stepper in this frame + var running = this._lastPosition !== position && this._time >= 0 + this._lastPosition = position + + // Figure out if we just started + var duration = this.duration() + var justStarted = this._lastTime < 0 && this._time > 0 + var justFinished = this._lastTime < this._time && this.time > duration + this._lastTime = this._time + if (justStarted) { + // this.fire('start', this) + } + + // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + var declarative = this._isDeclarative + this.done = !declarative && !justFinished && this._time >= duration + + // Call initialise and the run function + if (running || declarative) { + this._initialise(running) + + // clear the transforms on this runner so they dont get added again and again + this.transforms = new SVG.Matrix() + var converged = this._run(declarative ? dt : position) + // this.fire('step', this) + } + // correct the done flag here + // declaritive animations itself know when they converged + this.done = this.done || (converged && declarative) + // if (this.done) { + // this.fire('finish', this) + // } + return this + }, + + finish: function () { + return this.step(Infinity) + }, + + reverse: function (reverse) { + this._reverse = reverse == null ? !this._reverse : reverse + return this + }, + + ease: function (fn) { + this._stepper = new SVG.Ease(fn) + return this + }, + + active: function (enabled) { + if (enabled == null) return this.enabled + this.enabled = enabled + return this + }, + + /* + Runner Management + ================= + Functions that are used to help index the runner + */ + + tag: function (name) { + // Act as a getter to get all of the tags on this object + if (name == null) return Object.keys(this.tags) + + // Add all of the tags to the object directly + name = Array.isArray(name) ? name : [name] + for (var i = name.length; i--;) { + this.tags[name[i]] = true + } + return this + }, + + untag: function (name) { + name = Array.isArray(name) ? name : [name] + for (var i = name.length; i--;) { + delete this.tags[name[i]] + } + return this + }, + + getEventTarget: function () { + return this._dispatcher + }, + + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + + // Save a morpher to the morpher list so that we can retarget it later + _rememberMorpher: function (method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + } + }, + + // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + _tryRetarget: function (method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) + return false + } + + // for the case of transformations, we use the special retarget function + // which has access to the outer scope + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target) + // for everything else a simple morpher change is sufficient + } else { + this._history[method].morpher.to(target) + } + + this._history[method].caller.finished = false + var timeline = this.timeline() + timeline && timeline._continue() + return true + } + return false + }, + + // Run each initialise function in the runner if required + _initialise: function (running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return + + // Loop through all of the initialisers + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i] + + // Determine whether we need to initialise + var needsIt = this._isDeclarative || (!current.initialised && running) + running = !current.finished + + // Call the initialiser if we need to + if (needsIt && running) { + current.initialiser.call(this) + current.initialised = true + } + } + }, + + // Run each run function for the position or dt given + _run: function (positionOrDt) { + // Run all of the _queue directly + var allfinished = true + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i] + + // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) + allfinished = allfinished && current.finished + } + + // We report when all of the constructors are finished + return allfinished + }, + + addTransform: function (transform, index) { + this.transforms.lmultiplyO(transform) + return this + }, + + clearTransform: function () { + this.transforms = new SVG.Matrix() + return this + } + } +}) + +SVG.Runner.id = 0 + +SVG.Runner.sanitise = function (duration, delay, when) { + // Initialise the default parameters + var times = 1 + var swing = false + var wait = 0 + duration = duration || SVG.defaults.timeline.duration + delay = delay || SVG.defaults.timeline.delay + when = when || 'last' + + // If we have an object, unpack the values + if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) { + delay = duration.delay || delay + when = duration.when || when + swing = duration.swing || swing + times = duration.times || times + wait = duration.wait || wait + duration = duration.duration || SVG.defaults.timeline.duration + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + } +} + +SVG.FakeRunner = class { + constructor (transforms = new SVG.Matrix(), id = -1, done = true) { + this.transforms = transforms + this.id = id + this.done = done + } +} + +SVG.extend([SVG.Runner, SVG.FakeRunner], { + mergeWith (runner) { + return new SVG.FakeRunner( + runner.transforms.lmultiply(this.transforms), + runner.id + ) + } +}) + +// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner() + +const lmultiply = (last, curr) => last.lmultiplyO(curr) +const getRunnerTransform = (runner) => runner.transforms + +function mergeTransforms () { + // Find the matrix to apply to the element and apply it + let runners = this._transformationRunners.runners + let netTransform = runners + .map(getRunnerTransform) + .reduce(lmultiply, new SVG.Matrix()) + + this.transform(netTransform) + + this._transformationRunners.merge() + + if (this._transformationRunners.length() === 1) { + this._frameId = null + } +} + +class RunnerArray { + constructor () { + this.runners = [] + this.ids = [] + } + + add (runner) { + if (this.runners.includes(runner)) return + + let id = runner.id + 1 + + let leftSibling = this.ids.reduce((last, curr) => { + if (curr > last && curr < id) return curr + return last + }, 0) + + let index = this.ids.indexOf(leftSibling) + 1 + + this.ids.splice(index, 0, id) + this.runners.splice(index, 0, runner) + + return this + } + + getByID (id) { + return this.runners[this.ids.indexOf(id + 1)] + } + + remove (id) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1) + this.runners.splice(index, 1) + return this + } + + merge () { + let lastRunner = null + this.runners.forEach((runner, i) => { + if (lastRunner && runner.done && lastRunner.done) { + this.remove(runner.id) + this.edit(lastRunner.id, runner.mergeWith(lastRunner)) + } + + lastRunner = runner + }) + + return this + } + + edit (id, newRunner) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1, id) + this.runners.splice(index, 1, newRunner) + return this + } + + length () { + return this.ids.length + } + + clearBefore (id) { + let deleteCnt = this.ids.indexOf(id + 1) || 1 + this.ids.splice(0, deleteCnt, 0) + this.runners.splice(0, deleteCnt, new SVG.FakeRunner()) + return this + } +} + +SVG.extend(SVG.Element, { + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function (currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id) + }, + + _currentTransform (current) { + return this._transformationRunners.runners + // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter((runner) => runner.id <= current.id) + .map(getRunnerTransform) + .reduce(lmultiply, new SVG.Matrix()) + }, + + addRunner: function (runner) { + this._transformationRunners.add(runner) + + SVG.Animator.transform_frame( + mergeTransforms.bind(this), this._frameId + ) + }, + + _prepareRunner: function () { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray() + .add(new SVG.FakeRunner(new SVG.Matrix(this))) + + this._frameId = SVG.Element.frameId++ + } + } +}) + +SVG.Element.frameId = 0 + +SVG.extend(SVG.Runner, { + attr: function (a, v) { + return this.styleAttr('attr', a, v) + }, + + // Add animatable styles + css: function (s, v) { + return this.styleAttr('css', s, v) + }, + + styleAttr (type, name, val) { + // apply attributes individually + if (typeof name === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]) + } + } + + var morpher = new SVG.Morphable(this._stepper).to(val) + + this.queue(function () { + morpher = morpher.from(this.element()[type](name)) + }, function (pos) { + this.element()[type](name, morpher.at(pos)) + return morpher.done() + }) + + return this + }, + + zoom: function (level, point) { + var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level)) + + this.queue(function () { + morpher = morpher.from(this.zoom()) + }, function (pos) { + this.element().zoom(morpher.at(pos), point) + return morpher.done() + }) + + return this + }, + + /** + ** absolute transformations + **/ + + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + + transform: function (transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this + } + + // Parse the parameters + var isMatrix = isMatrixLike(transforms) + affine = transforms.affine != null + ? transforms.affine + : (affine != null ? affine : !isMatrix) + + // Create a morepher and set its type + const morpher = new SVG.Morphable() + .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix) + .stepper(this._stepper) + + let origin + let element + let current + let currentAngle + let startTransform + + function setup () { + // make sure element and origin is defined + element = element || this.element() + origin = origin || getOrigin(transforms, element) + + startTransform = new SVG.Matrix(relative ? undefined : element) + + // add the runner to the element so it can merge transformations + element.addRunner(this) + + // Deactivate all transforms that have run so far if we are absolute + if (!relative) { + element._clearTransformRunnersBefore(this) + } + } + + function run (pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform() + + let {x, y} = new SVG.Point(origin).transform(element._currentTransform(this)) + + let target = new SVG.Matrix({...transforms, origin: [x, y]}) + let start = this._isDeclarative && current + ? current + : startTransform + + if (affine) { + target = target.decompose(x, y) + start = start.decompose(x, y) + + // Get the current and target angle as it was set + const rTarget = target.rotate + const rCurrent = start.rotate + + // Figure out the shortest path to rotate directly + const possibilities = [rTarget - 360, rTarget, rTarget + 360] + const distances = possibilities.map(a => Math.abs(a - rCurrent)) + const shortest = Math.min(...distances) + const index = distances.indexOf(shortest) + target.rotate = possibilities[index] + } + + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of SVG.Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0 + } + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle + } + } + + morpher.from(start) + morpher.to(target) + + let affineParameters = morpher.at(pos) + currentAngle = affineParameters.rotate + current = new SVG.Matrix(affineParameters) + + this.addTransform(current) + return morpher.done() + } + + function retarget (newTransforms) { + // only get a new origin if it changed since the last call + if ( + (newTransforms.origin || 'center').toString() !== + (transforms.origin || 'center').toString() + ) { + origin = getOrigin(transforms, element) + } + + // overwrite the old transformations with the new ones + transforms = {...newTransforms, origin} + } + + this.queue(setup, run, retarget) + this._isDeclarative && this._rememberMorpher('transform', morpher) + return this + }, + + // Animatable x-axis + x: function (x, relative) { + return this._queueNumber('x', x) + }, + + // Animatable y-axis + y: function (y) { + return this._queueNumber('y', y) + }, + + dx: function (x) { + return this._queueNumberDelta('dx', x) + }, + + dy: function (y) { + return this._queueNumberDelta('dy', y) + }, + + _queueNumberDelta: function (method, to) { + to = new SVG.Number(to) + + // Try to change the target if we have this method already registerd + if (this._tryRetargetDelta(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new SVG.Morphable(this._stepper).to(to) + this.queue(function () { + var from = this.element()[method]() + morpher.from(from) + morpher.to(from + to) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueObject: function (method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new SVG.Morphable(this._stepper).to(to) + this.queue(function () { + morpher.from(this.element()[method]()) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueNumber: function (method, value) { + return this._queueObject(method, new SVG.Number(value)) + }, + + // Animatable center x-axis + cx: function (x) { + return this._queueNumber('cx', x) + }, + + // Animatable center y-axis + cy: function (y) { + return this._queueNumber('cy', y) + }, + + // Add animatable move + move: function (x, y) { + return this.x(x).y(y) + }, + + // Add animatable center + center: function (x, y) { + return this.cx(x).cy(y) + }, + + // Add animatable size + size: function (width, height) { + // animate bbox based size for all other elements + var box + + if (!width || !height) { + box = this._element.bbox() + } + + if (!width) { + width = box.width / box.height * height + } + + if (!height) { + height = box.height / box.width * width + } + + return this + .width(width) + .height(height) + }, + + // Add animatable width + width: function (width) { + return this._queueNumber('width', width) + }, + + // Add animatable height + height: function (height) { + return this._queueNumber('height', height) + }, + + // Add animatable plot + plot: function (a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]) + } + + // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function + return this._queueObject('plot', new this._element.MorphArray(a)) + + /* + var morpher = this._element.morphArray().to(a) + + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + + return this + */ + }, + + // Add leading method + leading: function (value) { + return this._queueNumber('leading', value) + }, + + // Add animatable viewbox + viewbox: function (x, y, width, height) { + return this._queueObject('viewbox', new SVG.Box(x, y, width, height)) + }, + + update: function (o) { + if (typeof o !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }) + } + + if (o.opacity != null) this.attr('stop-opacity', o.opacity) + if (o.color != null) this.attr('stop-color', o.color) + if (o.offset != null) this.attr('offset', o.offset) + + return this + } +}) diff --git a/src/shape.js b/src/shape.js index 87b01f9..cb15098 100644 --- a/src/shape.js +++ b/src/shape.js @@ -2,7 +2,7 @@ SVG.Shape = SVG.invent({ // Initialize node create: function (node) { - this.constructor(node) + SVG.Element.call(this, node) }, // Inherit from diff --git a/src/sugar.js b/src/sugar.js index c3a3332..ad991af 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -30,58 +30,89 @@ var sugar = { return this } - SVG.extend([SVG.Element, SVG.FX], extension) + SVG.extend([SVG.Element, SVG.Timeline], extension) }) -SVG.extend([SVG.Element, SVG.FX], { +SVG.extend([SVG.Element, SVG.Timeline], { + // Let the user set the matrix directly + matrix: function (mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new SVG.Matrix(this) + } + + // Act as a setter, the user can pass a matrix or a set of numbers + return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f)) + }, + // Map rotation to transform - rotate: function (d, cx, cy) { - return this.transform({ rotation: d, cx: cx, cy: cy }) + rotate: function (angle, cx, cy) { + return this.transform({rotate: angle, ox: cx, oy: cy}, true) }, + // Map skew to transform skew: function (x, y, cx, cy) { return arguments.length === 1 || arguments.length === 3 - ? this.transform({ skew: x, cx: y, cy: cx }) - : this.transform({ skewX: x, skewY: y, cx: cx, cy: cy }) + ? this.transform({skew: x, ox: y, oy: cx}, true) + : this.transform({skew: [x, y], ox: cx, oy: cy}, true) }, + + shear: function (lam, cx, cy) { + return this.transform({shear: lam, ox: cx, oy: cy}, true) + }, + // Map scale to transform scale: function (x, y, cx, cy) { return arguments.length === 1 || arguments.length === 3 - ? this.transform({ scale: x, cx: y, cy: cx }) - : this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy }) + ? this.transform({ scale: x, ox: y, oy: cx }, true) + : this.transform({ scale: [x, y], ox: cx, oy: cy }, true) }, + // Map translate to transform translate: function (x, y) { - return this.transform({ x: x, y: y }) + return this.transform({ translate: [x, y] }, true) }, - // Map flip to transform - flip: function (a, o) { - o = typeof a === 'number' ? a : o - return this.transform({ flip: a || 'both', offset: o }) + + // Map relative translations to transform + relative: function (x, y) { + return this.transform({ relative: [x, y] }, true) }, - // Map matrix to transform - matrix: function (m) { - return this.attr('transform', new SVG.Matrix(arguments.length === 6 ? [].slice.call(arguments) : m)) + + // Map flip to transform + flip: function (direction, around) { + var directionString = typeof direction === 'string' ? direction + : isFinite(direction) ? 'both' + : 'both' + var origin = (direction === 'both' && isFinite(around)) ? [around, around] + : (direction === 'x') ? [around, 0] + : (direction === 'y') ? [0, around] + : isFinite(direction) ? [direction, direction] + : [0, 0] + this.transform({flip: directionString, origin: origin}, true) }, + // Opacity opacity: function (value) { return this.attr('opacity', value) }, + // Relative move over x axis dx: function (x) { - return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true) + return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true) }, + // Relative move over y axis dy: function (y) { - return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true) + return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true) }, + // Relative move over x and y axes dmove: function (x, y) { return this.dx(x).dy(y) } }) -SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX], { +SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], { // Add x and y radius radius: function (x, y) { var type = (this._target || this).type @@ -102,7 +133,7 @@ SVG.extend(SVG.Path, { } }) -SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX], { +SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], { // Set font font: function (a, v) { if (typeof a === 'object') { @@ -2,7 +2,7 @@ /* eslint-disable new-cap */ // The main wrapping element -var SVG = this.SVG = function (element) { +var SVG = window.SVG = function (element) { if (SVG.supported) { element = createElement(element) return element @@ -52,12 +52,13 @@ SVG.invent = function (config) { // Create element initializer var initializer = typeof config.create === 'function' ? config.create : function (node) { - this.constructor(node || SVG.create(config.create)) + config.inherit.call(this, node || SVG.create(config.create)) } // Inherit prototype if (config.inherit) { initializer.prototype = new config.inherit() + initializer.prototype.constructor = initializer } // Extend with methods diff --git a/src/text.js b/src/text.js index b210c7b..8a50df9 100644 --- a/src/text.js +++ b/src/text.js @@ -1,7 +1,7 @@ SVG.Text = SVG.invent({ // Initialize node create: function (node) { - this.constructor(node || SVG.create('text')) + SVG.Element.call(this, node || SVG.create('text')) this.dom.leading = new SVG.Number(1.3) // store leading value for rebuilding this._rebuild = true // enable automatic updating of dy values this._build = false // disable build mode for adding multiple lines diff --git a/src/timeline.js b/src/timeline.js new file mode 100644 index 0000000..0bf8ac5 --- /dev/null +++ b/src/timeline.js @@ -0,0 +1,282 @@ + +// Must Change .... +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } +} + +var time = window.performance || Date + +var makeSchedule = function (runnerInfo) { + var start = runnerInfo.start + var duration = runnerInfo.runner.duration() + var end = start + duration + return {start: start, duration: duration, end: end, runner: runnerInfo.runner} +} + +SVG.Timeline = SVG.invent({ + inherit: SVG.EventTarget, + + // Construct a new timeline on the given element + create: function () { + this._timeSource = function () { + return time.now() + } + + this._dispatcher = document.createElement('div') + + // Store the timing variables + this._startTime = 0 + this._speed = 1.0 + + // Play control variables control how the animation proceeds + this._reverse = false + this._persist = 0 + + // Keep track of the running animations and their starting parameters + this._nextFrame = null + this._paused = false + this._runners = [] + this._order = [] + this._time = 0 + this._lastSourceTime = 0 + this._lastStepTime = 0 + }, + + extend: { + + getEventTarget () { + return this._dispatcher + }, + + /** + * + */ + + // schedules a runner on the timeline + schedule (runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) + } + + if (!this.active()) { + this._step() + if (when == null) { + when = 'now' + } + } + + // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + var absoluteStartTime = 0 + delay = delay || 0 + + // Work out when to start the animation + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay + delay = 0 + } else if (when === 'now') { + absoluteStartTime = this._time + } else if (when === 'relative') { + let runnerInfo = this._runners[runner.id] + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay + delay = 0 + } + } else { + throw new Error('Invalid value for the "when" parameter') + } + + // Manage runner + runner.unschedule() + runner.timeline(this) + runner.time(-delay) + + // Save startTime for next runner + this._startTime = absoluteStartTime + runner.duration() + delay + + // Save runnerInfo + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime + } + + // Save order and continue + this._order.push(runner.id) + this._continue() + return this + }, + + // Remove the runner from this timeline + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this + + delete this._runners[runner.id] + this._order.splice(index, 1) + runner.timeline(null) + return this + }, + + play () { + // Now make sure we are not paused and continue the animation + this._paused = false + return this._continue() + }, + + pause () { + // Cancel the next animation frame and pause + this._nextFrame = null + this._paused = true + return this + }, + + stop () { + // Cancel the next animation frame and go to start + this.seek(-this._time) + return this.pause() + }, + + finish () { + this.seek(Infinity) + return this.pause() + }, + + speed (speed) { + if (speed == null) return this._speed + this._speed = speed + return this + }, + + reverse (yes) { + var currentSpeed = this.speed() + if (yes == null) return this.speed(-currentSpeed) + + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) + }, + + seek (dt) { + this._time += dt + return this._continue() + }, + + time (time) { + if (time == null) return this._time + this._time = time + return this + }, + + persist (dtOrForever) { + if (dtOrForever == null) return this._persist + this._persist = dtOrForever + return this + }, + + source (fn) { + if (fn == null) return this._timeSource + this._timeSource = fn + return this + }, + + _step () { + // If the timeline is paused, just do nothing + if (this._paused) return + + // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + var time = this._timeSource() + var dtSource = time - this._lastSourceTime + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) + this._lastSourceTime = time + + // Update the time + this._time += dtTime + this._lastStepTime = this._time + // this.fire('time', this._time) + + // Run all of the runners directly + var runnersLeft = false + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]] + var runner = runnerInfo.runner + let dt = dtTime + + // Make sure that we give the actual difference + // between runner start time and now + let dtToStart = this._time - runnerInfo.start + + // Dont run runner if not started yet + if (dtToStart < 0) { + runnersLeft = true + continue + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart + } + + if (!runner.active()) continue + + // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + var finished = runner.step(dt).done + if (!finished) { + runnersLeft = true + // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]] + this._order.splice(i--, 1) && --len + runner.timeline(null) + } + } + } + + // Get the next animation frame to keep the simulation going + if (runnersLeft) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)) + } else { + this._nextFrame = null + } + return this + }, + + // Checks if we are running and continues the animation + _continue () { + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)) + } + return this + }, + + active () { + return !!this._nextFrame + } + }, + + // These methods will be added to all SVG.Element objects + parent: SVG.Element, + construct: { + timeline: function () { + this._timeline = (this._timeline || new SVG.Timeline()) + return this._timeline + } + } +}) diff --git a/src/transform.js b/src/transform.js index 54e9900..96c0aec 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,195 +1,11 @@ -/* global ensureCentre, capitalize, arrayToMatrix */ - -SVG.extend(SVG.Element, { - // Add transformations - transform: function (o, relative) { - // get target in case of the fx module, otherwise reference this - var target = this - var matrix, bbox - - // act as a getter - if (typeof o !== 'object') { - // get current matrix - matrix = new SVG.Matrix(target).extract() - - return typeof o === 'string' ? matrix[o] : matrix - } - - // get current matrix - matrix = new SVG.Matrix(target) - - // ensure relative flag - relative = !!relative || !!o.relative - - // act on matrix - if (o.a != null) { - matrix = relative - ? matrix.multiply(new SVG.Matrix(o)) - : new SVG.Matrix(o) - - // act on rotation - } else if (o.rotation != null) { - // ensure centre point - ensureCentre(o, target) - - // apply transformation - matrix = relative - ? matrix.rotate(o.rotation, o.cx, o.cy) - : matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy) - - // act on scale - } else if (o.scale != null || o.scaleX != null || o.scaleY != null) { - // ensure centre point - ensureCentre(o, target) - - // ensure scale values on both axes - o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1 - o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1 - - if (!relative) { - // absolute; multiply inversed values - var e = matrix.extract() - o.scaleX = o.scaleX * 1 / e.scaleX - o.scaleY = o.scaleY * 1 / e.scaleY - } - - matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy) - - // act on skew - } else if (o.skew != null || o.skewX != null || o.skewY != null) { - // ensure centre point - ensureCentre(o, target) - - // ensure skew values on both axes - o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0 - o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0 - - if (!relative) { - // absolute; reset skew values - var el = matrix.extract() - matrix = matrix.multiply(new SVG.Matrix().skew(el.skewX, el.skewY, el.cx, el.cy).inverse()) - } - - matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy) - - // act on flip - } else if (o.flip) { - if (o.flip === 'x' || o.flip === 'y') { - o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset - } else { - if (o.offset == null) { - bbox = target.bbox() - o.flip = bbox.cx - o.offset = bbox.cy - } else { - o.flip = o.offset - } - } - - matrix = new SVG.Matrix().flip(o.flip, o.offset) - - // act on translate - } else if (o.x != null || o.y != null) { - if (relative) { - // relative - matrix = matrix.translate(o.x, o.y) - } else { - // absolute - if (o.x != null) matrix.e = o.x - if (o.y != null) matrix.f = o.y - } - } - - return this.attr('transform', matrix) - } -}) - -SVG.extend(SVG.FX, { - transform: function (o, relative) { - // get target in case of the fx module, otherwise reference this - var target = this.target() - var matrix, bbox - - // act as a getter - if (typeof o !== 'object') { - // get current matrix - matrix = new SVG.Matrix(target).extract() - return typeof o === 'string' ? matrix[o] : matrix - } - - // ensure relative flag - relative = !!relative || !!o.relative - - // act on matrix - if (o.a != null) { - matrix = new SVG.Matrix(o) - - // act on rotation - } else if (o.rotation != null) { - // ensure centre point - ensureCentre(o, target) - - // apply transformation - matrix = new SVG.Rotate(o.rotation, o.cx, o.cy) - - // act on scale - } else if (o.scale != null || o.scaleX != null || o.scaleY != null) { - // ensure centre point - ensureCentre(o, target) - - // ensure scale values on both axes - o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1 - o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1 - - matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy) - - // act on skew - } else if (o.skewX != null || o.skewY != null) { - // ensure centre point - ensureCentre(o, target) - - // ensure skew values on both axes - o.skewX = o.skewX != null ? o.skewX : 0 - o.skewY = o.skewY != null ? o.skewY : 0 - - matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy) - - // act on flip - } else if (o.flip) { - if (o.flip === 'x' || o.flip === 'y') { - o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset - } else { - if (o.offset == null) { - bbox = target.bbox() - o.flip = bbox.cx - o.offset = bbox.cy - } else { - o.flip = o.offset - } - } - - matrix = new SVG.Matrix().flip(o.flip, o.offset) - - // act on translate - } else if (o.x != null || o.y != null) { - matrix = new SVG.Translate(o.x, o.y) - } - - if (!matrix) return this - - matrix.relative = relative - - this.last().transforms.push(matrix) - - return this._callStart() - } -}) +/* global arrayToMatrix getOrigin isMatrixLike */ SVG.extend(SVG.Element, { // Reset all transformations untransform: function () { return this.attr('transform', null) }, + // merge the whole transformation chain into one matrix and returns it matrixify: function () { var matrix = (this.attr('transform') || '') @@ -197,16 +13,23 @@ SVG.extend(SVG.Element, { .split(SVG.regex.transforms).slice(0, -1).map(function (str) { // generate key => value pairs var kv = str.trim().split('(') - return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })] + return [kv[0], + kv[1].split(SVG.regex.delimiter) + .map(function (str) { return parseFloat(str) }) + ] }) + .reverse() // merge every transformation into one matrix .reduce(function (matrix, transform) { - if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1])) + if (transform[0] === 'matrix') { + return matrix.lmultiply(arrayToMatrix(transform[1])) + } return matrix[transform[0]].apply(matrix, transform[1]) }, new SVG.Matrix()) return matrix }, + // add an element to another parent without changing the visual representation on the screen toParent: function (parent) { if (this === parent) return this @@ -217,143 +40,31 @@ SVG.extend(SVG.Element, { return this }, + // same as above with parent equals root-svg toDoc: function () { return this.toParent(this.doc()) } - }) -SVG.Transformation = SVG.invent({ - - create: function (source, inversed) { - if (arguments.length > 1 && typeof inversed !== 'boolean') { - return this.constructor.bind(this)([].slice.call(arguments)) - } - - var i, len - if (Array.isArray(source)) { - for (i = 0, len = this.arguments.length; i < len; ++i) { - this[this.arguments[i]] = source[i] - } - } else if (typeof source === 'object') { - for (i = 0, len = this.arguments.length; i < len; ++i) { - this[this.arguments[i]] = source[this.arguments[i]] - } - } - - this.inversed = false - - if (inversed === true) { - this.inversed = true - } - }, - - extend: { - - arguments: [], - method: '', - - at: function (pos) { - var params = [] - - for (var i = 0, len = this.arguments.length; i < len; ++i) { - params.push(this[this.arguments[i]]) - } - - var m = this._undo || new SVG.Matrix() - - m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos) - - return this.inversed ? m.inverse() : m - }, - - undo: function (o) { - for (var i = 0, len = this.arguments.length; i < len; ++i) { - o[this.arguments[i]] = typeof this[this.arguments[i]] === 'undefined' ? 0 : o[this.arguments[i]] - } - - // The method SVG.Matrix.extract which was used before calling this - // method to obtain a value for the parameter o doesn't return a cx and - // a cy so we use the ones that were provided to this object at its creation - o.cx = this.cx - o.cy = this.cy +SVG.extend(SVG.Element, { - this._undo = new SVG[capitalize(this.method)](o, true).at(1) - return this + // Add transformations + transform: function (o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new SVG.Matrix(this).decompose() + return decomposed[o] || decomposed } - } - -}) - -SVG.Translate = SVG.invent({ - - parent: SVG.Matrix, - inherit: SVG.Transformation, - - create: function (source, inversed) { - this.constructor.apply(this, [].slice.call(arguments)) - }, - - extend: { - arguments: ['transformedX', 'transformedY'], - method: 'translate' - } - -}) - -SVG.Rotate = SVG.invent({ - - parent: SVG.Matrix, - inherit: SVG.Transformation, - - create: function (source, inversed) { - this.constructor.apply(this, [].slice.call(arguments)) - }, - - extend: { - arguments: ['rotation', 'cx', 'cy'], - method: 'rotate', - at: function (pos) { - var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy) - return this.inversed ? m.inverse() : m - }, - undo: function (o) { - this._undo = o - return this + if (!isMatrixLike(o)) { + // Set the origin according to the defined transform + o = {...o, origin: getOrigin(o, this)} } - } - -}) - -SVG.Scale = SVG.invent({ - - parent: SVG.Matrix, - inherit: SVG.Transformation, - - create: function (source, inversed) { - this.constructor.apply(this, [].slice.call(arguments)) - }, - - extend: { - arguments: ['scaleX', 'scaleY', 'cx', 'cy'], - method: 'scale' - } - -}) - -SVG.Skew = SVG.invent({ - - parent: SVG.Matrix, - inherit: SVG.Transformation, - - create: function (source, inversed) { - this.constructor.apply(this, [].slice.call(arguments)) - }, - extend: { - arguments: ['skewX', 'skewY', 'cx', 'cy'], - method: 'skew' + // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing + var cleanRelative = relative === true ? this : (relative || false) + var result = new SVG.Matrix(cleanRelative).transform(o) + return this.attr('transform', result) } }) diff --git a/src/utilities.js b/src/utilities.js index 5ebe808..01b8ba5 100644 --- a/src/utilities.js +++ b/src/utilities.js @@ -1,3 +1,4 @@ + SVG.utils = { // Map function map: function (array, block) { @@ -0,0 +1,94 @@ + + +# Where We Left Off + +Saivan +====== + + +Ulima +===== +- Use runners[runnerid] = {startTime, runner, persist} +timeline.persist('monkey-in', Infinity) +- folding transformations +- testing direct non affine morph +- why cant i use current? +- handle null values + +Both +==== +- We discussed that matrices should always be applied from the left for animation, so we have: + - If we have C R x where C is the current Matrix and R is the relative matrix that we want to apply + - It could be animated by instead left multiplying (C R inv(C)) so that we have (C R inv(C)) C R + - This allows us to always left multiply (which greatly simplifies things) + => Conclusion: We dont do this. We apply transformations left or right whatever is necessary + +Latest +====== +- Runners would call an element.mergeMatrix() function that requests a native animation frame. Each runner would cancel the call made by the last runner, so that the function only runs once per frame. +-https://en.wikipedia.org/wiki/Change_of_basis#Change_of_coordinates_of_a_vector + + + +# Timeline Description + +- [T] Timeline constructors + - [T] timeline () - Returns the timeline context to the user + +- [T] Time Management + - [T] play () - Lets the timeline keep playing from here + - [T] pause () - Pauses the timeline where it currently is + - [T] stop () - Pauses the timeline and sets time = 0 + - [T] finish () - Moves the time to the final time for the final animation, forces declaratives to snap to their final positions + - [T] speed (newSpeed) - Sets the playback speed + - [T] seek (dt) - Scrubs the timeline time forward or backward by dt + - [T] time (t) - Sets the absolute time to t + - [T] backwards (back) - Sets the speed to (back ? speed : -speed) + - [T] position (p) - sets the position in range [0, 1] + - [T] loop (times, swing, waits) + +- [T] Runner Management + - [T] remove(tagOrRunner, end) - Removes all runners with tag from the timeline + - [T] reset () - Deletes all of the runners and resets the timeline + - [T] persist (tag, lifetime) - how long to keep a reference to an animation after it is completed + - [T] schedule (tag, time, when) - move the start time of the runner to time otherwise, returns all of the scheduled runners start and end times. + +- [T] Hidden Methods + - [x] `_step (dt)` + - [x] `_continue ()` + + +# Runner + +- [x] Constructors + - [x] animate (duration, delay, when) - Makes a new runner and returns the timeline context to the user with the new runner active. + - [x] loop (duration, times, swing) - Makes a new runner with the looping set as described by the parameters, returns timeline + - [x] delay (by, when) - Makes a new runner to start <by> ms after the last active runner is complete + +- [x] Runner Methods + - [x] element (svgElement) - Given an element, you can bind it directly + - [x] animate (args) - Calls animate if we have an element set + - [x] loop (args) - Calls loop with arguments if we have an element + - [x] delay (args) - calls delay if we have an element + +- [x] Runner Events + - [x] on (eventName, fn) - Binds a function to an event + - [x] off (eventName) - Unbinds all function from that event + - [x] fire () - Fires an event + +- [x] Basic Functionality + - [x] queue (initFn, runFn, alwaysInitialise) - Given two functions, the runner will run initFn once, and run runFn on every step. If alwaysInitialise is true, it will always run the initialisation as well. + - [x] during (runFn) - The function to run on each frame + +- [x] Runner Animation Methods + - [x] time (time) - Sets the time to the given time and runs the runner + - [x] step (dt) - Runs the runner method if + - [x] finish () - runs step with dT = Infinity + - [x] reverse () - Makes non-declarative runners play backwards + - [x] ease (fn) - Sets the easing function, can not be used to convert a non-declarative to a declarative animation. + - [x] active (activated) - Activates or deactivates a runner + - [x] loop (o) - Activates a loop sequence + +- [x] Runner Management + - [x] tag (name) - Name a runner or act as a getter + - [x] untag () diff --git a/useCases.md b/useCases.md new file mode 100644 index 0000000..d6acdcb --- /dev/null +++ b/useCases.md @@ -0,0 +1,330 @@ + + +# Tagged Animations + +The user can tag and control the runner for any animation + +```js + +var animation = element + .loop(300, true) + .tag('first') + .rotate(360) + .translate(50) + .animate(300, 200) + .tag('second') + .scale(3) + +element.timeline.finish() +element.timeline.pause() +element.timeline.stop() +element.timeline.play() + +``` + + +# Absolute Timeline Times + +The user can specify their time which is relative to the timelines time. + + +```js + +var animation = element.animate(2000).move(200, 200) + +// after 1000 ms +animation.animate(1000, 500, 'absolute').scale(2) + + +var runner = elemenet.move(0, 0).animate(1000) + +// after 500ms +runner.move(200, 200) + +``` + +This block of code would: +- Spend the first 1000ms moving the element +- At this time, it will snap the scale to 1.5 (halfway to 2) +- After this time, the scale and the move should go together + + +# Rotating While Scaling + +The user may want to run multiple animations concurrently and have +control over each animation that they define. + +```js + +let animationA = element.loop(300, ">").rotate(360) +let animationB = element.loop(200, "><").scale(2) + +// Maybe they want to disable a runner - which acts like pausing +animationB.active(false) + +// Maybe they want to remove an animation matching a tag +animationB.tag('B') +element.timeline().remove('B') + +// They can move around a runner as well +element.timeline() + .schedule('B', 300, 'absolute') // Moves a runner to start at 300 + // time(currentAbsolute - newAbsolute) + .shift('B', 300) // Shifts the runner start time by 300 + // which is sugar to + .schedule('B', 300, 'relative') + // seek(shiftTime) + +``` + +Lets demonstrate the difference between the schedule and shift + +``` +Given this: + + -------- + -------------- + ---------------- + +Schedule: + -------- + -------------- + ---------------- + +Shift: + -------- + -------------- + ---------------- +``` + + + +# A Sequenced Animation + +The user might want to be able to run a long sequenced animation that they have +predesigned as they please. + +```js + +let timeline = element.loop(300, "><").scale(2) + .animate(300).rotate(30) + .animate(300, 200).fill(blue) + +// They might want to move forwards or backwards +timeline.seek(-300) + +// They might want to set a specific time +timeline.time(200) + +// Or a specific position +timeline.position(0.3) + +// Maybe they want to clear the timeline +timeline.reset() + +``` + + +# User wants to Loop Something + +If the user wants to loop something, they should be able to call the loop +method at any time, and it will just change the behaviour of the current +runner. If we are running declaratively, we will throw an error. + +## Correct Usages + +They can invoke this from the timeline + +```js +element.loop(duration, times, swing) +``` + +If they want to work with absolute times, they should animate first + +```js +element.animate(300, 200, true) + .loop(Infinity, true) +``` + +Or alternatively, they could equivalently do this: + +```js +element.loop({ + now: true, + times: Infinity, + delay: 200, + duration: 300, + swing: true, + wait: [200, 300] +}) +``` + +## Error Case + + + +# Declarative Animations + +The user might want to have something chase their mouse around. This would +require a declarative animation. + +```js + +el.animate((curr, target, dt, ctx) => { + + // Find the error and the value + let error = target - current + ctx.speed = (ctx.error - error) / dt + ctx.error = error + return newPos + +}) + +SVG.on(document, 'mousemove', (ev) => { + + el.timeline(controller) + .move(ev.pageX, ev.pageY) + +}) + +``` + + +## Springy Mouse Chaser + +Pretend we gave the user a springy controller that basically springs to a +target in 300ms for example. They might be constantly changing the target with: + +```js + +el.animate(Spring(500), 200) + .tag('declarative') + .persist() + .move(10, 10) + +el.animate('declarative') + .move(300, 200) + + + +SVG.on(document, 'mousemove', function (ev) { + + el.animate(springy, 200) + .tag('declarative') + .move(ev.pageX, ev.pageY) + +}) + +``` + + +# Repeated Animations + +The user might want to duplicate an animation and have it rerun a few times + +```js + +// User makes two copies of an animation +let animA = el.animate(300, 300, 'now')...(animation)... +let animB = animA.clone() // Deep copy + +// Now let the user attach and reschedule their animations +el.timeline() + .schedule(animA, 500, 'absolute') + .schedule(animB, 2000, 'absolute') + +``` + +Then the user can loop the timeline, by changing its play mode + +```js +el.timeline() + .loop(times, swing, waits) +``` + + +# Advanced Animations + +The user can create their own runners and then attach it to the timeline +themselves if they like. + +```js + +// They declare their animation +let rotation = () => new SVG.Runner().rotate(500) + +// They attach an element, and schedule the runner +let leftAnimation = rotation().element(leftSquare).reverse() + +// They might want to animate another +let rightAnimation = rotation().element(rightSquare) + +// They can schedule these two runners to a master element +timelineElement.timeline() + .schedule(leftAnimation, 300, 'absolute') + .schedule(rightAnimation, 500, 'now') + .schedule(rightAnimation, 300, 'end') + +// Or they can schedule it to a timeline as well +let timeline = new SVG.Timeline() + .schedule(leftAnimation, 300, 'absolute') + .schedule(rightAnimation, 500, 'now') + +``` + + +# Modifying Controller Parameters + +Some user might want to change the speed of a controller, or how the controller +works in the middle of an animation. For example, they might do: + +```js + +var pid = PID(30, 20, 40) +let animation = el.animate(pid).move(.., ..) + + +// Some time later, the user slides a slider, and they can do: +slider1.onSlide( v => pid.p(v) ) + +``` + + +# Bidirectional Scheduling **(TODO)** + +We would like to schedule a runner to a timeline, or to do the opposite + +```js + +// If we have a runner and a timeline +let timeline = new Timeline()... +let runner = new Runner()... + +// Since the user can schedule a runner onto a timeline +timeline.schedule(runner, ...rest) + +// It should be possible to do the opposite +runner.schedule(timeline, ...rest) + +// It could be Implemented like this +runner.schedule = (t, duration, delay, now) { + this._timeline.remove(this) // Should work even if its not scheduled + t.schedule(this, duration, delay, now) + return this +} + +// The benefit would be that they could call animate afterwards: eg: +runner.schedule(timeline, ...rest) + .animate()... + +``` + +# Binding Events + +The user might want to react to some events that the runner might emit. We will +emit the following events from the runner: +- start - when a runner first initialises +- finish - when a runner finishes +- step - on every step + +Maybe they also want to react to timeline events as well |