diff --git a/index.html b/index.html new file mode 100644 index 0000000..b36dbda --- /dev/null +++ b/index.html @@ -0,0 +1,19 @@ + + + + + viewer + + +open content(.txt): +open annotation(.json): + +
+ + + + + \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..9890a11 --- /dev/null +++ b/main.js @@ -0,0 +1,71 @@ +/** + * Created by yjh on 2016/10/8. + */ +System.register(['./node_modules/synyi-annotation-tool/src/Annotator'], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var Annotator_1; + var categories; + function loadContentOfFile(file) { + var fr = new FileReader(); + return new Promise(function (resolve) { + fr.onload = function () { + resolve(fr.result); + }; + fr.readAsText(file, 'utf-8'); + }); + } + function run() { + document.querySelector('#con').innerHTML = ''; + var contentInput = document.querySelector('input#content'); + var annotationInput = document.querySelector('input#annotation'); + Promise.all([loadContentOfFile(contentInput.files[0]), loadContentOfFile(annotationInput.files[0])]) + .then(function (results) { + var ann = new Annotator_1.Annotator(document.querySelector('#con')); + var annotations = JSON.parse(results[1]); + var relations = []; + var labels = annotations['concepts'].map(function (concept) { + concept['relations'] = concept['relations'] || []; + concept['relations'].forEach(function (relation) { + if (relation['attribute_id'] != undefined) { + relations.push({ + dst: concept['meta']['id'], + src: relation['attribute_id'], + text: relation['relation_type'] + }); + } + }); + return { + 'category': Annotator_1.Categories[concept['meta']['category']], + 'pos': [concept['meta']['start_index'], concept['meta']['end_index'] - 1], + 'id': concept['meta']['id'] + }; + }).filter(function (x) { return !(x['category'] == undefined); }); + ann.import(results[0], categories, labels, relations); + }); + } + return { + setters:[ + function (Annotator_1_1) { + Annotator_1 = Annotator_1_1; + }], + execute: function() { + categories = [ + { id: 1, fill: 'rgb(174, 214, 241)', boader: 'rgb(93, 173, 226)', highlight: 'rgba(174, 214, 241,0.4)', text: "症状、表现", }, + { id: 2, fill: 'rgb(169, 204, 227)', boader: 'rgb(84, 153, 199)', highlight: 'rgba(169, 204, 227,0.4)', text: "疾病", }, + { id: 3, fill: 'rgb(210, 180, 222)', boader: 'rgb(165, 105, 189)', highlight: 'rgba(210, 180, 222,0.4)', text: "检查、评分", }, + { id: 4, fill: 'rgb(215, 189, 226)', boader: 'rgb(175, 122, 197)', highlight: 'rgba(215, 189, 226,0.4)', text: "治疗", }, + { id: 5, fill: 'rgb(245, 183, 177)', boader: 'rgb(236, 112, 99)', highlight: 'rgba(245, 183, 177,0.4)', text: "指标", }, + { id: 6, fill: 'rgb(230, 176, 170)', boader: 'rgb(205, 97, 85)', highlight: 'rgba(230, 176, 170,0.4)', text: "药物", }, + { id: 7, fill: 'rgb(237, 187, 153)', boader: 'rgb(245, 176, 65)', highlight: 'rgba(237, 187, 153,0.4)', text: "部位、方位", }, + { id: 8, fill: 'rgb(245, 203, 167)', boader: 'rgb(244, 208, 63)', highlight: 'rgba(245, 203, 167,0.4)', text: "频率", }, + { id: 9, fill: 'rgb(250, 215, 160)', boader: 'rgb(252, 220, 160)', highlight: 'rgba(250, 215, 160,0.4)', text: "值", }, + { id: 10, fill: 'rgb(171, 235, 198)', boader: 'rgb(181, 222, 190)', highlight: 'rgba(171, 235, 198,0.4)', text: "症状变化", }, + { id: 11, fill: 'rgb(169, 223, 191)', boader: 'rgb(175, 220, 190)', highlight: 'rgba(169, 223, 191,0.4)', text: "其他修饰词" }, + { id: 12, fill: 'rgb(249, 231, 159)', boader: 'rgb(82, 190, 128)', highlight: 'rgba(249, 231, 159,0.4)', text: "时间", }, + ]; + document.querySelector('#run').addEventListener('click', function () { return run(); }); + } + } +}); +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/main.js.map b/main.js.map new file mode 100644 index 0000000..44db45b --- /dev/null +++ b/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..0754d09 --- /dev/null +++ b/main.ts @@ -0,0 +1,58 @@ +/** + * Created by yjh on 2016/10/8. + */ + +import {Annotator, Categories} from './node_modules/synyi-annotation-tool/src/Annotator' +function loadContentOfFile(file: File) { + let fr = new FileReader(); + return new Promise(resolve=> { + fr.onload = function () { + resolve(fr.result) + }; + fr.readAsText(file, 'utf-8') + }) +} +let categories=[ + {id:1, fill: 'rgb(174, 214, 241)', boader: 'rgb(93, 173, 226)', highlight: 'rgba(174, 214, 241,0.4)', text: "症状、表现",}, + {id:2, fill: 'rgb(169, 204, 227)', boader: 'rgb(84, 153, 199)', highlight: 'rgba(169, 204, 227,0.4)', text: "疾病",}, + {id:3, fill: 'rgb(210, 180, 222)', boader: 'rgb(165, 105, 189)',highlight: 'rgba(210, 180, 222,0.4)', text: "检查、评分",}, + {id:4, fill: 'rgb(215, 189, 226)', boader: 'rgb(175, 122, 197)',highlight: 'rgba(215, 189, 226,0.4)', text: "治疗",}, + {id:5, fill: 'rgb(245, 183, 177)', boader: 'rgb(236, 112, 99)', highlight: 'rgba(245, 183, 177,0.4)', text: "指标",}, + {id:6, fill: 'rgb(230, 176, 170)', boader: 'rgb(205, 97, 85)', highlight: 'rgba(230, 176, 170,0.4)', text: "药物",}, + {id:7, fill: 'rgb(237, 187, 153)', boader: 'rgb(245, 176, 65)', highlight: 'rgba(237, 187, 153,0.4)', text: "部位、方位",}, + {id:8, fill: 'rgb(245, 203, 167)', boader: 'rgb(244, 208, 63)', highlight: 'rgba(245, 203, 167,0.4)', text: "频率",}, + {id:9, fill: 'rgb(250, 215, 160)', boader: 'rgb(252, 220, 160)', highlight: 'rgba(250, 215, 160,0.4)', text: "值",}, + {id:10, fill: 'rgb(171, 235, 198)', boader: 'rgb(181, 222, 190)', highlight: 'rgba(171, 235, 198,0.4)', text: "症状变化",}, + {id:11, fill: 'rgb(169, 223, 191)', boader: 'rgb(175, 220, 190)', highlight: 'rgba(169, 223, 191,0.4)', text: "其他修饰词"}, + {id:12, fill: 'rgb(249, 231, 159)', boader: 'rgb(82, 190, 128)', highlight: 'rgba(249, 231, 159,0.4)', text: "时间",}, +]; +function run() { + document.querySelector('#con').innerHTML = ''; + let contentInput: HTMLInputElement = document.querySelector('input#content') as HTMLInputElement; + let annotationInput: HTMLInputElement = document.querySelector('input#annotation') as HTMLInputElement; + Promise.all([loadContentOfFile(contentInput.files[0]), loadContentOfFile(annotationInput.files[0])]) + .then(results=> { + let ann = new Annotator(document.querySelector('#con')); + let annotations = JSON.parse(results[1]); + let relations = []; + let labels = annotations['concepts'].map(concept=> { + concept['relations'] = concept['relations'] || []; + concept['relations'].forEach(relation=> { + if (relation['attribute_id'] != undefined) { + relations.push({ + dst: concept['meta']['id'], + src: relation['attribute_id'], + text: relation['relation_type'] + }) + } + }); + return { + 'category': Categories[concept['meta']['category']], + 'pos': [concept['meta']['start_index'], concept['meta']['end_index'] - 1], + 'id': concept['meta']['id'] + } + }).filter(x=>!(x['category'] == undefined)); + ann.import(results[0],categories, labels, relations) + }) +} +document.querySelector('#run').addEventListener('click',()=>run()); \ No newline at end of file diff --git a/node_modules/svgjs/.documentup.json b/node_modules/svgjs/.documentup.json new file mode 100644 index 0000000..ccf71a6 --- /dev/null +++ b/node_modules/svgjs/.documentup.json @@ -0,0 +1,8 @@ +{ + "twitter": [ + "svg_js" + ], + "travis": false, + "issues": true, + "theme": "v1" +} \ No newline at end of file diff --git a/node_modules/svgjs/.npmignore b/node_modules/svgjs/.npmignore new file mode 100644 index 0000000..675a80c --- /dev/null +++ b/node_modules/svgjs/.npmignore @@ -0,0 +1,10 @@ +.DS_Store +.idea +public +site/ +bleed/ +docs/ +obsolete/ +test/ +src/index.js +node_modules/ \ No newline at end of file diff --git a/node_modules/svgjs/CHANGELOG.md b/node_modules/svgjs/CHANGELOG.md new file mode 100644 index 0000000..22a84ee --- /dev/null +++ b/node_modules/svgjs/CHANGELOG.md @@ -0,0 +1,248 @@ +# 3.0.0 + +- make transform-methods relative as default (breaking change) +- added `'random'` option and `randomize()` method to `SVG.Color` -> __TODO!__ +- added `enqueue()` method to `SVG.FX` -> __TODO!__ +- fixed a bug in clipping and masking where empty nodes persists after removal -> __TODO!__ +- fixed a bug in IE11 with `mouseenter` and `mouseleave` -> __TODO!__ +- added `precision()` method to round numeric element attributes -> __TODO!__ +- added specs for `SVG.FX` -> __TODO!__ + +# 2.3.0 +- added `SVG.Point` which serves as Wrapper to the native `SVGPoint` (#437) +- added `element.point(x,y)` which transforms a point from screen coordinates to the elements space (#403) +- fixed `svgjs:data` attribute which was not set properly in all browsers (#428) + +# 2.2.5 (29/12/2015) +- added check for existence of node (#431) +- `group.move()` now allows string numbers as input (#433) +- `matrixify()` will not apply the calculated matrix to the node anymore + +# 2.2.4 (12/12/2015) +- fixed `transform()` which returns the matrix values (a-f) now, too (#423) +- double newlines (\n\n) are correctly handled as blank line from `text()` +- fixed use of scrollX vs pageXOffset in `rbox()` (#425) +- fixed target array in mask and clip which was removed instead of reinitialized (#429) + +# 2.2.3 (30/11/2015) +- fixed null check in image (see 2.2.2) +- fixed bug related to the new path parser (see 2.2.2) +- fixed amd loader (#412) + +# 2.2.2 (28/11/2015) +- fixed leading point bug in path parsing (#416) +- added null check in image onload callback (#415) +- documentation rework (#407) [thanks @snowyplover] + +# 2.2.1 (18/11/2015) +- added workaround for `SvgPathSeg` which is removed in Chrome 48 (#409) +- added `gbox()` to group to get bbox with translation included (#405) +- fixed dom data which was not cleaned up properly (#398) + +# 2.2.0 (06/11/2015) + +- fixed pattern and gradient animation (#385) +- fixed mask animation in Firefox (#287) +- fixed return value of `text()` after import/clone (#393) +- svgjs now saves crucial data in the dom before export and restores them when element is adopted +- added `ungroup()/flatten()` (#238), `toParent()` and `toDoc()` +- added UMD-Wrapper with possibility to pass custom window object (#352) +- added `morph()` method for paths via plugin [svg.pathmorphing.js](https://github.com/Fuzzyma/svg.pathmorphing.js) +- added support for css selectors within the `parent()` method +- added `parents()` method to get an array of all parenting elements + +# 2.1.1 (03/10/2015) + +- added custom context binding to event callback (default is the element the event is bound to) + +# 2.1.0 (20/09/2015) + +- added transform to pattern and gradients (#383) +- fixed clone of textnodes (#369) +- fixed transformlists in IE (#372) +- fixed typo that leads to broken gradients (#370) +- fixed animate radius for circles (#367) + +# 2.0.2 (22/06/2015) + +- Fixed zoom consideration in circle and ellipse + +# 2.0.1 (21/06/2015) + +- fixed bug with `doc()` which always should return root svg +- removed target reference from use which caused bugs in `dmove()` and `use()` with external file +- added possibility to remove all events from a certain namespace +- fixed bug in `SVG.FX` when animating with `plot()` +- removed scale consideration in `move()` duo to incompatibilities with other move-functions e.g. in `SVG.PointArray` + +# 2.0.0 (11/06/2015) + +- implemented an SVG adoption system to be able to manipulate existing SVG's not created with svg.js +- changed `parent` reference on elements to `parent()` method +- using `CustomEvent` instead of `Event` to be able to fire events with a `detail` object [thanks @Fuzzyma] +- added polyfill for IE9 and IE10 custom events [thanks @Fuzzyma] +- added DOM query selector with the `select()` method globally or on parent elements +- added the intentionally neglected `SVG.Circle` element +- fixed bug in `radius()` method when `y` value equals `0` +- renamed `SVG.TSpan` class to `SVG.Tspan` to play nice with the adoption system +- added `rx()` and `ry()` to `SVG.Rect`, `SVG.Circle`, `SVG.Ellispe` and `SVG.FX` +- changed `array` reference to `array()` method on `SVG.Polyline`, `SVG.Polygon` and `SVG.Path` +- completely reworked `clone()` method to use the adoption system +- added support to clone manually built text elements +- added `svg.wiml.js` plugin to plugins list +- added `ctm()` method to for matrix-centric transformations +- added `morph()` method to `SVG.Matrix` +- added support for new matrix system to `SVG.FX` +- completely reworked transformations to be chainable and more true to their nature +- changed `lines` reference to `lines()` on `SVG.Text` +- changed `track` reference to `track()` on `SVG.Text` +- changed `textPath` reference to `textPath()` on `SVG.Text` +- added raw svg import functionality with the `svg()` method +- reworked sup-pixel offset implementation to be more compact +- added `native()` method to elements and matrix to get to the native api +- added `untransform()` method to remove all transformations +- switched from Ruby's `rake` to Node's `gulp` for building [thanks to Alex Ewerlöf] +- added coding style description to README +- changed `to()` method to `at()` method in `SVG.FX` +- added reverse functionality for animations +- documented the `situation` object in `SVG.FX` +- renamed `SVG.SetFX` to `SVG.FX.Set` +- added distinction between relative and absolute matrix transformations +- implemented the `element()` method using the `SVG.Bare` class to create elements that are not described by SVG.js +- removed `SVG.Symbol` but kept the `symbol()` method using the new `element()` method +- reworked `SVG.Number` to return new instances with calculations rather than itself +- added `w` and `h` properties as shorthand for `width` and `height` to `SVG.BBox` +- added `SVG.TBox` to get a bounding box that is affected by transformation values +- reworked animatable matrix rotations +- fixed a bug where events are not detached properly +- added event-based or complete detaching of event listeners in `off()` method + +# 1.0.0-rc.9 (17/06/2014) + +- added `SVG.Marker` +- added `SVG.Symbol` +- added `first()` and `last()` methods to `SVG.Set` +- added `length()` method to `SVG.Text` and `SVG.TSpan` to calculate total text length +- `SVG.get()` will now also fetch elements with a `xlink:href="#elementId"` or `url(#elementId)` value given +- added `reference()` method to get referenced elements from a given attribute value +- fixed infinite loop in viewbox when element has a percentage width / height [thanks @shabegger] + +# 1.0.0-rc.8 (12/06/2014) + +- fixed bug in `SVG.off` +- fixed offset by window scroll position in `rbox()` [thanks @bryhoyt] + +# 1.0.0-rc.7 (11/06/2014) + +- calling `after()` when calling `stop(true)` (fulfill flag) [thanks @vird] +- added `classes()`, `hasClass()`, `addClass()`, `removeClass()` and `toggleClass()` [thanks @pklingem] +- fixed a bug where `Element#style()` would not save empty values in IE11 [thanks @Shtong] +- fixed `SVG is not defined error` [thanks @anvaka] +- fixed a bug in `move()`on text elements with a string based value +- binding events listeners to svg.js instance +- text element fires `rebuild` event whenever the `rebuild()` method is called +- fix for `text()` method on text element when acting as getter [thanks @Lochemage] +- fix in `style()` method with a css string [thanks @TobiasHeckel] + +# 1.0.0-rc.6 (03/03/2014) + +- fine-tuned text element positioning +- fixed a bug in text `dy()` method +- added `leading()` method to `SVG.FX` +- removed internal representation for `style` +- added `reverse()` method to `SVG.Array` (and thereby also to `SVG.PointArray` and `SVG.PathArray`) +- added `fulfill` option to `stop()` method in `SVG.FX` to finalise animations +- calling `at()` method directly on morphable svg.js instances in `SVG.FX` module +- moved most `_private` methods to local named functions +- moved helpers to a separate file +- added more output values to `bbox()` and `rbox()` methods + +# 1.0.0-rc.5 (14/02/2014) + +- added `plain()` method to `SVG.Text` element to add plain text content, without tspans +- added `plain()` method to parent elements to create a text element without tspans +- updated `SVG.TSpan` to accept nested tspan elements, not unlike the `text()` method in `SVG.Text` +- removed the `relative()` method in favour of `dx()`, `dy()` and `dmove()` +- switched form objects to arrays in `SVG.PathArray` for compatibility with other libraries and better performance on parsing and rendering (up-to 48% faster than 1.0.0-rc.4) +- refined docs on element-specific methods and `SVG.PathArray` structure +- added `build()` to enable/disable build mode +- removed verbose style application to tspans +- reworked `leading()` implementation to be more font-size "aware" +- refactored the `attr` method on `SVG.Element` +- applied Helvetica as default font +- building `SVG.FX` class with `SVG.invent()` function + +# 1.0.0-rc.4 (04/02/2014) + +- switched to `MAJOR`.`MINOR`.`PATCH` versioning format to play nice with package managers +- made svg.pattern.js part of the core library +- automatic pattern creation by passing an image url or instance as `fill` attribute on elements +- added `loaded()` method to image tag +- fix in `animate('=').to()` +- added `pointAt()` method to `SVG.Path`, wrapping the native `getPointAtLength()` +- moved `length()` method to sugar module +- fix for arcs in patharray `toString()` method [thanks @dotnetCarpenter] + +# v1.0rc3 (03/02/2014) + +- fix for html-less documents +- added the `SVG.invent` function to ease invention of new elements +- using `SVG.invent` to generate core shapes as well for leaner code +- added second values for `animate('2s')` +- fix for arcs in patharray `toString()` method +- added `length()` mehtod to path, wrapping the native `getTotalLength()` + +# v1.0rc2 (01/02/2014) + +- added `index()` method to `SVG.Parent` and `SVG.Set` +- modified `cx()` and `cy()` methods on elements with native `x`, `y`, `width` and `height` attributes for better performance +- added `morph()` and `at()` methods to `SVG.Number` for unit morphing + +# v1.0rc1 (31/01/2014) + +- added `SVG.PathArray` for real path transformations +- removed `unbiased` system for paths +- enabled proportional resizing on `size()` method with `null` for either `width` or `height` values +- moved data module to separate file +- `data()` method now accepts object for for multiple key / value assignments +- added `bbox()` method to `SVG.Set` +- added `relative()` method for moves relative to the current position +- added `morph()` and `at()` methods to `SVG.Color` for color morphing + +# v0.38 (28/01/2014) + +- added `loop()` method to `SVG.FX` +- switched from `setInterval` to `requestAnimFrame` for animations + +# v0.37 (26/01/2014) + +- added `get()` to `SVG.Set` +- moved `SVG.PointArray` to a separate file + +# v0.36 (25/01/2014) + +- added `linkTo()`, `addTo()` and `putIn()` methods on `SVG.Element` +- provided more detailed documentation on parent elements + +# v0.35 (23/01/2014) + +- added `SVG.A` element with the `link()` + +# v0.34 (23/01/2014) + +- added `pause()` and `play()` to `SVG.FX` +- storing animation values in `situation` object + +# v0.33 (22/01/2014) + +- added `has()` method to `SVG.Set` +- added `width()` and `height()` as setter and getter methods on all shapes +- moved sub-pixel offset fix to be an optional method (e.g. `SVG('drawing').fixSubPixelOffset()`) +- added `replace()` method to elements +- added `radius()` method to `SVG.Rect` and `SVG.Ellipse` +- added reference to parent node in defs +- merged plotable.js and path.js + +# v0.32 + +- added library to [cdnjs](http://cdnjs.com) \ No newline at end of file diff --git a/node_modules/svgjs/LICENSE.txt b/node_modules/svgjs/LICENSE.txt new file mode 100644 index 0000000..92730ed --- /dev/null +++ b/node_modules/svgjs/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2012-2014 Wout Fierens +http://svgjs.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/svgjs/README.md b/node_modules/svgjs/README.md new file mode 100644 index 0000000..8a6c012 --- /dev/null +++ b/node_modules/svgjs/README.md @@ -0,0 +1,4014 @@ +The .js breaks es6 imports so I need to republish it... + +# SVG.js + +A lightweight library for manipulating and animating SVG. + +Svg.js has no dependencies and aims to be as small as possible. + +Svg.js is licensed under the terms of the MIT License. + +See [svgjs.com](http://svgjs.com) for an introduction, [documentation](http://documentup.com/wout/SVG.js) and [some action](http://svgjs.com/test). + +## Usage + +### Create an SVG document + +Use the `SVG()` function to create an SVG document within a given html element: + +```javascript +var draw = SVG('drawing').size(300, 300) +var rect = draw.rect(100, 100).attr({ fill: '#f06' }) +``` +The first argument can either be an id of the element or the selected element itself. +This will generate the following output: + +```html +
+ + + +
+``` + +By default the svg drawing follows the dimensions of its parent, in this case `#drawing`: + +```javascript +var draw = SVG('drawing').size('100%', '100%') +``` + +### Checking for SVG support + +By default this library assumes the client's browser supports SVG. You can test support as follows: + +```javascript +if (SVG.supported) { + var draw = SVG('drawing') + var rect = draw.rect(100, 100) +} else { + alert('SVG not supported') +} +``` + + +### SVG document +Svg.js also works outside of the HTML DOM, inside an SVG document for example: + +```xml + + + + + +``` + +### Sub-pixel offset fix +Call the `spof()` method to fix sub-pixel offset: + +```javascript +var draw = SVG('drawing').spof() +``` + +To enable automatic sub-pixel offset correction when the window is resized: + +```javascript +SVG.on(window, 'resize', function() { draw.spof() }) +``` + +## Parent elements + +### Main svg document +The main SVG.js initializer function creates a root svg node in the given element and returns an instance of `SVG.Doc`: + +```javascript +var draw = SVG('drawing') +``` + +__`returns`: `SVG.Doc`__ + +_Javascript inheritance stack: `SVG.Doc` < `SVG.Container` < `SVG.Parent`_ + +### Nested svg +With this feature you can nest svg documents within each other. Nested svg documents have exactly the same features as the main, top-level svg document: + +```javascript +var nested = draw.nested() + +var rect = nested.rect(200, 200) +``` + +__`returns`: `SVG.Nested`__ + +_Javascript inheritance stack: `SVG.Nested` < `SVG.Container` < `SVG.Parent`_ + +### Groups +Grouping elements is useful if you want to transform a set of elements as if it were one. All element within a group maintain their position relative to the group they belong to. A group has all the same element methods as the root svg document: + +```javascript +var group = draw.group() +group.path('M10,20L30,40') +``` + +Existing elements from the svg document can also be added to a group: + +```javascript +group.add(rect) +``` + +__Note:__ Groups do not have a geometry of their own, it's inherited from their content. Therefore groups do not listen to `x`, `y`, `width` and `height` attributes. If that is what you are looking for, use a `nested()` svg instead. + +__`returns`: `SVG.G`__ + +_Javascript inheritance stack: `SVG.G` < `SVG.Container` < `SVG.Parent`_ + +### Hyperlink +A hyperlink or `` tag creates a container that enables a link on all children: + +```javascript +var link = draw.link('http://svgjs.com') +var rect = link.rect(100, 100) +``` + +The link url can be updated with the `to()` method: + +```javascript +link.to('http://apple.com') +``` + +Furthermore, the link element has a `show()` method to create the `xlink:show` attribute: + +```javascript +link.show('replace') +``` + +And the `target()` method to create the `target` attribute: + +```javascript +link.target('_blank') +``` + +Elements can also be linked the other way around with the `linkTo()` method: + +```javascript +rect.linkTo('http://svgjs.com') +``` + +Alternatively a block can be passed instead of a url for more options on the link element: + +```javascript +rect.linkTo(function(link) { + link.to('http://svgjs.com').target('_blank') +}) +``` + +__`returns`: `SVG.A`__ + +_Javascript inheritance stack: `SVG.A` < `SVG.Container` < `SVG.Parent`_ + +### Defs +The `` element is a container element for referenced elements. Elements that are descendants of a ‘defs’ are not rendered directly. The `` node lives in the main `` document and can be accessed with the `defs()` method: + +```javascript +var defs = draw.defs() +``` + +The defs are also available on any other element through the `doc()` method: + +```javascript +var defs = rect.doc().defs() +``` + +The defs node works exactly the same as groups. + +__`returns`: `SVG.Defs`__ + +_Javascript inheritance stack: `SVG.Defs` < `SVG.Container` < `SVG.Parent`_ + +## Rect +Rects have two arguments, their `width` and `height`: + +```javascript +var rect = draw.rect(100, 100) +``` + +__`returns`: `SVG.Rect`__ + +_Javascript inheritance stack: `SVG.Rect` < `SVG.Shape` < `SVG.Element`_ + +### radius() +Rects can also have rounded corners: + +```javascript +rect.radius(10) +``` + +This will set the `rx` and `ry` attributes to `10`. To set `rx` and `ry` individually: + +```javascript +rect.radius(10, 20) +``` + +__`returns`: `itself`__ + +## Circle +The only argument necessary for a circle is the diameter: + +```javascript +var circle = draw.circle(100) +``` + +__`returns`: `SVG.Circle`__ + +_Javascript inheritance stack: `SVG.Circle` < `SVG.Shape` < `SVG.Element`_ + +### radius() +Circles can also be redefined by their radius: + +```javascript +circle.radius(75) +``` + +__`returns`: `itself`__ + +## Ellipse +Ellipses, like rects, have two arguments, their `width` and `height`: + +```javascript +var ellipse = draw.ellipse(200, 100) +``` + +__`returns`: `SVG.Ellipse`__ + +_Javascript inheritance stack: `SVG.Ellipse` < `SVG.Shape` < `SVG.Element`_ + +### radius() +Ellipses can also be redefined by their radii: + +```javascript +ellipse.radius(75, 50) +``` + +__`returns`: `itself`__ + +## Line +Create a line from point A to point B: + +```javascript +var line = draw.line(0, 0, 100, 150).stroke({ width: 1 }) +``` + +Creating a line element can be done in four ways. Look at the `plot()` method to see all the possiblilities. + +__`returns`: `SVG.Line`__ + +_Javascript inheritance stack: `SVG.Line` < `SVG.Shape` < `SVG.Element`_ + +### plot() +Updating a line is done with the `plot()` method: + +```javascript +line.plot(50, 30, 100, 150) +``` + +Alternatively it also accepts a point string: + +```javascript +line.plot('0,0 100,150') +``` + +Or a point array: + +```javascript +line.plot([[0, 0], [100, 150]]) +``` + +Or an instance of `SVG.PointArray`: + +```javascript +var array = new SVG.PointArray([[0, 0], [100, 150]]) +line.plot(array) +``` + +__`returns`: `itself`__ + +### array() +References the `SVG.PointArray` instance. This method is rather intended for internal use: + +```javascript +polyline.array() +``` + +__`returns`: `SVG.PointArray`__ + + +## Polyline +The polyline element defines a set of connected straight line segments. Typically, polyline elements define open shapes: + +```javascript +// polyline('x,y x,y x,y') +var polyline = draw.polyline('0,0 100,50 50,100').fill('none').stroke({ width: 1 }) +``` + +Polyline strings consist of a list of points separated by spaces: `x,y x,y x,y`. + +As an alternative an array of points will work as well: + +```javascript +// polyline([[x,y], [x,y], [x,y]]) +var polyline = draw.polyline([[0,0], [100,50], [50,100]]).fill('none').stroke({ width: 1 }) +``` + +__`returns`: `SVG.Polyline`__ + +_Javascript inheritance stack: `SVG.Polyline` < `SVG.Shape` < `SVG.Element`_ + +### plot() +Polylines can be updated using the `plot()` method: + +```javascript +polyline.plot([[0,0], [100,50], [50,100], [150,50], [200,50]]) +``` + +The `plot()` method can also be animated: + +```javascript +polyline.animate(3000).plot([[0,0], [100,50], [50,100], [150,50], [200,50], [250,100], [300,50], [350,50]]) +``` + +__`returns`: `itself`__ + +### array() +References the `SVG.PointArray` instance. This method is rather intended for internal use: + +```javascript +polyline.array() +``` + +__`returns`: `SVG.PointArray`__ + +## Polygon +The polygon element, unlike the polyline element, defines a closed shape consisting of a set of connected straight line segments: + +```javascript +// polygon('x,y x,y x,y') +var polygon = draw.polygon('0,0 100,50 50,100').fill('none').stroke({ width: 1 }) +``` + +Polygon strings are exactly the same as polyline strings. There is no need to close the shape as the first and last point will be connected automatically. + +__`returns`: `SVG.Polygon`__ + +_Javascript inheritance stack: `SVG.Polygon` < `SVG.Shape` < `SVG.Element`_ + +### plot() +Like polylines, polygons can be updated using the `plot()` method: + +```javascript +polygon.plot([[0,0], [100,50], [50,100], [150,50], [200,50]]) +``` + +The `plot()` method can also be animated: + +```javascript +polygon.animate(3000).plot([[0,0], [100,50], [50,100], [150,50], [200,50], [250,100], [300,50], [350,50]]) +``` + +__`returns`: `itself`__ + +### array() +References the `SVG.PointArray` instance. This method is rather intended for internal use: + +```javascript +polygon.array() +``` + +__`returns`: `SVG.PointArray`__ + +## Path +The path string is similar to the polygon string but much more complex in order to support curves: + +```javascript +draw.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') +``` + +__`returns`: `SVG.Path`__ + +_Javascript inheritance stack: `SVG.Path` < `SVG.Shape` < `SVG.Element`_ + +For more details on path data strings, please refer to the SVG documentation: +http://www.w3.org/TR/SVG/paths.html#PathData + +### plot() +Paths can be updated using the `plot()` method: + +```javascript +path.plot('M100,200L300,400') +``` + +__`returns`: `itself`__ + +### array() +References the `SVG.PathArray` instance. This method is rather intended for internal use: + +```javascript +path.array() +``` + +__`returns`: `SVG.PathArray`__ + +## Image +Creating images is as you might expect: + +```javascript +var image = draw.image('/path/to/image.jpg') +``` + +If you know the size of the image, those parameters can be passed as the second and third arguments: + +```javascript +var image = draw.image('/path/to/image.jpg', 200, 300) +``` + +__`returns`: `SVG.Image`__ + +_Javascript inheritance stack: `SVG.Image` < `SVG.Shape` < `SVG.Element`_ + +### load() +Loading another image can be done with the `load()` method: + +```javascript +image.load('/path/to/another/image.jpg') +``` + +__`returns`: `itself`__ + +### loaded() +If you don't know the size of the image, obviously you will have to wait for the image to be `loaded`: + +```javascript +var image = draw.image('/path/to/image.jpg').loaded(function(loader) { + this.size(loader.width, loader.height) +}) +``` + +The returned `loader` object as first the argument of the loaded method contains four values: +- `width` +- `height` +- `ratio` (width / height) +- `url` + +__`returns`: `itself`__ + + +## Text +Unlike html, text in svg is much harder to tame. There is no way to create flowing text, so newlines should be entered manually. In SVG.js there are two ways to create text elements. + +The first and easiest method is to provide a string of text, split by newlines: + +```javascript +var text = draw.text("Lorem ipsum dolor sit amet consectetur.\nCras sodales imperdiet auctor.") +``` + +This will automatically create a block of text and insert newlines where necessary. + +The second method will give you much more control but requires a bit more code: + +```javascript +var text = draw.text(function(add) { + add.tspan('Lorem ipsum dolor sit amet ').newLine() + add.tspan('consectetur').fill('#f06') + add.tspan('.') + add.tspan('Cras sodales imperdiet auctor.').newLine().dx(20) + add.tspan('Nunc ultrices lectus at erat').newLine() + add.tspan('dictum pharetra elementum ante').newLine() +}) +``` + +If you want to go the other way and don't want to add tspans at all, just one line of text, you can use the `plain()` method instead: + +```javascript +var text = draw.plain('Lorem ipsum dolor sit amet consectetur.') +``` + +This is a shortcut to the `plain` method on the `SVG.Text` instance which doesn't render newlines at all. + +_Javascript inheritance stack: `SVG.Text` < `SVG.Shape` < `SVG.Element`_ + +__`returns`: `SVG.Text`__ + +### text() +Changing text afterwards is also possible with the `text()` method: + +```javascript +text.text('Brilliant!') +``` + +__`returns`: `itself`__ + +To get the raw text content: + +```javascript +text.text() +``` + +__`returns`: `string`__ + +### tspan() +Just adding one tspan is also possible: + +```javascript +text.tspan(' on a train...').fill('#f06') +``` + +__`returns`: `SVG.Tspan`__ + +### plain() +If the content of the element doesn't need any stying or multiple lines, it might be sufficient to just add some plain text: + +```javascript +text.plain('I do not have any expectations.') +``` + +__`returns`: `itself`__ + +### font() +The sugar.js module provides some syntax sugar specifically for this element type: + +```javascript +text.font({ + family: 'Helvetica' +, size: 144 +, anchor: 'middle' +, leading: '1.5em' +}) +``` + +__`returns`: `itself`__ + +### leading() +As opposed to html, where leading is defined by `line-height`, svg does not have a natural leading equivalent. In svg, lines are not defined naturally. They are defined by `` nodes with a `dy` attribute defining the line height and a `x` value resetting the line to the `x` position of the parent text element. But you can also have many nodes in one line defining a different `y`, `dy`, `x` or even `dx` value. This gives us a lot of freedom, but also a lot more responsibility. We have to decide when a new line is defined, where it starts, what its offset is and what it's height is. The `leading()` method in SVG.js tries to ease the pain by giving you behaviour that is much closer to html. In combination with newline separated text, it works just like html: + +```javascript +var text = draw.text("Lorem ipsum dolor sit amet consectetur.\nCras sodales imperdiet auctor.") +text.leading(1.3) +``` + +This will render a text element with a tspan element for each line, with a `dy` value of `130%` of the font size. + +Note that the `leading()` method assumes that every first level tspan in a text node represents a new line. Using `leading()` on text elements containing multiple tspans in one line (e.g. without a wrapping tspan defining a new line) will render scrambeled. So it is advisable to use this method with care, preferably only when throwing newline separated text at the text element or calling the `newLine()` method on every first level tspan added in the block passed as argument to the text element. + +__`returns`: `itself`__ + +### build() +The `build()` can be used to enable / disable build mode. With build mode disabled, the `plain()` and `tspan()` methods will first call the `clear()` bethod before adding the new content. So when build mode is enabled, `plain()` and `tspan()` will append the new content to the existing content. When passing a block to the `text()` method, build mode is toggled automatically before and after the block is called. But in some cases it might be useful to be able to toggle it manually: + + +```javascript +var text = draw.text('This is just the start, ') + +text.build(true) // enables build mode + +var tspan = text.tspan('something pink in the middle ').fill('#00ff97') +text.plain('and again boring at the end.') + +text.build(false) // disables build mode + +tspan.animate('2s').fill('#f06') +``` + +__`returns`: `itself`__ + +### rebuild() +This is an internal callback that probably never needs to be called manually. Basically it rebuilds the text element whenerver `font-size` and `x` attributes or the `leading()` of the text element are modified. This method also acts a setter to enable or disable rebuilding: + +```javascript +text.rebuild(false) //-> disables rebuilding +text.rebuild(true) //-> enables rebuilding and instantaneously rebuilds the text element +``` + +__`returns`: `itself`__ + +### clear() +Clear all the contents of the called text element: + +```javascript +text.clear() +``` + +__`returns`: `itself`__ + +### length() +Gets the total computed text length of all tspans together: + +```javascript +text.length() +``` + +__`returns`: `number`__ + + +### lines() +All first level tspans can be referenced with the `lines()` method: + +```javascript +text.lines() +``` + +This will return an intance of `SVG.Set` including all `tspan` elements. + +__`returns`: `SVG.Set`__ + +### events +The text element has one event. It is fired every time the `rebuild()` method is called: + +```javascript +text.on('rebuild', function() { + // whatever you need to do after rebuilding +}) +``` + +## Tspan +The tspan elements are only available inside text elements or inside other tspan elements. In SVG.js they have a class of their own: + +_Javascript inheritance stack: `SVG.Tspan` < `SVG.Shape` < `SVG.Element`_ + +### text() +Update the content of the tspan. This can be done by either passing a string: + + +```javascript +tspan.text('Just a string.') +``` + +Which will basicly call the `plain()` method. + +Or by passing a block to add more specific content inside the called tspan: + +```javascript +tspan.text(function(add) { + add.plain('Just plain text.') + add.tspan('Fancy text wrapped in a tspan.').fill('#f06') + add.tspan(function(addMore) { + addMore.tspan('And you can doo deeper and deeper...') + }) +}) +``` + +__`returns`: `itself`__ + +### tspan() +Add a nested tspan: + +```javascript +tspan.tspan('I am a child of my parent').fill('#f06') +``` + +__`returns`: `SVG.Tspan`__ + +### plain() +Just adds some plain text: + +```javascript +tspan.plain('I do not have any expectations.') +``` + +__`returns`: `itself`__ + +### dx() +Define the dynamic `x` value of the element, much like a html element with `position:relative` and `left` defined: + +```javascript +tspan.dx(30) +``` + +__`returns`: `itself`__ + +### dy() +Define the dynamic `y` value of the element, much like a html element with `position:relative` and `top` defined: + +```javascript +tspan.dy(30) +``` + +__`returns`: `itself`__ + +### newLine() +The `newLine()` is a convenience method for adding a new line with a `dy` attribute using the current "leading": + +```javascript +var text = draw.text(function(add) { + add.tspan('Lorem ipsum dolor sit amet ').newLine() + add.tspan('consectetur').fill('#f06') + add.tspan('.') + add.tspan('Cras sodales imperdiet auctor.').newLine().dx(20) + add.tspan('Nunc ultrices lectus at erat').newLine() + add.tspan('dictum pharetra elementum ante').newLine() +}) +``` + +__`returns`: `itself`__ + +### clear() +Clear all the contents of the called tspan element: + +```javascript +tspan.clear() +``` + +__`returns`: `itself`__ + +### length() +Gets the total computed text length: + +```javascript +tspan.length() +``` + +__`returns`: `number`__ + +## TextPath +A nice feature in svg is the ability to run text along a path: + +```javascript +var text = draw.text(function(add) { + add.tspan('We go ') + add.tspan('up').fill('#f09').dy(-40) + add.tspan(', then we go down, then up again').dy(40) +}) +text + .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') + .font({ size: 42.5, family: 'Verdana' }) +``` + +When calling the `path()` method on a text element, the text element is mutated into an intermediate between a text and a path element. From that point on the text element will also feature a `plot()` method to update the path: + +```javascript +text.plot('M 300 500 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100') +``` + +Attributes specific to the `` element can be applied to the textPath instance itself: + +```javascript +text.textPath().attr('startOffset', 0.5) +``` + +And they can be animated as well of course: + +```javascript +text.textPath().animate(3000).attr('startOffset', 0.8) +``` + +__`returns`: `SVG.TextPath`__ + +_Javascript inheritance stack: `SVG.TextPath` < `SVG.Element`_ + +### textPath() +Referencing the textPath node directly: + +```javascript +var textPath = text.textPath() +``` + +__`returns`: `SVG.TextPath`__ + +### track() +Referencing the linked path element directly: + +```javascript +var path = text.track() +``` + +__`returns`: `SVG.Path`__ + +## Use +The use element simply emulates another existing element. Any changes on the master element will be reflected on all the `use` instances. The usage of `use()` is very straightforward: + +```javascript +var rect = draw.rect(100, 100).fill('#f09') +var use = draw.use(rect).move(200, 200) +``` + +In the case of the example above two rects will appear on the svg drawing, the original and the `use` instance. In some cases you might want to hide the original element. the best way to do this is to create the original element in the defs node: + +```javascript +var rect = draw.defs().rect(100, 100).fill('#f09') +var use = draw.use(rect).move(200, 200) +``` + +In this way the rect element acts as a library element. You can edit it but it won't be rendered. + +Another way is to point an external SVG file, just specified the element `id` and path to file. + +```javascript +var use = draw.use('elementId', 'path/to/file.svg') +``` + +This way is usefull when you have complex images already created. +Note that, for external images (outside your domain) it may be necessary to load the file with XHR. + +__`returns`: `SVG.Use`__ + +_Javascript inheritance stack: `SVG.Use` < `SVG.Shape` < `SVG.Element`_ + +## Symbol +Not unlike the `group` element, the `symbol` element is a container element. The only difference between symbols and groups is that symbols are not rendered. Therefore a `symbol` element is ideal in combination with the `use` element: + +```javascript +var symbol = draw.symbol() +symbol.rect(100, 100).fill('#f09') + +var use = draw.use(symbol).move(200, 200) +``` + +__`returns`: `SVG.Bare`__ + +_Javascript inheritance stack: `SVG.Bare` < `SVG.Element` [with a shallow inheritance from `SVG.Parent`]_ + +## Bare +For all SVG elements that are not described by SVG.js, the `SVG.Bare` class comes in handy. This class inherits directly from `SVG.Element` and makes it possible to add custom methods in a separate namespace without polluting the main `SVG.Element` namespace. Consider it your personal playground. + +### element() +The `SVG.Bare` class can be instantiated with the `element()` method on any parent element: + +```javascript +var element = draw.element('title') +``` +The string value passed as the first argument is the node name that should be generated. + +Additionally any existing class name can be passed as the second argument to define from which class the element should inherit: + +```javascript +var element = draw.element('symbol', SVG.Parent) +``` + +This gives you as the user a lot of power. But remember, with great power comes great responsibility. + +__`returns`: `SVG.Bare`__ + +### words() +The `SVG.Bare` instance carries an additional method to add plain text: + +```javascript +var element = draw.element('title').words('This is a title.') +//-> This is a title. +``` + +__`returns`: `itself`__ + +## Referencing elements + +### By id +If you want to get an element created by SVG.js by its id, you can use the `SVG.get()` method: + +```javascript +var element = SVG.get('my_element') + +element.fill('#f06') +``` + +### Using CSS selectors +There are two ways to select elements using CSS selectors. + +The first is to search globally. This will search in all svg elements in a document and return them in an instance of `SVG.Set`: + +```javascript +var elements = SVG.select('rect.my-class').fill('#f06') +``` + +The second is to search within a parent element: + +```javascript +var elements = group.select('rect.my-class').fill('#f06') +``` + +### Using jQuery or Zepto +Another way is to use [jQuery](http://jquery.com/) or [Zepto](http://zeptojs.com/). Here is an example: + +```javascript +// add elements +var draw = SVG('drawing') +var group = draw.group().addClass('my-group') +var rect = group.rect(100,100).addClass('my-element') +var circle = group.circle(100).addClass('my-element').move(100, 100) + +// get elements in group +var elements = $('#drawing g.my-group .my-element').each(function() { + this.instance.animate().fill('#f09') +}) +``` + +## Circular reference +Every element instance within SVG.js has a reference to the actual `node`: + +### node +```javascript +element.node +``` +__`returns`: `node`__ + +### native() +The same can be achieved with the `native()` method: +```javascript +element.native() +``` +__`returns`: `node`__ + + +### instance +Similar, the node carries a reference to the SVG.js `instance`: + +```javascript +node.instance +``` +__`returns`: `element`__ + +## Parent reference +Every element has a reference to its parent with the `parent()` method: + +### parent() + +```javascript +element.parent() +``` + +__`returns`: `element`__ + +Alternatively a class or css selector can be passed as the first argument: + +```javascript +var draw = SVG('drawing') +var nested = draw.nested().addClass('test') +var group = nested.group() +var rect = group.rect(100, 100) + +rect.parent() //-> returns group +rect.parent(SVG.Doc) //-> returns draw +rect.parent(SVG.Nested) //-> returns nested +rect.parent(SVG.G) //-> returns group +rect.parent('.test') //-> returns nested +``` + +__`returns`: `element`__ + +Even the main svg document: + +```javascript +var draw = SVG('drawing') + +draw.parent() //-> returns the wrappig html element with id 'drawing' +``` + +__`returns`: `HTMLNode`__ + + +### doc() +For retrieving the root svg you can use `doc()` + +```javascript +var draw = SVG('drawing') +var rect = draw.rect(100, 100) + +rect.doc() //-> returns draw +``` + +### parents() +To get all ancestors of the element filtered by type or css selector (see `parent()` method) + +```javascript +var group1 = draw.group().addClass('test') + , group2 = group1.group() + , rect = group2.rect(100,100) + +rect.parents() // returns [group1, group2, draw] +rect.parents('.test') // returns [group1] +rect.parents(SVG.G) // returns [group1, group2] +``` + +__`returns`: `Array`__ + +## Child references + +### first() +To get the first child of a parent element: + +```javascript +draw.first() +``` +__`returns`: `element`__ + +### last() +To get the last child of a parent element: + +```javascript +draw.last() +``` +__`returns`: `element`__ + +### children() +An array of all children will can be retreives with the `children` method: + +```javascript +draw.children() +``` +__`returns`: `array`__ + +### each() +The `each()` allows you to iterate over the all children of a parent element: + +```javascript +draw.each(function(i, children) { + this.fill({ color: '#f06' }) +}) +``` + +Deep traversing is also possible by passing true as the second argument: + +```javascript +// draw.each(block, deep) +draw.each(function(i, children) { + this.fill({ color: '#f06' }) +}, true) +``` + +Note that `this` refers to the current child element. + +__`returns`: `itself`__ + +### has() +Checking the existence of an element within a parent: + +```javascript +var rect = draw.rect(100, 50) +var group = draw.group() + +draw.has(rect) //-> returns true +group.has(rect) //-> returns false +``` +__`returns`: `boolean`__ + +### index() +Returns the index of given element and returns -1 when it is not a child: + +```javascript +var rect = draw.rect(100, 50) +var group = draw.group() + +draw.index(rect) //-> returns 0 +group.index(rect) //-> returns -1 +``` +__`returns`: `number`__ + +### get() +Get an element on a given position in the children array: + +```javascript +var rect = draw.rect(20, 30) +var circle = draw.circle(50) + +draw.get(0) //-> returns rect +draw.get(1) //-> returns circle +``` +__`returns`: `element`__ + +### clear() +To remove all elements from a parent element: + +```javascript +draw.clear() +``` +__`returns`: `itself`__ + + +## Import / export SVG + +### svg() +Exporting the full generated SVG, or a part of it, can be done with the `svg()` method: + +```javascript +draw.svg() +``` + +Exporting works on all elements. + +Importing is done with the same method: + +```javascript +draw.svg('') +``` + +Importing works on any element that inherits from `SVG.Parent`, which is basically every element that can contain other elements. + +`getter`__`returns`: `string`__ + +`setter`__`returns`: `itself`__ + +## Attributes and styles + +### attr() +You can get and set an element's attributes directly using `attr()`. + +Get a single attribute: +```javascript +rect.attr('x') +``` + +Set a single attribute: +```javascript +rect.attr('x', 50) +``` + +Set multiple attributes at once: +```javascript +rect.attr({ + fill: '#f06' +, 'fill-opacity': 0.5 +, stroke: '#000' +, 'stroke-width': 10 +}) +``` + +Set an attribute with a namespace: +```javascript +rect.attr('x', 50, 'http://www.w3.org/2000/svg') +``` + +Explicitly remove an attribute: +```javascript +rect.attr('fill', null) +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + + +### style() +With the `style()` method the `style` attribute can be managed like attributes with `attr`: + +```javascript +rect.style('cursor', 'pointer') +``` + +Multiple styles can be set at once using an object: + +```javascript +rect.style({ cursor: 'pointer', fill: '#f03' }) +``` + +Or a css string: + +```javascript +rect.style('cursor:pointer;fill:#f03;') +``` + +Similar to `attr()` the `style()` method can also act as a getter: + +```javascript +rect.style('cursor') +// => pointer +``` + +Or even a full getter: + +```javascript +rect.style() +// => 'cursor:pointer;fill:#f03;' +``` + +Explicitly deleting individual style definitions works the same as with the `attr()` method: + +```javascript +rect.style('cursor', null) +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### fill() +The `fill()` method is a pretty alternative to the `attr()` method: + +```javascript +rect.fill({ color: '#f06', opacity: 0.6 }) +``` + +A single hex string will work as well: + +```javascript +rect.fill('#f06') +``` + +Last but not least, you can also use an image as fill, simply by passing an image url: + +```javascript +rect.fill('images/shade.jpg') +``` + +Or if you want more control over the size of the image, you can pass an image instance as well: + +```javascript +rect.fill(draw.image('images/shade.jpg', 20, 20)) +``` + +__`returns`: `itself`__ + +### stroke() +The `stroke()` method is similar to `fill()`: + +```javascript +rect.stroke({ color: '#f06', opacity: 0.6, width: 5 }) +``` + +Like fill, a single hex string will work as well: + +```javascript +rect.stroke('#f06') +``` + +Not unlike the `fill()` method, you can also use an image as stroke, simply by passing an image url: + +```javascript +rect.stroke('images/shade.jpg') +``` + +Or if you want more control over the size of the image, you can pass an image instance as well: + +```javascript +rect.stroke(draw.image('images/shade.jpg', 20, 20)) +``` + +__`returns`: `itself`__ + +### opacity() +To set the overall opacity of an element: + +```javascript +rect.opacity(0.5) +``` + +__`returns`: `itself`__ + +### reference() +In cases where an element is linked to another element through an attribute, the linked element instance can be fetched with the `reference()` method. The only thing required is the attribute name: + +```javascript +use.reference('href') //-> returns used element instance +// or +rect.reference('fill') //-> returns gradient or pattern instance for example +// or +circle.reference('clip-path') //-> returns clip instance +``` + +### hide() +Hide element: + +```javascript +rect.hide() +``` + +__`returns`: `itself`__ + +### show() +Show element: + +```javascript +rect.show() +``` + +__`returns`: `itself`__ + +### visible() +To check if the element is visible: + +```javascript +rect.visible() +``` + +__`returns`: `boolean`__ + +## Classes + +### classes() +Fetches the css classes for the node as an array: + +```javascript +rect.classes() +``` + +`getter`__`returns`: `array`__ + +### hasClass() +Test the presence of a given css class: + +```javascript +rect.hasClass('purple-rain') +``` + +`getter`__`returns`: `boolean`__ + +### addClass() +Adds a given css class: + +```javascript +rect.addClass('pink-flower') +``` + +`setter`__`returns`: `itself`__ + +### removeClass() +Removes a given css class: + +```javascript +rect.removeClass('pink-flower') +``` + +`setter`__`returns`: `itself`__ + +### toggleClass() +Toggles a given css class: + +```javascript +rect.toggleClass('pink-flower') +``` + +`setter`__`returns`: `itself`__ + +## Size and position + +While positioning an element by directly setting its attributes works only if the attributes are used natively by that type of element, the positioning methods described below are much more convenient as they work for all element types. + +For example, the following code works because each element is positioned by setting native attributes: + +```javascript +rect.attr({ x: 20, y: 60 }) +circle.attr({ cx: 50, cy: 40 }) +``` + +The `rect` will be moved by its upper left corner to the new coordinates, and the `circle` will be moved by its center. However, trying to move a `circle` by its 'corner' or a `rect` by its center in this way will fail. The following lines will get silently ignored as the attributes that are addressed are not natively used by the element setting them: + +```javascript +rect.attr({ cx: 20, cy: 60 }) +circle.attr({ x: 50, y: 40 }) +``` + +However, the positioning methods detailed below will work for all element types, regardless of whether the attributes being addressed are native to the type. So, unlike the lines above, these lines work just fine: + +```javascript +rect.cx(20).cy(60) +circle.x(50).y(40) +``` + +It is important to note, though, that these methods are only intended for use with user (unitless) coordinates. If, for example, an element has its size set via percentages or other units, the positioning methods that address its native attributes will most likely still work, but the ones that address non-native attributes will give unexpected results -- as both getters and setters! + + +### size() +Set the size of an element to a given `width` and `height`: + +```javascript +rect.size(200, 300) +``` + +Proportional resizing is also possible by leaving out `height`: + +```javascript +rect.size(200) +``` + +Or by passing `null` as the value for `width`: + +```javascript +rect.size(null, 200) +``` + +As with positioning, the size of an element could be set by using `attr()`. But because every type of element is handles its size differently the `size()` method is much more convenient. + +There is one exception though: for `SVG.Text` elements, this method takes only one argument and applies the given value to the `font-size` attribute. + +__`returns`: `itself`__ + +### width() +Set the width of an element: + +```javascript +rect.width(200) +``` + +This method also acts as a getter: + +```javascript +rect.width() //-> returns 200 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### height() +Set the height of an element: + +```javascript +rect.height(325) +``` + +This method also acts as a getter: + +```javascript +rect.height() //-> returns 325 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### radius() +Circles, ellipses, and rects may use the `radius()` method. On rects, it defines rounded corners. + +For a circle, the argument sets the `r` attribute. + +```javascript +circle.radius(10) +``` + +For ellipses and rects, pass two arguments to set the `rx` and `ry` attributes individually. Or, pass a single argument, to make the two attributes equal. + +```javascript +ellipse.radius(10, 20) +rect.radius(5) +``` + +_This functionality requires the sugar.js module which is included in the default distribution._ + +__`returns`: `itself`__ + +### move() +Move the element by its upper left corner to a given `x` and `y` position: + +```javascript +rect.move(200, 350) +``` + +__`returns`: `itself`__ + +### x() +Move the element by its upper left corner along the x-axis only: + +```javascript +rect.x(200) +``` + +Without an argument the `x()` method serves as a getter as well: + +```javascript +rect.x() //-> returns 200 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### y() +Move the element by its upper left corner along the y-axis only: + +```javascript +rect.y(350) +``` + +Without an argument the `y()` method serves as a getter as well: + +```javascript +rect.y() //-> returns 350 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### center() +Move the element by its center to a given `cx` and `cy` position: + +```javascript +rect.center(150, 150) +``` + +__`returns`: `itself`__ + +### cx() +Move the element by its center in the `x` direction only: + +```javascript +rect.cx(200) +``` + +Without an argument the `cx()` method serves as a getter as well: + +```javascript +rect.cx() //-> returns 200 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### cy() +Move the element by its center in the `y` direction only: + +```javascript +rect.cy(350) +``` + +Without an argument the `cy()` method serves as a getter as well: + +```javascript +rect.cy() //-> returns 350 +``` + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### dmove() +Shift the element in both the `x` and `y` directions relative to its current position: + +```javascript +rect.dmove(10, 30) +``` + +__`returns`: `itself`__ + +### dx() +Shift the element in the `x` direction relative to its current position: + +```javascript +rect.dx(200) +``` + +__`returns`: `itself`__ + +### dy() +Shift the element in the `y` direction relative to its current position: + +```javascript +rect.dy(200) +``` + +__`returns`: `itself`__ + +## Document tree manipulations + +### clone() +To make an exact copy of an element the `clone()` method comes in handy: + +```javascript +var clone = rect.clone() +``` + +__`returns`: `element`__ + +This will create a new, unlinked copy. For making a linked clone, see the [use](#use) element. + +### remove() +Removes the calling element from the svg document: + +```javascript +rect.remove() +``` + +__`returns`: `itself`__ + +### replace() +At the calling element's position in the svg document, replace the calling element with the element passed to the method. + +```javascript +rect.replace(draw.circle(100)) +``` + +__`returns`: `element`__ + + +### add() +Sets the calling element as the parent node of the argument. Returns the parent: + +```javascript +var rect = draw.rect(100, 100) +var group = draw.group() + +group.add(rect) //-> returns group +``` + +__`returns`: `itself`__ + +### put() +Sets the calling element as the parent node of the argument. Returns the child: + +```javascript +group.put(rect) //-> returns rect +``` + +__`returns`: `element`__ + +### addTo() +Sets the calling element as a child node of the argument. Returns the child: + +```javascript +rect.addTo(group) //-> returns rect +``` + +__`returns`: `itself`__ + +### putIn() +Sets the calling element as a child node of the argument. Returns the parent: + +```javascript +rect.putIn(group) //-> returns group +``` + +__`returns`: `element`__ + +### toParent() +Moves an element to a different parent (similar to `addTo`), but without changing its visual representation. All transformations are merged and applied to the element. + +```javascript +rect.toParent(group) // looks the same as before +``` + +__`returns`: `itself`__ + +### toDoc() +Same as `toParent()` but with the root-node as parent + +__`returns`: `itself`__ + +### ungroup() / flatten() +Break up a group/container and move all the elements to a given parent node without changing their visual representations. The result is a flat svg structure, e.g. for exporting. + +```javascript +// ungroups all elements in this group recursively and places them into the given parent +// (default: parent container of the calling element) +group.ungroup(parent, depth) + +// call it on the whole document to get a flat svg structure +drawing.ungroup() + +// breaks up the group and places all elements in drawing +group.ungroup(drawing) + +// breaks up all groups until it reaches a depth of 3 +drawing.ungroup(null, 3) + +// flat and export svg +var svgString = drawing.ungroup().svg() +``` + +__`returns`: `itself`__ + + +## Transforms + +### transform() + +The `transform()` method acts as a full getter without an argument: + +```javascript +element.transform() +``` + +The returned __`object`__ contains the following values: + +- `x` (translation on the x-axis) +- `y` (translation on the y-axis) +- `skewX` (calculated skew on x-axis) +- `skewY` (calculated skew on y-axis) +- `scaleX` (calculated scale on x-axis) +- `scaleY` (calculated scale on y-axis) +- `rotation` (calculated rotation) +- `cx` (last used rotation centre on x-axis) +- `cy` (last used rotation centre on y-axis) + +Additionally a string value for the required property can be passed: + +```javascript +element.transform('rotation') +``` + +In this case the returned value is a __`number`__. + + +As a setter it has two ways of working. By default transformations are absolute. For example, if you call: + +```javascript +element.transform({ rotation: 125 }).transform({ rotation: 37.5 }) +``` + +The resulting rotation will be `37.5` and not the sum of the two transformations. But if that's what you want there is a way out by adding the `relative` parameter. That would be: + + +```javascript +element.transform({ rotation: 125 }).transform({ rotation: 37.5, relative: true }) +``` + +Alternatively a relative flag can be passed as the second argument: + +```javascript +element.transform({ rotation: 125 }).transform({ rotation: 37.5 }, true) +``` + +Available transformations are: + +- `rotation` with optional `cx` and `cy` +- `scale` with optional `cx` and `cy` +- `scaleX` with optional `cx` and `cy` +- `scaleY` with optional `cx` and `cy` +- `skewX` with optional `cx` and `cy` +- `skewY` with optional `cx` and `cy` +- `x` +- `y` +- `a`, `b`, `c`, `d`, `e` and/or `f` or an existing matrix instead of the object + +`getter`__`returns`: `value`__ + +`setter`__`returns`: `itself`__ + +### rotate() +The `rotate()` method will automatically rotate elements according to the center of the element: + +```javascript +// rotate(degrees) +rect.rotate(45) +``` + +Although you can also define a specific rotation point: + +```javascript +// rotate(degrees, cx, cy) +rect.rotate(45, 50, 50) +``` + +__`returns`: `itself`__ + +### skew() +The `skew()` method will take an `x` and `y` value: + +```javascript +// skew(x, y) +rect.skew(0, 45) +``` + +__`returns`: `itself`__ + +### scale() +The `scale()` method will take an `x` and `y` value: + +```javascript +// scale(x, y) +rect.scale(0.5, -1) +``` + +__`returns`: `itself`__ + +### translate() +The `translate()` method will take an `x` and `y` value: + +```javascript +// translate(x, y) +rect.translate(0.5, -1) +``` + + +## Geometry + +### viewbox() + +The `viewBox` attribute of an `` element can be managed with the `viewbox()` method. When supplied with four arguments it will act as a setter: + +```javascript +draw.viewbox(0, 0, 297, 210) +``` + +Alternatively you can also supply an object as the first argument: + +```javascript +draw.viewbox({ x: 0, y: 0, width: 297, height: 210 }) +``` + +Without any arguments an instance of `SVG.ViewBox` will be returned: + +```javascript +var box = draw.viewbox() +``` + +But the best thing about the `viewbox()` method is that you can get the zoom of the viewbox: + +```javascript +var box = draw.viewbox() +var zoom = box.zoom +``` + +If the size of the viewbox equals the size of the svg drawing, the zoom value will be 1. + +`getter`__`returns`: `SVG.ViewBox`__ + +`setter`__`returns`: `itself`__ + +### bbox() +Get the bounding box of an element. This is a wrapper for the native `getBBox()` method but adds more values: + +```javascript +path.bbox() +``` + +This will return an instance of `SVG.BBox` containing the following values: + +- `width` (value from native `getBBox`) +- `height` (value from native `getBBox`) +- `w` (shorthand for `width`) +- `h` (shorthand for `height`) +- `x` (value from native `getBBox`) +- `y` (value from native `getBBox`) +- `cx` (center `x` of the bounding box) +- `cy` (center `y` of the bounding box) +- `x2` (lower right `x` of the bounding box) +- `y2` (lower right `y` of the bounding box) + +The `SVG.BBox` has one other nifty little feature, enter the `merge()` method. With `merge()` two `SVG.BBox` instances can be merged into one new instance, basically being the bounding box of the two original bounding boxes: + +```javascript +var box1 = draw.rect(100,100).move(50,50) +var box2 = draw.rect(100,100).move(200,200) +var box3 = box1.merge(box2) +``` + +__`returns`: `SVG.BBox`__ + +### tbox() +Where `bbox()` returns a bounding box mindless of any transformations, the `tbox()` method does take transformations into account. So any translation or scale will be applied to the resulting values to get closer to the actual visual representation: + +```javascript +path.tbox() +``` + +This will return an instance of `SVG.TBox` containing the following values: + +- `width` (value from native getBBox influenced by the `scaleX` of the current matrix) +- `height` (value from native getBBox influenced by the `scaleY` of the current matrix) +- `w` (shorthand for `width`) +- `h` (shorthand for `height`) +- `x` (value from native getBBox influenced by the `x` of the current matrix) +- `y` (value from native getBBox influenced by the `y` of the current matrix) +- `cx` (center `x` of the bounding box) +- `cy` (center `y` of the bounding box) +- `x2` (lower right `x` of the bounding box) +- `y2` (lower right `y` of the bounding box) + +Note that the rotation of the element will not be added to the calculation. + +__`returns`: `SVG.TBox`__ + +### rbox() +Is similar to `bbox()` but will give you the box around the exact visual representation of the element, taking all transformations into account. + +```javascript +path.rbox() +``` + +This will return an instance of `SVG.RBox` containing the following values: + +- `width` (the actual visual width) +- `height` (the actual visual height) +- `w` (shorthand for `width`) +- `h` (shorthand for `height`) +- `x` (the actual visual position on the x-axis) +- `y` (the actual visual position on the y-axis) +- `cx` (center `x` of the bounding box) +- `cy` (center `y` of the bounding box) +- `x2` (lower right `x` of the bounding box) +- `y2` (lower right `y` of the bounding box) + +__Important__: Mozilla browsers include stroke widths where other browsers do not. Therefore the resulting box might be different in Mozilla browsers. It is very hard to modify this behavior so for the time being this is an inconvenience we have to live with. + +__`returns`: `SVG.RBox`__ + +### ctm() +Retreives the current transform matrix of the element relative to the nearest viewport parent: + +```javascript +path.ctm() +``` + +__`returns`: `SVG.Matrix`__ + +### screenCTM() +Retreives the current transform matrix of the element relative to the screen: + +```javascript +path.screenCTM() +``` + +__`returns`: `SVG.Matrix`__ + +### matrixify() +Merges all transformations of the element into one single matrix which is returned + +```javascript +path.matrixify() +``` + +__`returns`: `SVG.Matrix`__ + + +### point() +Transforms a point from screen coordinates to the elements coordinate system + +```javascript +// e is some mouseevent +var point = path.point(e.screeX, e.screenY) // {x, y} +``` + +__`returns`: `SVG.Point`__ + + +### inside() +To check if a given point is inside the bounding box of an element you can use the `inside()` method: + +```javascript +var rect = draw.rect(100, 100).move(50, 50) + +rect.inside(25, 30) //-> returns false +rect.inside(60, 70) //-> returns true +``` + +Note: the `x` and `y` positions are tested against the relative position of the element. Any offset on the parent element is not taken into account. + +__`returns`: `boolean`__ + +### length() +Get the total length of a path element: + +```javascript +var length = path.length() +``` + +__`returns`: `number`__ + +### pointAt() +Get point on a path at given length: + +```javascript +var point = path.pointAt(105) //-> returns { x : 96.88497924804688, y : 58.062747955322266 } +``` + +__`returns`: `object`__ + + +## Animating elements + +### Animatable method chain +Note that the `animate()` method will not return the targeted element but an instance of SVG.FX which will take the following methods: + +Of course `attr()`: +```javascript +rect.animate().attr({ fill: '#f03' }) +``` + +The `x()`, `y()` and `move()` methods: +```javascript +rect.animate().move(100, 100) +``` + +And the `cx()`, `cy()` and `center()` methods: +```javascript +rect.animate().center(200, 200) +``` + +If you include the sugar.js module, `fill()`, `stroke()`, `rotate()`, `skew()`, `scale()`, `matrix()`, `opacity()`, `radius()` will be available as well: +```javascript +rect.animate().rotate(45).skew(25, 0) +``` + +You can also animate non-numeric unit values using the `attr()` method: +```javascript +rect.attr('x', '10%').animate().attr('x', '50%') +``` + +### easing +All available ease types are: + +- `<>`: ease in and out +- `>`: ease out +- `<`: ease in +- `-`: linear +- `=`: external control +- a function + +For the latter, here is an example of the default `<>` function: + +```javascript +function(pos) { return (-Math.cos(pos * Math.PI) / 2) + 0.5 } +``` + +For more easing equations, have a look at the [svg.easing.js](https://github.com/wout/svg.easing.js) plugin. + +### animate() +Animating elements is very much the same as manipulating elements, the only difference is you have to include the `animate()` method: + +```javascript +rect.animate().move(150, 150) +``` + +The `animate()` method will take three arguments. The first is `duration`, the second `ease` and the third `delay`: + +```javascript +rect.animate(2000, '>', 1000).attr({ fill: '#f03' }) +``` + +Alternatively you can pass an object as the first argument: + +```javascript +rect.animate({ ease: '<', delay: '1.5s' }).attr({ fill: '#f03' }) +``` + +By default `duration` will be set to `1000`, `ease` will be set to `<>`. + +__`returns`: `SVG.FX`__ + + +### pause() +Pausing an animations is fairly straightforward: + +```javascript +rect.animate().move(200, 200) + +rect.mouseover(function() { this.pause() }) +``` + +__`returns`: `itself`__ + +### play() +Will start playing a paused animation: + +```javascript +rect.animate().move(200, 200) + +rect.mouseover(function() { this.pause() }) +rect.mouseout(function() { this.play() }) +``` +__`returns`: `itself`__ + +### stop() +Animations can be stopped in two ways. + +By calling the `stop()` method: +```javascript +rect.animate().move(200, 200) + +rect.stop() +``` + +Or by invoking another animation: +```javascript +rect.animate().move(200, 200) + +rect.animate().center(200, 200) +``` + +By calling `stop()`, the transition is left at its current position. By passing `true` as the first argument to `stop()`, the animation will be fulfilled instantly: + +```javascript +rect.animate().move(200, 200) + +rect.stop(true) +``` + +Stopping an animation is irreversable. + +__`returns`: `itself`__ + +### during() +If you want to perform your own actions during the animations you can use the `during()` method: + +```javascript +var position + , from = 100 + , to = 300 + +rect.animate(3000).move(100, 100).during(function(pos) { + position = from + (to - from) * pos +}) +``` +Note that `pos` is `0` in the beginning of the animation and `1` at the end of the animation. + +To make things easier a morphing function is passed as the second argument. This function accepts a `from` and `to` value as the first and second argument and they can be a number, unit or hex color: + +```javascript +var ellipse = draw.ellipse(100, 100).attr('cx', '20%').fill('#333') + +rect.animate(3000).move(100, 100).during(function(pos, morph) { + // numeric values + ellipse.size(morph(100, 200), morph(100, 50)) + + // unit strings + ellipse.attr('cx', morph('20%', '80%')) + + // hex color strings + ellipse.fill(morph('#333', '#ff0066')) +}) +``` + +__`returns`: `SVG.FX`__ + +### loop() +By default the `loop()` method creates and eternal loop: + +```javascript +rect.animate(3000).move(100, 100).loop() +``` + +But the loop can also be a predefined number of times: + +```javascript +rect.animate(3000).move(100, 100).loop(3) +``` + +Loops go from beginning to end and start over again (`0->1.0->1.0->1.`). + +There is also a reverse flag that should be passed as the second argument: + +```javascript +rect.animate(3000).move(100, 100).loop(3, true) +``` + +Loops will then be completely reversed before starting over (`0->1->0->1->0->1.`). + +__`returns`: `SVG.FX`__ + +### after() +Finally, you can add callback methods using `after()`: + +```javascript +rect.animate(3000).move(100, 100).after(function() { + this.animate().attr({ fill: '#f06' }) +}) +``` + +Note that the `after()` method will never be called if the animation is looping eternally. + +__`returns`: `SVG.FX`__ + +### at() +Say you want to control the position of an animation with an external event, then the `at()` method will proove very useful: + +```javascript +var animation = draw.rect(100, 100).move(50, 50).animate('=').move(200, 200) + +document.onmousemove = function(event) { + animation.at(event.clientX / 1000) +} +``` + +In order to be able to use the `at()` method, the duration of the animation should be set to `'='`. The value passed as the first argument of `at()` should be a number between `0` and `1`, `0` being the beginning of the animation and `1` being the end. Note that any values below `0` and above `1` will be normalized. + +_This functionality requires the fx.js module which is included in the default distribution._ + +__`returns`: `SVG.FX`__ + + +### situation +The current situation of an animation is stored in the `situation` object: + +```javascript +rect.animate(3000).move(100, 100) +rect.fx.situation //-> everything is in here +``` + +Available values are: + +- `start` (start time as a number in milliseconds) +- `play` (animation playing or not; `true` or `false`) +- `pause` (time when the animation was last paused) +- `duration` (the chosen duration of the animation) +- `ease` (the chosen easing calculation) +- `finish` (start + duration) +- `loop` (the current loop; counting down if a number; `true`, `false` or a number) +- `loops` (if a number, the total number loops; `true`, `false` or a number) +- `reverse` (whether or not the loop should be reversed; `true` or `false`) +- `reversing` (`true` if the loop is currently reversing, otherwise `false`) +- `during` (the function that should be called on every keyframe) +- `after` (the function that should be called after completion) + + +## Masking elements + +### maskWith() +The easiest way to mask is to use a single element: + +```javascript +var ellipse = draw.ellipse(80, 40).move(10, 10).fill({ color: '#fff' }) + +rect.maskWith(ellipse) +``` + +__`returns`: `itself`__ + +### mask() +But you can also use multiple elements: + +```javascript +var ellipse = draw.ellipse(80, 40).move(10, 10).fill({ color: '#fff' }) +var text = draw.text('SVG.JS').move(10, 10).font({ size: 36 }).fill({ color: '#fff' }) + +var mask = draw.mask().add(text).add(ellipse) + +rect.maskWith(mask) +``` + +If you want the masked object to be rendered at 100% you need to set the fill color of the masking object to white. But you might also want to use a gradient: + +```javascript +var gradient = draw.gradient('linear', function(stop) { + stop.at({ offset: 0, color: '#000' }) + stop.at({ offset: 1, color: '#fff' }) +}) + +var ellipse = draw.ellipse(80, 40).move(10, 10).fill({ color: gradient }) + +rect.maskWith(ellipse) +``` + +__`returns`: `SVG.Mask`__ + +### unmask() +Unmasking the elements can be done with the `unmask()` method: + +```javascript +rect.unmask() +``` + +The `unmask()` method returns the masking element. + +__`returns`: `itself`__ + +### remove() +Removing the mask alltogether will also `unmask()` all masked elements as well: + +```javascript +mask.remove() +``` + +__`returns`: `itself`__ + +### masker +For your convenience, the masking element is also referenced in the masked element. This can be useful in case you want to change the mask: + +```javascript +rect.masker.fill('#fff') +``` + +_This functionality requires the mask.js module which is included in the default distribution._ + + +## Clipping elements +Clipping elements works exactly the same as masking elements. The only difference is that clipped elements will adopt the geometry of the clipping element. Therefore events are only triggered when entering the clipping element whereas with masks the masked element triggers the event. Another difference is that masks can define opacity with their fill color and clipPaths don't. + +### clipWith() +```javascript +var ellipse = draw.ellipse(80, 40).move(10, 10) + +rect.clipWith(ellipse) +``` + +__`returns`: `itself`__ + +### clip() +Clip multiple elements: + +```javascript +var ellipse = draw.ellipse(80, 40).move(10, 10) +var text = draw.text('SVG.JS').move(10, 10).font({ size: 36 }) + +var clip = draw.clip().add(text).add(ellipse) + +rect.clipWith(clip) +``` + +__`returns`: `SVG.ClipPath`__ + +### unclip() +Unclipping the elements can be done with the `unclip()` method: + +```javascript +rect.unclip() +``` + +__`returns`: `itself`__ + +### remove() +Removing the clip alltogether will also `unclip()` all clipped elements as well: + +```javascript +clip.remove() +``` + +__`returns`: `itself`__ + +### clipper +For your convenience, the clipping element is also referenced in the clipped element. This can be useful in case you want to change the clipPath: + +```javascript +rect.clipper.move(10, 10) +``` + +_This functionality requires the clip.js module which is included in the default distribution._ + + +## Arranging elements +You can arrange elements within their parent SVG document using the following methods. + +### front() +Move element to the front: + +```javascript +rect.front() +``` + +__`returns`: `itself`__ + +### back() +Move element to the back: + +```javascript +rect.back() +``` + +__`returns`: `itself`__ + +### forward() +Move element one step forward: + +```javascript +rect.forward() +``` + +__`returns`: `itself`__ + +### backward() +Move element one step backward: + +```javascript +rect.backward() +``` + +__`returns`: `itself`__ + +### siblings() +The arrange.js module brings some additional methods. To get all siblings of rect, including rect itself: + +```javascript +rect.siblings() +``` + +__`returns`: `array`__ + +### position() +Get the position (a number) of rect between its siblings: + +```javascript +rect.position() +``` + +__`returns`: `number`__ + +### next() +Get the next sibling: + +```javascript +rect.next() +``` + +__`returns`: `element`__ + +### previous() +Get the previous sibling: + +```javascript +rect.previous() +``` + +__`returns`: `element`__ + +### before() +Insert an element before another: + +```javascript +// inserts circle before rect +rect.before(circle) +``` + +__`returns`: `itself`__ + +### after() +Insert an element after another: + +```javascript +// inserts circle after rect +rect.after(circle) +``` + +__`returns`: `itself`__ + +_This functionality requires the arrange.js module which is included in the default distribution._ + + +## Sets +Sets are very useful if you want to modify or animate multiple elements at once. A set will accept all the same methods accessible on individual elements, even the ones that you add with your own plugins! Creating a set is exactly as you would expect: + +```javascript +// create some elements +var rect = draw.rect(100,100) +var circle = draw.circle(100).move(100,100).fill('#f09') + +// create a set and add the elements +var set = draw.set() +set.add(rect).add(circle) + +// change the fill of all elements in the set at once +set.fill('#ff0') +``` + +A single element can be a member of many sets. Sets also don't have a structural representation, in fact they are just fancy array's. + +### add() +Add an element to a set: + +```javascript +set.add(rect) +``` + +Quite a useful feature of sets is the ability to accept multiple elements at once: + +```javascript +set.add(rect, circle) +``` + +__`returns`: `itself`__ + +### each() +Iterating over all members in a set is the same as with svg containers: + +```javascript +set.each(function(i) { + this.attr('id', 'shiny_new_id_' + i) +}) +``` + +Note that `this` refers to the current child element. + +__`returns`: `itself`__ + +### has() +Determine if an element is member of the set: + +```javascript +set.has(rect) +``` + +__`returns`: `boolean`__ + +### index() +Returns the index of a given element in the set. + +```javascript +set.index(rect) //-> -1 if element is not a member +``` + +__`returns`: `number`__ + +### get() +Gets the element at a given index: + +```javascript +set.get(1) +``` + +__`returns`: `element`__ + +### first() +Gets the first element: + +```javascript +set.first() +``` + +__`returns`: `element`__ + +### last() +Gets the last element: + +```javascript +set.last() +``` + +__`returns`: `element`__ + +### bbox() +Get the bounding box of all elements in the set: + +```javascript +set.bbox() +``` + +__`returns`: `SVG.BBox`__ + +### remove() +To remove an element from a set: + +```javascript +set.remove(rect) +``` + +__`returns`: `itself`__ + +### clear() +Or to remove all elements from a set: + +```javascript +set.clear() +``` + +__`returns`: `itself`__ + +### animate() +Sets work with animations as well: + +```javascript +set.animate(3000).fill('#ff0') +``` + +__`returns`: `SVG.SetFX`__ + + +## Gradient + +### gradient() +There are linear and radial gradients. The linear gradient can be created like this: + +```javascript +var gradient = draw.gradient('linear', function(stop) { + stop.at(0, '#333') + stop.at(1, '#fff') +}) +``` + +__`returns`: `SVG.Gradient`__ + +### at() +The `offset` and `color` parameters are required for stops, `opacity` is optional. Offset is float between 0 and 1, or a percentage value (e.g. `33%`). + +```javascript +stop.at(0, '#333') +``` + +or + +```javascript +stop.at({ offset: 0, color: '#333', opacity: 1 }) +``` + +__`returns`: `itself`__ + +### from() +To define the direction you can set from `x`, `y` and to `x`, `y`: + +```javascript +gradient.from(0, 0).to(0, 1) +``` + +The from and to values are also expressed in percent. + +__`returns`: `itself`__ + +### to() +To define the direction you can set from `x`, `y` and to `x`, `y`: + +```javascript +gradient.from(0, 0).to(0, 1) +``` + +The from and to values are also expressed in percent. + +__`returns`: `itself`__ + +### radius() +Radial gradients have a `radius()` method to define the outermost radius to where the inner color should develop: + +```javascript +var gradient = draw.gradient('radial', function(stop) { + stop.at(0, '#333') + stop.at(1, '#fff') +}) + +gradient.from(0.5, 0.5).to(0.5, 0.5).radius(0.5) +``` + +__`returns`: `itself`__ + +### update() +A gradient can also be updated afterwards: + +```javascript +gradient.update(function(stop) { + stop.at(0.1, '#333', 0.2) + stop.at(0.9, '#f03', 1) +}) +``` + +And even a single stop can be updated: + +```javascript +var s1, s2, s3 + +draw.gradient('radial', function(stop) { + s1 = stop.at(0, '#000') + s2 = stop.at(0.5, '#f03') + s3 = stop.at(1, '#066') +}) + +s1.update(0.1, '#0f0', 1) +``` + +__`returns`: `itself`__ + +### get() +The `get()` method makes it even easier to get a stop from an existing gradient: + +```javascript +var gradient = draw.gradient('radial', function(stop) { + stop.at({ offset: 0, color: '#000', opacity: 1 }) // -> first + stop.at({ offset: 0.5, color: '#f03', opacity: 1 }) // -> second + stop.at({ offset: 1, color: '#066', opacity: 1 }) // -> third +}) + +var s1 = gradient.get(0) // -> returns "first" stop +``` + +__`returns`: `SVG.Stop`__ + +### fill() +Finally, to use the gradient on an element: + +```javascript +rect.attr({ fill: gradient }) +``` + +Or: + +```javascript +rect.fill(gradient) +``` + +By passing the gradient instance as the fill on any element, the `fill()` method will be called: + +```javascript +gradient.fill() //-> returns 'url(#SvgjsGradient1234)' +``` + +[W3Schools](http://www.w3schools.com/svg/svg_grad_linear.asp) has a great example page on how +[linear gradients](http://www.w3schools.com/svg/svg_grad_linear.asp) and +[radial gradients](http://www.w3schools.com/svg/svg_grad_radial.asp) work. + +_This functionality requires the gradient.js module which is included in the default distribution._ + +__`returns`: `value`__ + + +## Pattern + +### pattern() +Creating a pattern is very similar to creating gradients: + +```javascript +var pattern = draw.pattern(20, 20, function(add) { + add.rect(20,20).fill('#f06') + add.rect(10,10) + add.rect(10,10).move(10,10) +}) +``` + +This creates a checkered pattern of 20 x 20 pixels. You can add any available element to your pattern. + +__`returns`: `SVG.Pattern`__ + + +### update() +A pattern can also be updated afterwards: + +```javascript +pattern.update(function(add) { + add.circle(15).center(10,10) +}) +``` + +__`returns`: `itself`__ + + +### fill() +Finally, to use the pattern on an element: + +```javascript +rect.attr({ fill: pattern }) +``` + +Or: + +```javascript +rect.fill(pattern) +``` + +By passing the pattern instance as the fill on any element, the `fill()` method will be called on th pattern instance: + +```javascript +pattern.fill() //-> returns 'url(#SvgjsPattern1234)' +``` + +__`returns`: `value`__ + + +## Marker + +### marker() +Markers can be added to every individual point of a `line`, `polyline`, `polygon` and `path`. There are three types of markers: `start`, `mid` and `end`. Where `start` represents the first point, `end` the last and `mid` every point in between. + +```javascript +var path = draw.path('M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100z') + +path.fill('none').stroke({ width: 1 }) + +path.marker('start', 10, 10, function(add) { + add.circle(10).fill('#f06') +}) +path.marker('mid', 10, 10, function(add) { + add.rect(10, 10) +}) +path.marker('end', 20, 20, function(add) { + add.circle(6).center(4, 5) + add.circle(6).center(4, 15) + add.circle(6).center(16, 10) + + this.fill('#0f6') +}) +``` + +The `marker()` method can be used in three ways. Firstly, a marker can be created on any container element (e.g. svg, nested, group, ...). This is useful if you plan to reuse the marker many times so it will create a marker in the defs but not show it yet: + +```javascript +var marker = draw.marker(10, 10, function(add) { + add.rect(10, 10) +}) +``` + +Secondly a marker can be created and applied directly on its target element: + +```javascript +path.marker('start', 10, 10, function(add) { + add.circle(10).fill('#f06') +}) +``` + +This will create a marker in the defs and apply it directly. Note that the first argument defines the position of the marker and that there are four arguments as opposed to three with the first example. + +Lastly, if a marker is created for reuse on a container element, it can be applied directly on the target element: + +```javascript +path.marker('mid', marker) +``` + +Finally, to get a marker instance from the target element reference: + +```javascript +path.reference('marker-end') +``` + + +### ref() +By default the `refX` and `refY` attributes of a marker are set to respectively half the `width` nd `height` values. To define the `refX` and `refY` of a marker differently: + +```javascript +marker.ref(2, 7) +``` + +__`returns`: `itself`__ + +### update() +Updating the contents of a marker will `clear()` the existing content and add the content defined in the block passed as the first argument: + +```javascript +marker.update(function(add) { + add.circle(10) +}) +``` + +__`returns`: `itself`__ + +### width() +Defines the `markerWidth` attribute: + +```javascript +marker.width(10) +``` + +__`returns`: `itself`__ + +### height() +Defines the `markerHeight` attribute: + +```javascript +marker.height(10) +``` + +__`returns`: `itself`__ + +### size() +Defines the `markerWidth` and `markerHeight` attributes: + +```javascript +marker.size(10, 10) +``` + +__`returns`: `itself`__ + + +## Data + +### Setting +The `data()` method allows you to bind arbitrary objects, strings and numbers to SVG elements: + +```javascript +rect.data('key', { value: { data: 0.3 }}) +``` + +Or set multiple values at once: + +```javascript +rect.data({ + forbidden: 'fruit' +, multiple: { + values: 'in' + , an: 'object' + } +}) +``` + +__`returns`: `itself`__ + +### Getting +Fetching the values is similar to the `attr()` method: + +```javascript +rect.data('key') +``` + +__`returns`: `itself`__ + +### Removing +Removing the data altogether: + +```javascript +rect.data('key', null) +``` + +__`returns`: `itself`__ + +### Sustaining data types +Your values will always be stored as JSON and in some cases this might not be desirable. If you want to store the value as-is, just pass true as the third argument: + +```javascript +rect.data('key', 'value', true) +``` + +__`returns`: `itself`__ + + +## Memory + +### remember() +Storing data in-memory is very much like setting attributes: + +```javascript +rect.remember('oldBBox', rect.bbox()) +``` + +Multiple values can also be remembered at once: + +```javascript +rect.remember({ + oldFill: rect.attr('fill') +, oldStroke: rect.attr('stroke') +}) +``` + +To retrieve a memory + +```javascript +rect.remember('oldBBox') +``` + +__`returns`: `itself`__ + +### forget() +Erasing a single memory: + +```javascript +rect.forget('oldBBox') +``` + +Or erasing multiple memories at once: + + +```javascript +rect.forget('oldFill', 'oldStroke') +``` + +And finally, just erasing the whole memory: + +```javascript +rect.forget() +``` + +__`returns`: `itself`__ + +## Events + +### Basic events +Events can be bound to elements as follows: + +```javascript +rect.click(function() { + this.fill({ color: '#f06' }) +}) +``` + +Removing it is quite as easy: + +```javascript +rect.click(null) +``` + +All available events are: `click`, `dblclick`, `mousedown`, `mouseup`, `mouseover`, `mouseout`, `mousemove`, `touchstart`, `touchmove`, `touchleave`, `touchend` and `touchcancel`. + +__`returns`: `itself`__ + +### Event listeners +You can also bind event listeners to elements: + +```javascript +var click = function() { + this.fill({ color: '#f06' }) +} + +rect.on('click', click) +``` + +**Note:** The context of `this` in the callback is bound to the element. You can change this context by applying your own object: + +```javascript +rect.on('click', click, window) // context of this is window +``` + +__`returns`: `itself`__ + +Unbinding events is just as easy: + +```javascript +rect.off('click', click) +``` + +Or to unbind all listeners for a given event: + +```javascript +rect.off('click') +``` + +Or even unbind all listeners for all events: + +```javascript +rect.off() +``` + +__`returns`: `itself`__ + +But there is more to event listeners. You can bind events to html elements as well: + +```javascript +SVG.on(window, 'click', click) +``` + +Obviously unbinding is practically the same: + +```javascript +SVG.off(window, 'click', click) +``` + +### Custom events +You can even use your own events. + +Just add an event listener for your event: +```javascript +rect.on('myevent', function() { + alert('ta-da!') +}) +``` + +Now you are ready to fire the event whenever you need: + +```javascript +function whenSomethingHappens() { + rect.fire('myevent') +} + +// or if you want to pass an event +function whenSomethingHappens(event) { + rect.fire(event) +} + +``` + +You can also pass some data to the event: + +```javascript +function whenSomethingHappens() { + rect.fire('myevent', {some:'data'}) +} + +rect.on('myevent', function(e) { + alert(e.detail.some) // outputs 'data' +}) +``` + +svg.js supports namespaced events following the syntax `event.namespace`. + +A namespaced event behaves like a normal event with the difference that you can remove it without touching handlers from other namespaces. + +``` +// attach +rect.on('myevent.namespace', function(e) { + // do something +}) + +// detach all handlers of namespace for myevent +rect.off('myevent.namespace') + +// detach all handlers of namespace +rect.off('.namespace') + +// detach all handlers including all namespaces +rect.off('myevent) +``` + +However you can't fire a specific namespaced event. Calling `rect.fire('myevent.namespace')` won't do anything while `rect.fire('myevent')` works and fires all attached handlers of the event + +_Important: always make sure you namespace your event to avoid conflicts. Preferably use something very specific. So `event.wicked` for example would be better than something generic like `event.svg`._ + +## Numbers + +Numbers in SVG.js have a dedicated number class to be able to process string values. Creating a new number is simple: + +```javascript +var number = new SVG.Number('78%') +number.plus('3%').toString() //-> returns '81%' +number.valueOf() //-> returns 0.81 +``` + +Operators are defined as methods on the `SVG.Number` instance. + +### plus() +Addition: + +```javascript +number.plus('3%') +``` + +__`returns`: `SVG.Number`__ + +### minus() +Subtraction: + +```javascript +number.minus('3%') +``` + +__`returns`: `SVG.Number`__ + +### times() +Multiplication: + +```javascript +number.times(2) +``` + +__`returns`: `SVG.Number`__ + +### divide() +Division: + +```javascript +number.divide('3%') +``` + +__`returns`: `SVG.Number`__ + +### to() +Change number to another unit: + +```javascript +number.to('px') +``` + +__`returns`: `SVG.Number`__ + +### morph() +Make a number morphable: + +```javascript +number.morph('11%') +``` + +__`returns`: `itself`__ + + +### at() +Get morphable number at given position: + +```javascript +var number = new SVG.Number('79%').morph('3%') +number.at(0.55).toString() //-> '37.2%' +``` + +__`returns`: `SVG.Number`__ + + +## Colors + +Svg.js has a dedicated color class handling different types of colors. Accepted values are: + +- hex string; three based (e.g. #f06) or six based (e.g. #ff0066) `new SVG.Color('#f06')` +- rgb string; e.g. rgb(255, 0, 102) `new SVG.Color('rgb(255, 0, 102)')` +- rgb object; e.g. { r: 255, g: 0, b: 102 } `new SVG.Color({ r: 255, g: 0, b: 102 })` + +Note that when working with objects is important to provide all three values every time. + +The `SVG.Color` instance has a few methods of its own. + +### toHex() +Get hex value: + +```javascript +color.toHex() //-> returns '#ff0066' +``` + +__`returns`: hex color string__ + +### toRgb() +Get rgb string value: + +```javascript +color.toRgb() //-> returns 'rgb(255,0,102)' +``` + +__`returns`: rgb color string__ + +### brightness() +Get the brightness of a color: + +```javascript +color.brightness() //-> returns 0.344 +``` + +This is the perceived brighness where `0` is black and `1` is white. + +__`returns`: `number`__ + +### morph() +Make a color morphable: + +```javascript +color.morph('#000') +``` + +__`returns`: `itself`__ + +### at() +Get morphable color at given position: + +```javascript +var color = new SVG.Color('#ff0066').morph('#000') +color.at(0.5).toHex() //-> '#7f0033' +``` + +__`returns`: `SVG.Color`__ + + +## Arrays +In SVG.js every value list string can be cast and passed as an array. This makes writing them more convenient but also adds a lot of key functionality to them. + +### SVG.Array +Is for simple, whitespace separated value strings: + +```javascript +'0.343 0.669 0.119 0 0 0.249 -0.626 0.13 0 0 0.172 0.334 0.111 0 0 0 0 0 1 0' +``` + +Can also be passed like this in a more manageable format: + +```javascript +new SVG.Array([ .343, .669, .119, 0, 0 + , .249, -.626, .130, 0, 0 + , .172, .334, .111, 0, 0 + , .000, .000, .000, 1, -0 ]) +``` + +### SVG.PointArray +Is a bit more complex and is used for polyline and polygon elements. This is a poly-point string: + +```javascript +'0,0 100,100' +``` + +The dynamic representation: + +```javascript +[ + [0, 0] +, [100, 100] +] +``` + +Precompiling it as an `SVG.PointArray`: + +```javascript +new SVG.PointArray([ + [0, 0] +, [100, 100] +]) +``` + +Note that every instance of `SVG.Polyline` and `SVG.Polygon` carries a reference to the `SVG.PointArray` instance: + +```javascript +polygon.array() //-> returns the SVG.PointArray instance +``` + +_Javascript inheritance stack: `SVG.PointArray` < `SVG.Array`_ + +### SVG.PathArray +Path arrays carry arrays representing every segment in a path string: + +```javascript +'M0 0L100 100z' +``` + +The dynamic representation: + +```javascript +[ + ['M', 0, 0] +, ['L', 100, 100] +, ['z'] +] +``` + +Precompiling it as an `SVG.PathArray`: + +```javascript +new SVG.PathArray([ + ['M', 0, 0] +, ['L', 100, 100] +, ['z'] +]) +``` + +Note that every instance of `SVG.Path` carries a reference to the `SVG.PathArray` instance: + +```javascript +path.array() //-> returns the SVG.PathArray instance +``` + +#### Syntax +The syntax for patharrays is very predictable. They are basically literal representations in the form of two dimentional arrays. + +##### Move To +Original syntax is `M0 0` or `m0 0`. The SVG.js syntax `['M',0,0]` or `['m',0,0]`. + +##### Line To +Original syntax is `L100 100` or `l100 100`. The SVG.js syntax `['L',100,100]` or `['l',100,100]`. + +##### Horizontal line +Original syntax is `H200` or `h200`. The SVG.js syntax `['H',200]` or `['h',200]`. + +##### Vertical line +Original syntax is `V300` or `v300`. The SVG.js syntax `['V',300]` or `['v',300]`. + +##### Bezier curve +Original syntax is `C20 20 40 20 50 10` or `c20 20 40 20 50 10`. The SVG.js syntax `['C',20,20,40,20,50,10]` or `['c',20,20,40,20,50,10]`. + +Or mirrored with `S`: + +Original syntax is `S40 20 50 10` or `s40 20 50 10`. The SVG.js syntax `['S',40,20,50,10]` or `['s',40,20,50,10]`. + +Or quadratic with `Q`: + +Original syntax is `Q20 20 50 10` or `q20 20 50 10`. The SVG.js syntax `['Q',20,20,50,10]` or `['q',20,20,50,10]`. + +Or a complete shortcut with `T`: + +Original syntax is `T50 10` or `t50 10`. The SVG.js syntax `['T',50,10]` or `['t',50,10]`. + +##### Arc +Original syntax is `A 30 50 0 0 1 162 163` or `a 30 50 0 0 1 162 163`. The SVG.js syntax `['A',30,50,0,0,1,162,163]` or `['a',30,50,0,0,1,162,163]`. + +##### Close +Original syntax is `Z` or `z`. The SVG.js syntax `['Z']` or `['z']`. + +The best documentation on paths can be found at https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths. + + +_Javascript inheritance stack: `SVG.PathArray` < `SVG.Array`_ + +### morph() +In order to animate array values the `morph()` method lets you pass a destination value. This can be either the string value, a plain array or an instance of the same type of SVG.js array: + +```javascript +var array = new SVG.PointArray([[0, 0], [100, 100]]) +array.morph('100,0 0,100 200,200') +``` + +This method will prepare the array ensuring both the source and destination arrays have the same length. + +In order to morph paths you need to include the [svg.pathmorphing.js](https://github.com/wout/svg.pathmorphing.js) extension. + +__`returns`: `itself`__ + +### at() +This method will morph the array to a given position between `0` and `1`. Continuing with the previous example: + +```javascript +array.at(0.27).toString() //-> returns '27,0 73,100 127,127' +``` + +Note that this method is currently not available on `SVG.PathArray` but will be soon. + +__`returns`: new instance__ + +### settle() +When morphing is done the `settle()` method will eliminate any transitional points like duplicates: + +```javascript +array.settle() +``` + +Note that this method is currently not available on `SVG.PathArray` but will be soon. + +__`returns`: `itself`__ + +### move() +Moves geometry of the array with the given `x` and `y` values: + +```javascript +var array = new SVG.PointArray([[0, 0], [100, 100]]) +array.move(33,75) +array.toString() //-> returns '33,75 133,175' +``` + +Note that this method is only available on `SVG.PointArray` and `SVG.PathArray` + +__`returns`: `itself`__ + +### size() +Resizes geometry of the array by the given `width` and `height` values: + +```javascript +var array = new SVG.PointArray([[0, 0], [100, 100]]) +array.move(100,100).size(222,333) +array.toString() //-> returns '100,100 322,433' +``` + +Note that this method is only available on `SVG.PointArray` and `SVG.PathArray` + +__`returns`: `itself`__ + +### reverse() +Reverses the order of the array: + +```javascript +var array = new SVG.PointArray([[0, 0], [100, 100]]) +array.reverse() +array.toString() //-> returns '100,100 0,0' +``` + +__`returns`: `itself`__ + +### bbox() +Gets the bounding box of the geometry of the array: + +```javascript +array.bbox() +``` + +Note that this method is only available on `SVG.PointArray` and `SVG.PathArray` + +__`returns`: `object`__ + + +## Matrices +Matrices in SVG.js have their own class `SVG.Matrix`, wrapping the native `SVGMatrix`. They add a lot of functionality like extracting transform values, matrix morphing and improvements on the native methods. + +### SVG.Matrix +In SVG.js matrices accept various values on initialization. + +Without a value: + +```javascript +var matrix = new SVG.Matrix +matrix.toString() //-> returns matrix(1,0,0,1,0,0) +``` + +Six arguments: + +```javascript +var matrix = new SVG.Matrix(1, 0, 0, 1, 100, 150) +matrix.toString() //-> returns matrix(1,0,0,1,100,150) +``` + +A string value: + +```javascript +var matrix = new SVG.Matrix('1,0,0,1,100,150') +matrix.toString() //-> returns matrix(1,0,0,1,100,150) +``` + +An object value: + +```javascript +var matrix = new SVG.Matrix({ a: 1, b: 0, c: 0, d: 1, e: 100, f: 150 }) +matrix.toString() //-> returns matrix(1,0,0,1,100,150) +``` + +A native `SVGMatrix`: + +```javascript +var svgMatrix = svgElement.getCTM() +var matrix = new SVG.Matrix(svgMatrix) +matrix.toString() //-> returns matrix(1,0,0,1,0,0) +``` + +Even an instance of `SVG.Element`: + +```javascript +var rect = draw.rect(50, 25) +var matrix = new SVG.Matrix(rect) +matrix.toString() //-> returns matrix(1,0,0,1,0,0) +``` + +### extract() +Gets the calculated values of the matrix as an object: + +```javascript +matrix.extract() +``` + +The returned object contains the following values: + +- `x` (translation on the x-axis) +- `y` (translation on the y-axis) +- `skewX` (calculated skew on x-axis) +- `skewY` (calculated skew on y-axis) +- `scaleX` (calculated scale on x-axis) +- `scaleY` (calculated scale on y-axis) +- `rotation` (calculated rotation) + +__`returns`: `object`__ + +### clone() +Returns an exact copy of the matrix: + +```javascript +matrix.clone() +``` + +__`returns`: `SVG.Matrix`__ + +### morph() +In order to animate matrices the `morph()` method lets you pass a destination matrix. This can be any value a `SVG.Matrix` would accept on initialization: + +```javascript +matrix.morph('matrix(2,0,0,2,100,150)') +``` + +__`returns`: `itself`__ + +### at() +This method will morph the matrix to a given position between `0` and `1`: + +```javascript +matrix.at(0.27) +``` + +This will only work when a destination matirx is defined using the `morph()` method. + +__`returns`: `SVG.Matrix`__ + +### multiply() +Multiplies by another given matrix: + +```javascript +matrix.matrix(matrix2) +``` + +__`returns`: `SVG.Matrix`__ + +### inverse() +Creates an inverted matix: + +```javascript +matrix.inverse() +``` + +__`returns`: `SVG.Matrix`__ + +### translate() +Translates matrix by a given x and y value: + +```javascript +matrix.translate(10, 20) +``` + +__`returns`: `SVG.Matrix`__ + +### scale() +Scales matrix uniformal with one value: + +```javascript +// scale +matrix.scale(2) +``` + +Scales matrix non-uniformal with two values: + +```javascript +// scaleX, scaleY +matrix.scale(2, 3) +``` + +Scales matrix uniformal on a given center point with three values: + +```javascript +// scale, cx, cy +matrix.scale(2, 100, 150) +``` + +Scales matrix non-uniformal on a given center point with four values: + +```javascript +// scaleX, scaleY, cx, cy +matrix.scale(2, 3, 100, 150) +``` + +__`returns`: `SVG.Matrix`__ + +### rotate() +Rotates matrix by degrees with one value given: + +```javascript +// degrees +matrix.rotate(45) +``` + +Rotates a matrix by degrees around a given point with three values: + +```javascript +// degrees, cx, cy +matrix.rotate(45, 100, 150) +``` + +__`returns`: `SVG.Matrix`__ + +### flip() +Flips matrix over a given axis: + +```javascript +matrix.flip('x') +``` + +or + +```javascript +matrix.flip('y') +``` + +By default elements are flipped over their center point. The flip axis position can be defined with the second argument: + +```javascript +matrix.flip('x', 150) +``` + +or + +```javascript +matrix.flip('y', 100) +``` + +__`returns`: `SVG.Matrix`__ + +### skew() +Skews matrix a given degrees over x and or y axis with two values: + +```javascript +// degreesX, degreesY +matrix.skew(0, 45) +``` + +Skews matrix a given degrees over x and or y axis on a given point with four values: + +```javascript +// degreesX, degreesY, cx, cy +matrix.skew(0, 45, 150, 100) +``` + +__`returns`: `SVG.Matrix`__ + +### around() +Performs a given matrix transformation around a given center point: + +```javascript +// cx, cy, matrix +matrix.around(100, 150, new SVG.Matrix().skew(0, 45)) +``` + +The matrix passed as the third argument will be used to multiply. + +__`returns`: `SVG.Matrix`__ + +### native() +Returns a native `SVGMatrix` extracted from the `SVG.Matrix` instance: + +```javascript +matrix.native() +``` + +__`returns`: `SVGMatrix`__ + +### toString() +Converts the matrix to a transform string: + +```javascript +matrix.toString() +// -> matrix(1,0,0,1,0,0) +``` + +__`returns`: `string`__ + +## Extending functionality + +### SVG.invent() +Creating your own custom elements with SVG.js is a piece of cake thanks to the `SVG.invent` function. For the sake of this example, lets "invent" a shape. We want a `rect` with rounded corners that are always proportional to the height of the element. The new shape lives in the `SVG` namespace and is called `Rounded`. Here is how we achieve that. + +```javascript +SVG.Rounded = SVG.invent({ + // Define the type of element that should be created + create: 'rect' + + // Specify from which existing class this shape inherits +, inherit: SVG.Shape + + // Add custom methods to invented shape +, extend: { + // Create method to proportionally scale the rounded corners + size: function(width, height) { + return this.attr({ + width: width + , height: height + , rx: height / 5 + , ry: height / 5 + }) + } + } + + // Add method to parent elements +, construct: { + // Create a rounded element + rounded: function(width, height) { + return this.put(new SVG.Rounded).size(width, height) + } + + } +}) +``` + +To create the element in your drawing: + +```javascript +var rounded = draw.rounded(200, 100) +``` + +That's it, the invention is now ready to be used! + +#### Accepted values +The `SVG.invent()` function always expects an object. The object can have the following configuration values: + +- `create`: can be either a string with the node name (e.g. `rect`, `ellipse`, ...) or a custom initializer function; `[required]` +- `inherit`: the desired SVG.js class to inherit from (e.g. `SVG.Shape`, `SVG.Element`, `SVG.Container`, `SVG.Rect`, ...); `[optional but recommended]` +- `extend`: an object with the methods that should be applied to the element's prototype; `[optional]` +- `construct`: an object with the methods to create the element on the parent element; `[optional]` +- `parent`: an SVG.js parent class on which the methods in the passed `construct` object should be available - defaults to `SVG.Container`; `[optional]` + +#### Usage notes + +It should be emphasized that in the configuration object passed to `SVG.invent()`: + +- `construct` does not supply constructors, but rather methods that are likely to *call* constructors; +- `create` specifies the constructor for the type you are defining, and is not analogous to `Object.create()`. + +When defining specialized svg elements (such as `SVG.Rounded` in the example above), the function specified by `create` needs to do all the work of adding the element to the DOM for the svg document and connecting the DOM node to the SVG.js interface. All this is done automatically when the value of `create` is a string identifying an element type. If needed, see the source for a sense of how to do it explicitly. + +Though the defaults are geared toward creating svg elements for the SVG.js framework, `SVG.invent()` can be used as a generalized function for defining types in Javascript. When used in this more general way, the function supplied as a value for `create` should be written as an ordinary JS constructor. (Indeed, the function is simply returned as the constructor for your newly defined type.) + +Svg.js uses the `SVG.invent()` function to create all internal elements. A look at the source will show how this function is used in various ways. + + + +### SVG.extend() +SVG.js has a modular structure. It is very easy to add your own methods at different levels. Let's say we want to add a method to all shape types then we would add our method to SVG.Shape: + +```javascript +SVG.extend(SVG.Shape, { + paintRed: function() { + return this.fill('red') + } +}) +``` + +Now all shapes will have the paintRed method available. Say we want to have the paintRed method on an ellipse apply a slightly different color: + +```javascript +SVG.extend(SVG.Ellipse, { + paintRed: function() { + return this.fill('orangered') + } +}) + +``` +The complete inheritance stack for `SVG.Ellipse` is: + +_`SVG.Ellipse` < `SVG.Shape` < `SVG.Element`_ + +The SVG document can be extended by using: + +```javascript +SVG.extend(SVG.Doc, { + paintAllPink: function() { + this.each(function() { + this.fill('pink') + }) + } +}) +``` + +You can also extend multiple elements at once: +```javascript +SVG.extend(SVG.Ellipse, SVG.Path, SVG.Polygon, { + paintRed: function() { + return this.fill('orangered') + } +}) +``` + + +## Plugins +Here are a few nice plugins that are available for SVG.js: + +### pathmorphing +[svg.pathmorphing.js](https://github.com/wout/svg.pathmorphing.js) to make path animatable + +### textmorphing +[svg.textmorph.js](https://github.com/wout/svg.textmorph.js) to make text animatable + +### absorb +[svg.absorb.js](https://github.com/wout/svg.absorb.js) absorb raw SVG data into an SVG.js instance. + +### draggable +[svg.draggable.js](https://github.com/wout/svg.draggable.js) to make elements draggable. + +### connectable +[svg.connectable.js](https://github.com/jillix/svg.connectable.js) to connect elements. + +[svg.connectable.js fork](https://github.com/loredanacirstea/svg.connectable.js) to connect elements (added: curved connectors, you can use any self-made path as a connector, choosable 'center'/'perifery' attachment, 'perifery' attachment for source / target SVG Paths uses smallest-distance algorithm between PathArray points) + +### easing +[svg.easing.js](https://github.com/wout/svg.easing.js) for more easing methods on animations. + +### export +[svg.export.js](https://github.com/wout/svg.export.js) export raw SVG. + +### filter +[svg.filter.js](https://github.com/wout/svg.filter.js) adding svg filters to elements. + +### foreignobject +[svg.foreignobject.js](https://github.com/john-memloom/svg.foreignobject.js) foreignObject implementation (by john-memloom). + +### import +[svg.import.js](https://github.com/wout/svg.import.js) import raw SVG data. + +### math +[svg.math.js](https://github.com/otm/svg.math.js) a math extension (by Nils Lagerkvist). + +### path +[svg.path.js](https://github.com/otm/svg.path.js) for manually drawing paths (by Nils Lagerkvist). + +## screenBBox +[svg.screenbbox.js](https://github.com/fuzzyma/svg.screenbbox.js) to get the bbox in screen coordinates from transformed path/polygon/polyline + +### shapes +[svg.shapes.js](https://github.com/wout/svg.shapes.js) for more polygon based shapes. + +### topath +[svg.topath.js](https://github.com/wout/svg.topath.js) to convert any other shape to a path. + +### topoly +[svg.topoly.js](https://github.com/wout/svg.topoly.js) to convert a path to polygon or polyline. + +### wiml +[svg.wiml.js](https://github.com/wout/svg.wiml.js) a templating language for svg output. + +### comic +[comic.js](https://github.com/balint42/comic.js) to cartoonize any given svg. + +### draw +[svg.draw.js](https://github.com/fuzzyma/svg.draw.js) to draw elements with your mouse + +### select +[svg.select.js](https://github.com/fuzzyma/svg.select.js) to select elements + +### resize +[svg.resize.js](https://github.com/fuzzyma/svg.resize.js) to resize elements with your mouse + +## Contributing +We love contributions. Yes indeed, we used the word LOVE! But please make sure you follow the same coding style. Here are some guidelines. + +### Indentation +We do it with __two spaces__. Make sure you don't start using tabs because then things get messy. + +### Avoid hairy code +We like to keep things simple and clean, don't write anything you don't need. So use __single quotes__ where possible and __avoid semicolons__, we're not writing PHP here. + +__Good__: +```javascript +var text = draw.text('with single quotes here') + , nest = draw.nested().attr('x', '50%') + +for (var i = 0; i < 5; i++) + if (i != 3) + nest.circle(i * 100) +``` + +__Bad__: +```javascript +var text = draw.text("with double quotes here"); +var nest = draw.nested().attr("x", "50%"); + +for (var i = 0; i < 5; i++) { + if (i != 3) { + nest.circle(100); + }; +}; +``` + +### Minimize variable declarations +All local variables should be declared at the beginning of a function or method unless there is ony one variable to declare. Although it is not required to assign them at the same moment. When if statements are involved, requiring some variables only to be present in the statement, the necessary variables should be declared right after the if statement. + +__Good__: +```javascript +function reading_board() { + var aap, noot, mies + + aap = 1 + noot = 2 + mies = aap + noot +} +``` + +__Bad__: +```javascript +function reading_board() { + var aap = 1 + var noot = 2 + var mies = aap + noot +} +``` + +### Let your code breathe people! +Don't try to be a code compressor yourself, they do way a better job anyway. Give your code some spaces and newlines. + +__Good__: +```javascript +var nest = draw.nested().attr({ + x: 10 +, y: 20 +, width: 200 +, height: 300 +}) + +for (var i = 0; i < 5; i++) + nest.circle(100) +``` + +__Bad__: +```javascript +var nest=draw.nested().attr({x:10,y:20,width:200,height:300}); +for(var i=0;i<5;i++)nest.circle(100); +``` + +### It won't hurt to add a few comments +Where necessary tell us what you are doing but be concise. We only use single-line comments. Also keep your variable and method names short while maintaining readability. + +__Good__: +```javascript +// Adds orange-specific methods +SVG.extend(SVG.Rect, { + // Add a nice, transparent orange + orangify: function() { + // fill with orange color + this.fill('orange') + + // add a slight opacity + return this.opacity(0.85) + } +}) +``` + +__Bad__: +```javascript +/* + * + * does something with orange and opacity + * + */ +SVG.extend(SVG.Rect, { + orgf: function() { + return this.fill('orange').opacity(0.85) + } +}) +``` + +### Refactor your code +Once your implementation is ready, revisit and rework it. We like to keep it [DRY](http://en.wikipedia.org/wiki/Don't_repeat_yourself). + +### Test. Your. Code. +It's not that hard to write at least one example per implementation, although we prefer more. Your code might seem to work by quickly testing it in your brwoser but more than often you can't forsee everything. + +Before running the specs you will need to build the library. Be aware that pull requests without specs will be declined. + + +## Building +After contributing you probably want to build the library to run some specs. Make sure you have Node.js installed on your system, `cd` to the svg.js directory and run: + +``` sh +$ npm install +``` + +Build SVG.js by running `gulp`: + +``` sh +$ gulp +``` + +The resulting files are: + +1. `dist/svg.js` +2. `dist/svg.min.js` + + +## Compatibility + +### Desktop +- Firefox 3+ +- Chrome 4+ +- Safari 3.2+ +- Opera 9+ +- IE9+ + +### Mobile +- iOS Safari 3.2+ +- Android Browser 3+ +- Opera Mobile 10+ +- Chrome for Android 18+ +- Firefox for Android 15+ + +Visit the [SVG.js test page](http://svgjs.com/test) if you want to check compatibility with different browsers. + +## Acknowledgements & Thanks + +Documentation kindly provided by [DocumentUp](http://documentup.com) + +SVG.js and its documentation is released under the terms of the MIT license. diff --git a/node_modules/svgjs/bower.json b/node_modules/svgjs/bower.json new file mode 100644 index 0000000..0c3fe08 --- /dev/null +++ b/node_modules/svgjs/bower.json @@ -0,0 +1,20 @@ +{ + "name": "svg.js", + "version":"2.2.5", + "homepage": "http://svgjs.com/", + "authors": [ + "Wout Fierens " + ], + "description": "A lightweight library for manipulating and animating SVG", + "main": "dist/svg.js", + "keywords": [ + "svg", "vector", "graphics" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "spec/", + "src/", + "gulpfile.js" + ] +} \ No newline at end of file diff --git a/node_modules/svgjs/component.json b/node_modules/svgjs/component.json new file mode 100644 index 0000000..9ac7f65 --- /dev/null +++ b/node_modules/svgjs/component.json @@ -0,0 +1,11 @@ +{ + "name": "svg.js", + "repo": "wout/svg.js", + "description": "A lightweight library for manipulating and animating SVG", + "version": "2.2.5", + "keywords": ["svg"], + "author": "Wout Fierens ", + "main": "dist/svg.js", + "scripts": ["dist/svg.js"], + "license": "MIT" +} \ No newline at end of file diff --git a/node_modules/svgjs/dist/svg.js b/node_modules/svgjs/dist/svg.js new file mode 100644 index 0000000..4b7d7dd --- /dev/null +++ b/node_modules/svgjs/dist/svg.js @@ -0,0 +1,4662 @@ +/*! +* svg.js - A lightweight library for manipulating and animating SVG. +* @version 2.2.5 +* http://www.svgjs.com +* +* @copyright Wout Fierens +* @license MIT +* +* BUILT: Thu Jan 21 2016 16:57:48 GMT+0100 (Mitteleuropäische Zeit) +*/; +(function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(function(){ + return factory(root, root.document) + }) + } else if (typeof exports === 'object') { + module.exports = root.document ? factory(root, root.document) : function(w){ return factory(w, w.document) } + } else { + root.SVG = factory(root, root.document) + } +}(typeof window !== "undefined" ? window : this, function(window, document) { + +// The main wrapping element +var SVG = this.SVG = function(element) { + if (SVG.supported) { + element = new SVG.Doc(element) + + if (!SVG.parser) + SVG.prepare(element) + + return element + } +} + +// 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' + +// Svg support test +SVG.supported = (function() { + return !! document.createElementNS && + !! document.createElementNS(SVG.ns,'svg').createSVGRect +})() + +// Don't bother to continue if SVG is not supported +if (!SVG.supported) return false + +// 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 + var element = document.createElementNS(this.ns, name) + + // apply unique id + element.setAttribute('id', this.eid(name)) + + return element +} + +// Method for extending objects +SVG.extend = function() { + var modules, methods, key, i + + // Get list of modules + modules = [].slice.call(arguments) + + // Get object with extensions + methods = modules.pop() + + for (i = modules.length - 1; i >= 0; i--) + if (modules[i]) + for (key in methods) + modules[i].prototype[key] = methods[key] + + // Make sure SVG.Set inherits any newly added methods + if (SVG.Set && SVG.Set.inherit) + SVG.Set.inherit() +} + +// Invent new element +SVG.invent = function(config) { + // Create element initializer + var initializer = typeof config.create == 'function' ? + config.create : + function() { + this.constructor.call(this, 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) return node.instance + + // initialize variables + var element + + // adopt with element-specific settings + if (node.nodeName == 'svg') + element = node.parentNode instanceof SVGElement ? new SVG.Nested : new SVG.Doc + else if (node.nodeName == 'linearGradient') + element = new SVG.Gradient('linear') + else if (node.nodeName == 'radialGradient') + element = new SVG.Gradient('radial') + else if (SVG[capitalize(node.nodeName)]) + element = new SVG[capitalize(node.nodeName)] + else + element = new SVG.Element(node) + + // ensure references + element.type = node.nodeName + element.node = node + node.instance = element + + // SVG.Class specific preparations + if (element instanceof SVG.Doc) + element.namespace().defs() + + // pull svgjs data from the dom (getAttributeNS doesn't work in html5) + element.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}) + + return element +} + +// Initialize parsing element +SVG.prepare = function(element) { + // Select document body and create invisible svg element + var body = document.getElementsByTagName('body')[0] + , draw = (body ? new SVG.Doc(body) : element.nested()).size(2, 0) + , path = SVG.create('path') + + // Insert parsers + draw.node.appendChild(path) + + // Create parser object + SVG.parser = { + body: body || element.parent() + , draw: draw.style('opacity:0;position:fixed;left:100%;top:100%;overflow:hidden') + , poly: draw.polyline().node + , path: path + } +} + +// Storage for regular expressions +SVG.regex = { + // Parse unit value + unit: /^(-?[\d\.]+)([a-z%]{0,2})$/ + + // 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 + + // Parse matrix wrapper +, matrix: /matrix\(|\)/g + + // Elements of a matrix +, matrixElements: /,*\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 + + // The following regex are used to parse the d attribute of a path + + // Replaces all negative exponents +, negExp: /e\-/gi + + // Replaces all comma +, comma: /,/g + + // Replaces all hyphens +, hyphen: /\-/g + + // Replaces and tests for all path letters +, pathLetters: /[MLHVCSQTAZ]/gi + + // yes we need this one, too +, isPathLetter: /[MLHVCSQTAZ]/i + + // split at whitespaces +, whitespaces: /\s+/ + + // matches X +, X: /X/g +} + +SVG.utils = { + // Map function + map: function(array, block) { + var i + , il = array.length + , result = [] + + for (i = 0; i < il; i++) + result.push(block(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(p) { + return [].filter.call(p, function(el){ return el instanceof SVGElement }) + } + +} + +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' + } + +} +// Module for color convertions +SVG.Color = function(color) { + var match + + // initialize defaults + this.r = 0 + this.g = 0 + this.b = 0 + + // parse color + if (typeof color === 'string') { + if (SVG.regex.isRgb.test(color)) { + // get rgb values + match = SVG.regex.rgb.exec(color.replace(/\s/g,'')) + + // 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) +} +// 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] + , 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 + return this.value = 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 this.split(array) + } + // Strip unnecessary whitespace +, split: function(string) { + return string.trim().split(/\s+/) + } + // Reverse array +, reverse: function() { + this.value.reverse() + + return this + } + +}) +// Poly points array +SVG.PointArray = function(array, fallback) { + this.constructor.call(this, array, fallback || [[0,0]]) +} + +// Inherit from SVG.Array +SVG.PointArray.prototype = new SVG.Array + +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 +, parse: function(array) { + array = array.valueOf() + + // if already is an array, no need to parse it + if (Array.isArray(array)) return array + + // split points + array = this.split(array) + + // parse points + for (var i = 0, il = array.length, p, points = []; i < il; i++) { + p = array[i].split(',') + points.push([parseFloat(p[0]), parseFloat(p[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, box = this.bbox() + + // recalculate position of all points according to new size + for (i = this.value.length - 1; i >= 0; i--) { + this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x + this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y + } + + return this + } + // Get bounding box of points +, bbox: function() { + SVG.parser.poly.setAttribute('points', this.toString()) + + return SVG.parser.poly.getBBox() + } + +}) +// Path points array +SVG.PathArray = function(array, fallback) { + this.constructor.call(this, array, fallback || [['M', 0, 0]]) +} + +// Inherit from SVG.Array +SVG.PathArray.prototype = new SVG.Array + +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 i, l, box = this.bbox() + + // 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 + } + // 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 i, x0, y0, s, seg, arr + , x = 0 + , y = 0 + , paramCnt = { 'M':2, 'L':2, 'H':1, 'V':1, 'C':6, 'S':4, 'Q':4, 'T':2, 'A':7 } + + if(typeof array == 'string'){ + + array = array + .replace(SVG.regex.negExp, 'X') // replace all negative exponents with certain char + .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers + .replace(SVG.regex.hyphen, ' -') // add space before hyphen + .replace(SVG.regex.comma, ' ') // unify all spaces + .replace(SVG.regex.X, 'e-') // add back the expoent + .trim() // trim + .split(SVG.regex.whitespaces) // split into array + + // at this place there could be parts like ['3.124.854.32'] because we could not determine the point as seperator till now + // we fix this elements in the next loop + for(i = array.length; --i;){ + if(array[i].indexOf('.') != array[i].lastIndexOf('.')){ + var split = array[i].split('.') // split at the point + var first = [split.shift(), split.shift()].join('.') // join the first number together + array.splice.apply(array, [i, 1].concat(first, split.map(function(el){ return '.'+el }))) // add first and all other entries back to array + } + } + + }else{ + array = array.reduce(function(prev, curr){ + return [].concat.apply(prev, curr) + }, []) + } + + // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + + var arr = [] + + do{ + + // Test if we have a path letter + if(SVG.regex.isPathLetter.test(array[0])){ + s = array[0] + array.shift() + // 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' + } + + // add path letter as first element + seg = [s.toUpperCase()] + + // push all necessary parameters to segment + for(i = 0; i < paramCnt[seg[0]]; ++i){ + seg.push(parseFloat(array.shift())) + } + + // upper case + if(s == seg[0]){ + + if(s == 'M' || s == 'L' || s == 'C' || s == 'Q'){ + x = seg[paramCnt[seg[0]]-1] + y = seg[paramCnt[seg[0]]] + }else if(s == 'V'){ + y = seg[1] + }else if(s == 'H'){ + x = seg[1] + }else if(s == 'A'){ + x = seg[6] + y = seg[7] + } + + // lower case + }else{ + + // convert relative to absolute values + if(s == 'm' || s == 'l' || s == 'c' || s == 's' || s == 'q' || s == 't'){ + + seg[1] += x + seg[2] += y + + if(seg[3] != null){ + seg[3] += x + seg[4] += y + } + + if(seg[5] != null){ + seg[5] += x + seg[6] += y + } + + // move pointer + x = seg[paramCnt[seg[0]]-1] + y = seg[paramCnt[seg[0]]] + + }else if(s == 'v'){ + seg[1] += y + y = seg[1] + }else if(s == 'h'){ + seg[1] += x + x = seg[1] + }else if(s == 'a'){ + seg[6] += x + seg[7] += y + x = seg[6] + y = seg[7] + } + + } + + if(seg[0] == 'M'){ + x0 = x + y0 = y + } + + if(seg[0] == 'Z'){ + x = x0 + y = y0 + } + + arr.push(seg) + + }while(array.length) + + return arr + + } + // Get bounding box of path +, bbox: function() { + SVG.parser.path.setAttribute('d', this.toString()) + + return SVG.parser.path.getBBox() + } + +}) +// 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.unit) + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]) + + // normalize + if (unit[2] == '%') + this.value /= 100 + else if (unit[2] == 's') + this.value *= 1000 + + // store unit + this.unit = unit[2] + } + + } 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) { + return new SVG.Number(this + new SVG.Number(number), this.unit) + } + // Subtract number + , minus: function(number) { + return this.plus(-new SVG.Number(number)) + } + // Multiply number + , times: function(number) { + return new SVG.Number(this * new SVG.Number(number), this.unit) + } + // Divide number + , divide: function(number) { + return new SVG.Number(this / new SVG.Number(number), this.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) + + 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.ViewBox = function(element) { + var x, y, width, height + , wm = 1 // width multiplier + , hm = 1 // height multiplier + , box = element.bbox() + , view = (element.attr('viewBox') || '').match(/-?[\d\.]+/g) + , we = element + , he = element + + // get dimensions of current node + width = new SVG.Number(element.width()) + height = new SVG.Number(element.height()) + + // find nearest non-percentual dimensions + while (width.unit == '%') { + wm *= width.value + width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width()) + we = we.parent() + } + while (height.unit == '%') { + hm *= height.value + height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height()) + he = he.parent() + } + + // ensure defaults + this.x = box.x + this.y = box.y + this.width = width * wm + this.height = height * hm + this.zoom = 1 + + if (view) { + // get width and height from viewbox + x = parseFloat(view[0]) + y = parseFloat(view[1]) + width = parseFloat(view[2]) + height = parseFloat(view[3]) + + // calculate zoom accoring to viewbox + this.zoom = ((this.width / this.height) > (width / height)) ? + this.height / height : + this.width / width + + // calculate real pixel dimensions on parent SVG.Doc element + this.x = x + this.y = y + this.width = width + this.height = height + + } + +} + +// +SVG.extend(SVG.ViewBox, { + // Parse viewbox to string + toString: function() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height + } + +}) + +SVG.Element = SVG.invent({ + // Initialize node + create: function(node) { + // make stroke value accessible dynamically + this._stroke = SVG.defaults.attrs.stroke + + // initialize data object + this.dom = {} + + // create circular reference + if (this.node = node) { + this.type = node.nodeName + this.node.instance = this + + // store current attribute value + this._stroke = node.getAttribute('stroke') || this._stroke + } + } + + // 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.bbox(), width, height) + + return this + .width(new SVG.Number(p.width)) + .height(new SVG.Number(p.height)) + } + // Clone element + , clone: function() { + // clone element and assign new id + var clone = assignNewId(this.node.cloneNode(true)) + + // insert the clone after myself + 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 parent.put(this) + } + // Add element to given container and return container + , putIn: function(parent) { + return parent.add(this) + } + // Get / set id + , id: function(id) { + 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.style('display', '') + } + // Hide element + , hide: function() { + return this.style('display', 'none') + } + // Is element visible? + , visible: function() { + return this.style('display') != 'none' + } + // Return id on string conversion + , toString: function() { + return this.attr('id') + } + // Return array of classes on the node + , classes: function() { + var attr = this.attr('class') + + return attr == null ? [] : attr.trim().split(/\s+/) + } + // 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.node instanceof SVGElement){ + if(typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = SVG.adopt(parent.node.parentNode) + } + } + // Get parent document + , doc: function() { + return this instanceof SVG.Doc ? this : this.parent(SVG.Doc) + } + // return array of all ancestors of given type up to the root svg + , parents: function(type) { + var parents = [], 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) { + // create temporary holder + var well = document.createElement('svg') + + // act as a setter if svg is given + if (svg && this instanceof SVG.Parent) { + // dump raw svg + well.innerHTML = '' + svg.replace(/\n/, '').replace(/<(\w+)([^<]+?)\/>/g, '<$1$2>') + '' + + // transplant nodes + for (var i = 0, il = well.firstChild.childNodes.length; i < il; i++) + this.node.appendChild(well.firstChild.firstChild) + + // otherwise act as a getter + } else { + // create a wrapping svg element in case of partial content + well.appendChild(svg = document.createElement('svg')) + + // write svgjs data to the dom + this.writeDataToDom() + + // insert a copy of this node + svg.appendChild(this.node.cloneNode(true)) + + // return target element + return well.innerHTML.replace(/^/, '').replace(/<\/svg>$/, '') + } + + return this + } + // write svgjs data to the dom + , writeDataToDom: function() { + + // dump variables recursively + if(this.each || this.lines){ + var fn = this.each ? this : this.lines(); + fn.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 + } + } +}) + +SVG.FX = SVG.invent({ + // Initialize FX object + create: function(element) { + // store target element + this.target = element + } + + // Add class methods +, extend: { + // Add animation parameters and start animation + animate: function(d, ease, delay) { + var akeys, skeys, key + , element = this.target + , fx = this + + // dissect object if one is passed + if (typeof d == 'object') { + delay = d.delay + ease = d.ease + d = d.duration + } + + // ensure default duration and easing + d = d == '=' ? d : d == null ? 1000 : new SVG.Number(d).valueOf() + ease = ease || '<>' + + // process values + fx.at = function(pos) { + var i + + // normalise pos + pos = pos < 0 ? 0 : pos > 1 ? 1 : pos + + // collect attribute keys + if (akeys == null) { + akeys = [] + for (key in fx.attrs) + akeys.push(key) + + // make sure morphable elements are scaled, translated and morphed all together + if (element.morphArray && (fx.destination.plot || akeys.indexOf('points') > -1)) { + // get destination + var box + , p = new element.morphArray(fx.destination.plot || fx.attrs.points || element.array()) + + // add size + if (fx.destination.size) + p.size(fx.destination.size.width.to, fx.destination.size.height.to) + + // add movement + box = p.bbox() + if (fx.destination.x) + p.move(fx.destination.x.to, box.y) + else if (fx.destination.cx) + p.move(fx.destination.cx.to - box.width / 2, box.y) + + box = p.bbox() + if (fx.destination.y) + p.move(box.x, fx.destination.y.to) + else if (fx.destination.cy) + p.move(box.x, fx.destination.cy.to - box.height / 2) + + // reset destination values + fx.destination = { + plot: element.array().morph(p) + } + } + } + + // collect style keys + if (skeys == null) { + skeys = [] + for (key in fx.styles) + skeys.push(key) + } + + // apply easing + pos = ease == '<>' ? + (-Math.cos(pos * Math.PI) / 2) + 0.5 : + ease == '>' ? + Math.sin(pos * Math.PI / 2) : + ease == '<' ? + -Math.cos(pos * Math.PI / 2) + 1 : + ease == '-' ? + pos : + typeof ease == 'function' ? + ease(pos) : + pos + + // run plot function + if (fx.destination.plot) { + element.plot(fx.destination.plot.at(pos)) + + } else { + // run all x-position properties + if (fx.destination.x) + element.x(fx.destination.x.at(pos)) + else if (fx.destination.cx) + element.cx(fx.destination.cx.at(pos)) + + // run all y-position properties + if (fx.destination.y) + element.y(fx.destination.y.at(pos)) + else if (fx.destination.cy) + element.cy(fx.destination.cy.at(pos)) + + // run all size properties + if (fx.destination.size) + element.size(fx.destination.size.width.at(pos), fx.destination.size.height.at(pos)) + } + + // run all viewbox properties + if (fx.destination.viewbox) + element.viewbox( + fx.destination.viewbox.x.at(pos) + , fx.destination.viewbox.y.at(pos) + , fx.destination.viewbox.width.at(pos) + , fx.destination.viewbox.height.at(pos) + ) + + // run leading property + if (fx.destination.leading) + element.leading(fx.destination.leading.at(pos)) + + // animate attributes + for (i = akeys.length - 1; i >= 0; i--) + element.attr(akeys[i], at(fx.attrs[akeys[i]], pos)) + + // animate styles + for (i = skeys.length - 1; i >= 0; i--) + element.style(skeys[i], at(fx.styles[skeys[i]], pos)) + + // callback for each keyframe + if (fx.situation.during) + fx.situation.during.call(element, pos, function(from, to) { + return at({ from: from, to: to }, pos) + }) + } + + if (typeof d === 'number') { + // delay animation + this.timeout = setTimeout(function() { + var start = new Date().getTime() + + // initialize situation object + fx.situation.start = start + fx.situation.play = true + fx.situation.finish = start + d + fx.situation.duration = d + fx.situation.ease = ease + + // render function + fx.render = function() { + + if (fx.situation.play === true) { + // calculate pos + var time = new Date().getTime() + , pos = time > fx.situation.finish ? 1 : (time - fx.situation.start) / d + + // reverse pos if animation is reversed + if (fx.situation.reversing) + pos = -pos + 1 + + // process values + fx.at(pos) + + // finish off animation + if (time > fx.situation.finish) { + if (fx.destination.plot) + element.plot(new SVG.PointArray(fx.destination.plot.destination).settle()) + + if (fx.situation.loop === true || (typeof fx.situation.loop == 'number' && fx.situation.loop > 0)) { + // register reverse + if (fx.situation.reverse) + fx.situation.reversing = !fx.situation.reversing + + if (typeof fx.situation.loop == 'number') { + // reduce loop count + if (!fx.situation.reverse || fx.situation.reversing) + --fx.situation.loop + + // remove last loop if reverse is disabled + if (!fx.situation.reverse && fx.situation.loop == 1) + --fx.situation.loop + } + + fx.animate(d, ease, delay) + } else { + fx.situation.after ? fx.situation.after.apply(element, [fx]) : fx.stop() + } + + } else { + fx.animationFrame = requestAnimationFrame(fx.render) + } + } else { + fx.animationFrame = requestAnimationFrame(fx.render) + } + + } + + // start animation + fx.render() + + }, new SVG.Number(delay).valueOf()) + } + + return this + } + // Get bounding box of target element + , bbox: function() { + return this.target.bbox() + } + // Add animatable attributes + , attr: function(a, v) { + // apply attributes individually + if (typeof a == 'object') { + for (var key in a) + this.attr(key, a[key]) + + } else { + // get the current state + var from = this.target.attr(a) + + // detect format + if (a == 'transform') { + // merge given transformation with an existing one + if (this.attrs[a]) + v = this.attrs[a].destination.multiply(v) + + // prepare matrix for morphing + this.attrs[a] = (new SVG.Matrix(this.target)).morph(v) + + // add parametric rotation values + if (this.param) { + // get initial rotation + v = this.target.transform('rotation') + + // add param + this.attrs[a].param = { + from: this.target.param || { rotation: v, cx: this.param.cx, cy: this.param.cy } + , to: this.param + } + } + + } else { + this.attrs[a] = SVG.Color.isColor(v) ? + // prepare color for morphing + new SVG.Color(from).morph(v) : + SVG.regex.unit.test(v) ? + // prepare number for morphing + new SVG.Number(from).morph(v) : + // prepare for plain morphing + { from: from, to: v } + } + } + + return this + } + // Add animatable styles + , style: function(s, v) { + if (typeof s == 'object') + for (var key in s) + this.style(key, s[key]) + + else + this.styles[s] = { from: this.target.style(s), to: v } + + return this + } + // Animatable x-axis + , x: function(x) { + this.destination.x = new SVG.Number(this.target.x()).morph(x) + + return this + } + // Animatable y-axis + , y: function(y) { + this.destination.y = new SVG.Number(this.target.y()).morph(y) + + return this + } + // Animatable center x-axis + , cx: function(x) { + this.destination.cx = new SVG.Number(this.target.cx()).morph(x) + + return this + } + // Animatable center y-axis + , cy: function(y) { + this.destination.cy = new SVG.Number(this.target.cy()).morph(y) + + return this + } + // 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 = this.target.bbox() + + this.destination.size = { + width: new SVG.Number(box.width).morph(width) + , height: new SVG.Number(box.height).morph(height) + } + } + + return this + } + // Add animatable plot + , plot: function(p) { + this.destination.plot = p + + return this + } + // Add leading method + , leading: function(value) { + if (this.target.destination.leading) + this.destination.leading = new SVG.Number(this.target.destination.leading).morph(value) + + return this + } + // Add animatable viewbox + , viewbox: function(x, y, width, height) { + if (this.target instanceof SVG.Container) { + var box = this.target.viewbox() + + this.destination.viewbox = { + x: new SVG.Number(box.x).morph(x) + , y: new SVG.Number(box.y).morph(y) + , width: new SVG.Number(box.width).morph(width) + , height: new SVG.Number(box.height).morph(height) + } + } + + return this + } + // Add animateable gradient update + , update: function(o) { + if (this.target instanceof SVG.Stop) { + 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 + } + // Add callback for each keyframe + , during: function(during) { + this.situation.during = during + + return this + } + // Callback after animation + , after: function(after) { + this.situation.after = after + + return this + } + // Make loopable + , loop: function(times, reverse) { + // store current loop and total loops + this.situation.loop = this.situation.loops = times || true + + // make reversable + this.situation.reverse = !!reverse + + return this + } + // Stop running animation + , stop: function(fulfill) { + // fulfill animation + if (fulfill === true) { + + this.animate(0) + + if (this.situation.after) + this.situation.after.apply(this.target, [this]) + + } else { + // stop current animation + clearTimeout(this.timeout) + cancelAnimationFrame(this.animationFrame); + + // reset storage for properties + this.attrs = {} + this.styles = {} + this.situation = {} + this.destination = {} + } + + return this + } + // Pause running animation + , pause: function() { + if (this.situation.play === true) { + this.situation.play = false + this.situation.pause = new Date().getTime() + } + + return this + } + // Play running animation + , play: function() { + if (this.situation.play === false) { + var pause = new Date().getTime() - this.situation.pause + + this.situation.finish += pause + this.situation.start += pause + this.situation.play = true + } + + return this + } + + } + + // Define parent class +, 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(d, ease, delay) { + return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(d, ease, delay) + } + // Stop current animation; this is an alias to the fx instance + , stop: function(fulfill) { + if (this.fx) + this.fx.stop(fulfill) + + 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 + } + + } +}) + +SVG.BBox = SVG.invent({ + // Initialize + create: function(element) { + // get values if element is given + if (element) { + var box + + // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered + try { + // find native bbox + box = element.node.getBBox() + } catch(e) { + if(element instanceof SVG.Shape){ + var clone = element.clone().addTo(SVG.parser.draw) + box = clone.bbox() + clone.remove() + }else{ + box = { + x: element.node.clientLeft + , y: element.node.clientTop + , width: element.node.clientWidth + , height: element.node.clientHeight + } + } + } + + // plain x and y + this.x = box.x + this.y = box.y + + // plain width and height + this.width = box.width + this.height = box.height + } + + // add center, right and bottom + fullBox(this) + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get bounding box + bbox: function() { + return new SVG.BBox(this) + } + } + +}) + +SVG.TBox = SVG.invent({ + // Initialize + create: function(element) { + // get values if element is given + if (element) { + var t = element.ctm().extract() + , box = element.bbox() + + // width and height including transformations + this.width = box.width * t.scaleX + this.height = box.height * t.scaleY + + // x and y including transformations + this.x = box.x + t.x + this.y = box.y + t.y + } + + // add center, right and bottom + fullBox(this) + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get transformed bounding box + tbox: function() { + return new SVG.TBox(this) + } + } + +}) + + +SVG.RBox = SVG.invent({ + // Initialize + create: function(element) { + if (element) { + var e = element.doc().parent() + , box = element.node.getBoundingClientRect() + , zoom = 1 + + // get screen offset + this.x = box.left + this.y = box.top + + // subtract parent offset + this.x -= e.offsetLeft + this.y -= e.offsetTop + + while (e = e.offsetParent) { + this.x -= e.offsetLeft + this.y -= e.offsetTop + } + + // calculate cumulative zoom from svg documents + e = element + while (e.parent && (e = e.parent())) { + if (e.viewbox) { + zoom *= e.viewbox().zoom + this.x -= e.x() || 0 + this.y -= e.y() || 0 + } + } + + // recalculate viewbox distortion + this.width = box.width /= zoom + this.height = box.height /= zoom + } + + // add center, right and bottom + fullBox(this) + + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + this.y += window.pageYOffset + } + + // define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get rect box + rbox: function() { + return new SVG.RBox(this) + } + } + +}) + +// Add universal merge method +;[SVG.BBox, SVG.TBox, SVG.RBox].forEach(function(c) { + + SVG.extend(c, { + // Merge rect box with another, return a new instance + merge: function(box) { + var b = new c() + + // merge boxes + b.x = Math.min(this.x, box.x) + b.y = Math.min(this.y, box.y) + b.width = Math.max(this.x + this.width, box.x + box.width) - b.x + b.height = Math.max(this.y + this.height, box.y + box.height) - b.y + + return fullBox(b) + } + + }) + +}) + +SVG.Matrix = SVG.invent({ + // Initialize + create: function(source) { + var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0]) + + // ensure source as object + source = source instanceof SVG.Element ? + source.matrixify() : + typeof source === 'string' ? + stringToMatrix(source) : + arguments.length == 6 ? + arrayToMatrix([].slice.call(arguments)) : + typeof source === 'object' ? + source : base + + // merge source + for (i = abcdef.length - 1; i >= 0; i--) + this[abcdef[i]] = source && typeof source[abcdef[i]] === 'number' ? + source[abcdef[i]] : base[abcdef[i]] + } + + // Add methods +, extend: { + // Extract individual transformations + extract: function() { + // find delta transform points + var px = deltaTransformPoint(this, 0, 1) + , py = deltaTransformPoint(this, 1, 0) + , skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90 + + return { + // translation + x: this.e + , y: this.f + // 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 + } + } + // 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 + }) + + // process parametric rotation if present + if (this.param && this.param.to) { + // calculate current parametric position + var param = { + rotation: this.param.from.rotation + (this.param.to.rotation - this.param.from.rotation) * pos + , cx: this.param.from.cx + , cy: this.param.from.cy + } + + // rotate matrix + matrix = matrix.rotate( + (this.param.to.rotation - this.param.from.rotation * 2) * pos + , param.cx + , param.cy + ) + + // store current parametric values + matrix.param = param + } + + 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 universal scale + if (arguments.length == 1 || arguments.length == 3) + y = x + if (arguments.length == 3) { + cy = cx + cx = y + } + + 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) : this.scale(1, -1, 0, o) + } + // Skew + , skew: function(x, y, cx, cy) { + return this.around(cx, cy, this.native().skewX(x || 0).skewY(y || 0)) + } + // SkewX + , skewX: function(x, cx, cy) { + return this.around(cx, cy, this.native().skewX(x || 0)) + } + // SkewY + , skewY: function(y, cx, cy) { + return this.around(cx, cy, this.native().skewY(y || 0)) + } + // 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.draw.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() { + return new SVG.Matrix(this.node.getScreenCTM()) + } + + } + +}) + +SVG.Point = SVG.invent({ + // Initialize + create: function(x,y) { + var i, source, 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} : + y != null ? + {x:x, y:y} : base + + // 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(point) { + // store new destination + this.destination = new SVG.Point(point) + + 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.draw.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 { + // BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0 + if (a == 'stroke-width') + this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null) + else if (a == 'stroke') + this._stroke = v + + // convert image fill and stroke to patterns + if (a == 'fill' || a == 'stroke') { + if (SVG.regex.isImage.test(v)) + v = this.doc().defs().image(v, 0, 0) + + 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) + + // ensure full hex color + else if (SVG.Color.isColor(v)) + v = new SVG.Color(v) + + // parse array values + else if (Array.isArray(v)) + v = new SVG.Array(v) + + // store parametric transformation values locally + else if (v instanceof SVG.Matrix && v.param) + this.param = v.param + + // 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.Element, SVG.FX, { + // Add transformations + transform: function(o, relative) { + // get target in case of the fx module, otherwise reference this + var target = this.target || this + , matrix + + // act as a getter + if (typeof o !== 'object') { + // get current matrix + matrix = new SVG.Matrix(target).extract() + + // add parametric rotation + if (typeof this.param === 'object') { + matrix.rotation = this.param.rotation + matrix.cx = this.param.cx + matrix.cy = this.param.cy + } + + return typeof o === 'string' ? matrix[o] : matrix + } + + // get current matrix + matrix = this instanceof SVG.FX && this.attrs.transform ? + this.attrs.transform : + new SVG.Matrix(target) + + // ensure relative flag + relative = !!relative || !!o.relative + + // act on matrix + if (o.a != null) { + matrix = relative ? + // relative + matrix.multiply(new SVG.Matrix(o)) : + // absolute + new SVG.Matrix(o) + + // act on rotation + } else if (o.rotation != null) { + // ensure centre point + ensureCentre(o, target) + + // relativize rotation value + if (relative) { + o.rotation += this.param && this.param.rotation != null ? + this.param.rotation : + matrix.extract().rotation + } + + // store parametric values + this.param = o + + // apply transformation + if (this instanceof SVG.Element) { + matrix = relative ? + // relative + matrix.rotate(o.rotation, o.cx, o.cy) : + // absolute + 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.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 + + if (!relative) { + // absolute; reset skew values + var e = matrix.extract() + matrix = matrix.multiply(new SVG.Matrix().skew(e.skewX, e.skewY, o.cx, o.cy).inverse()) + } + + matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy) + + // act on flip + } else if (o.flip) { + matrix = matrix.flip( + o.flip + , o.offset == null ? target.bbox()['c' + 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(this instanceof SVG.Pattern ? 'patternTransform' : this instanceof SVG.Gradient ? 'gradientTransform' : 'transform', matrix) + } +}) + +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(/\)\s*/).slice(0,-1).map(function(str){ + // generate key => value pairs + var kv = str.trim().split('(') + return [kv[0], kv[1].split(SVG.regex.matrixElements).map(function(str){ return parseFloat(str) })] + }) + // calculate 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 temp = parent.rect(1,1) + var pCtm = temp.screenCTM().inverse() + temp.remove() + + 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.extend(SVG.Element, { + // Dynamic style generator + style: function(s, v) { + if (arguments.length == 0) { + // get full style + return this.node.style.cssText || '' + + } else if (arguments.length < 2) { + // apply every style individually if an object is passed + if (typeof s == 'object') { + for (v in s) this.style(v, s[v]) + + } else if (SVG.regex.isCss.test(s)) { + // parse css string + s = s.split(';') + + // apply every definition individually + for (var i = 0; i < s.length; i++) { + v = s[i].split(':') + this.style(v[0].replace(/\s+/g, ''), v[1]) + } + } else { + // act as a getter if the first and only argument is not an object + return this.node.style[camelCase(s)] + } + + } else { + this.node.style[camelCase(s)] = v === null || SVG.regex.isBlank.test(v) ? '' : v + } + + return this + } +}) +SVG.Parent = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Element + + // Add class methods +, extend: { + // Returns all child elements + children: function() { + return SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(node) { + return SVG.adopt(node) + }) + } + // Add given element at a position + , add: function(element, i) { + if (!this.has(element)) { + // define insertion index if none given + i = i == null ? this.children().length : i + + // add element references + this.node.insertBefore(element.node, this.node.childNodes[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 + } + // 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 this.children().indexOf(element) + } + // Get a element at the given index + , get: function(i) { + return this.children()[i] + } + // Get first child, skipping the defs node + , first: function() { + return this.children()[0] + } + // Get the last child + , last: function() { + return this.children()[this.children().length - 1] + } + // Iterates over all children and invokes a given block + , each: function(block, deep) { + var i, il + , children = this.children() + + 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.Container)) + 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 + } + , // Get defs + defs: function() { + return this.doc().defs() + } + } + +}) + +SVG.extend(SVG.Parent, { + + ungroup: function(parent, depth) { + if(depth === 0 || this instanceof SVG.Defs) return this + + parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent)) + depth = depth || Infinity + + this.each(function(){ + if(this instanceof SVG.Defs) return this + if(this instanceof SVG.Parent) return this.ungroup(parent, depth-1) + return this.toParent(parent) + }) + + this.node.firstChild || this.remove() + + return this + }, + + flatten: function(parent, depth) { + return this.ungroup(parent, depth) + } + +}) +SVG.Container = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Parent + + // Add class methods +, extend: { + // Get the viewBox and calculate the zoom value + viewbox: function(v) { + if (arguments.length == 0) + // act as a getter if there are no arguments + return new SVG.ViewBox(this) + + // otherwise act as a setter + v = arguments.length == 1 ? + [v.x, v.y, v.width, v.height] : + [].slice.call(arguments) + + return this.attr('viewBox', v) + } + } + +}) +// Add events to elements +;[ 'click' + , 'dblclick' + , 'mousedown' + , 'mouseup' + , 'mouseover' + , 'mouseout' + , 'mousemove' + // , 'mouseenter' -> not supported by IE + // , 'mouseleave' -> not supported by IE + , 'touchstart' + , 'touchmove' + , 'touchleave' + , 'touchend' + , 'touchcancel' ].forEach(function(event) { + + // add event to SVG.Element + SVG.Element.prototype[event] = function(f) { + var self = this + + // bind event to element rather than element node + this.node['on' + event] = typeof f == 'function' ? + function() { return f.apply(self, arguments) } : null + + return this + } + +}) + +// Initialize listeners stack +SVG.listeners = [] +SVG.handlerMap = [] + +// Add event binder in the SVG namespace +SVG.on = function(node, event, listener, binding) { + // create listener, get object-index + var l = listener.bind(binding || node.instance || node) + , index = (SVG.handlerMap.indexOf(node) + 1 || SVG.handlerMap.push(node)) - 1 + , ev = event.split('.')[0] + , ns = event.split('.')[1] || '*' + + + // ensure valid object + SVG.listeners[index] = SVG.listeners[index] || {} + SVG.listeners[index][ev] = SVG.listeners[index][ev] || {} + SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {} + + // reference listener + SVG.listeners[index][ev][ns][listener] = l + + // add listener + node.addEventListener(ev, l, false) +} + +// Add event unbinder in the SVG namespace +SVG.off = function(node, event, listener) { + var index = SVG.handlerMap.indexOf(node) + , ev = event && event.split('.')[0] + , ns = event && event.split('.')[1] + + if(index == -1) return + + if (listener) { + // remove listener reference + if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) { + // remove listener + node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false) + + delete SVG.listeners[index][ev][ns || '*'][listener] + } + + } else if (ns && ev) { + // remove all listeners for a namespaced event + if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) { + for (listener in SVG.listeners[index][ev][ns]) + SVG.off(node, [ev, ns].join('.'), listener) + + delete SVG.listeners[index][ev][ns] + } + + } else if (ns){ + // remove all listeners for a specific namespace + for(event in SVG.listeners[index]){ + for(namespace in SVG.listeners[index][event]){ + if(ns === namespace){ + SVG.off(node, [event, ns].join('.')) + } + } + } + + } else if (ev) { + // remove all listeners for the event + if (SVG.listeners[index][ev]) { + for (namespace in SVG.listeners[index][ev]) + SVG.off(node, [ev, namespace].join('.')) + + delete SVG.listeners[index][ev] + } + + } else { + // remove all listeners on a given node + for (event in SVG.listeners[index]) + SVG.off(node, event) + + delete SVG.listeners[index] + + } +} + +// +SVG.extend(SVG.Element, { + // Bind given event to listener + on: function(event, listener, binding) { + SVG.on(this.node, event, listener, binding) + + return this + } + // Unbind event from listener +, off: function(event, listener) { + SVG.off(this.node, event, listener) + + return this + } + // Fire given event +, fire: function(event, data) { + + // Dispatch event + if(event instanceof Event){ + this.node.dispatchEvent(event) + }else{ + this.node.dispatchEvent(new CustomEvent(event, {detail:data})) + } + + return this + } +}) + +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: { + // 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.tbox().cx : this.x(x - this.tbox().width / 2) + } + // Move by center over y-axis + , cy: function(y) { + return y == null ? this.tbox().cy : this.y(y - this.tbox().height / 2) + } + , gbox: function() { + + var bbox = this.bbox() + , 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) + } + } +}) + +// ### 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) +, previous: function() { + return this.siblings()[this.position() - 1] + } + // Send given element one step forward +, forward: function() { + var i = this.position() + 1 + , 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 + } + +}) +SVG.Mask = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('mask')) + + // keep references to masked elements + this.targets = [] + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Unmask all masked elements and remove itself + remove: function() { + // unmask all targets + for (var i = this.targets.length - 1; i >= 0; i--) + if (this.targets[i]) + this.targets[i].unmask() + this.targets = [] + + // remove mask from parent + this.parent().removeElement(this) + + return this + } + } + + // 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 + this.masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element) + + // store reverence on self in mask + this.masker.targets.push(this) + + // apply mask + return this.attr('mask', 'url("#' + this.masker.attr('id') + '")') + } + // Unmask element +, unmask: function() { + delete this.masker + return this.attr('mask', null) + } + +}) + +SVG.ClipPath = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('clipPath')) + + // keep references to clipped elements + this.targets = [] + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Unclip all clipped elements and remove itself + remove: function() { + // unclip all targets + for (var i = this.targets.length - 1; i >= 0; i--) + if (this.targets[i]) + this.targets[i].unclip() + this.targets = [] + + // remove clipPath from parent + this.parent().removeElement(this) + + return this + } + } + + // 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 + this.clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element) + + // store reverence on self in mask + this.clipper.targets.push(this) + + // apply mask + return this.attr('clip-path', 'url("#' + this.clipper.attr('id') + '")') + } + // Unclip element +, unclip: function() { + delete this.clipper + return this.attr('clip-path', null) + } + +}) +SVG.Gradient = SVG.invent({ + // Initialize node + create: function(type) { + this.constructor.call(this, SVG.create(type + 'Gradient')) + + // store type + this.type = type + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Add a color stop + at: 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 + , fill: function() { + return 'url(#' + this.id() + ')' + } + // Alias string convertion to fill + , toString: function() { + return this.fill() + } + // 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 == 'radial' ? + 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 == 'radial' ? + 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 + } + } + +}) + +SVG.Pattern = SVG.invent({ + // Initialize node + create: 'pattern' + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Return the fill id + fill: 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.fill() + } + // 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' + }) + } + +}) +SVG.Doc = SVG.invent({ + // Initialize node + create: function(element) { + if (element) { + // ensure the presence of a dom element + element = typeof element == 'string' ? + document.getElementById(element) : + element + + // If the target is an svg element, use that element as the main wrapper. + // This allows svg.js to work with svg documents as well. + if (element.nodeName == 'svg') { + this.constructor.call(this, element) + } else { + this.constructor.call(this, SVG.create('svg')) + element.appendChild(this.node) + } + + // set svg element attributes and ensure defs node + this.namespace().size('100%', '100%').defs() + } + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Add namespaces + namespace: function() { + 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._defs) { + var defs + + // Find or create a defs element in this instance + if (defs = this.node.getElementsByTagName('defs')[0]) + this._defs = SVG.adopt(defs) + else + this._defs = new SVG.Defs + + // Make sure the defs node is at the end of the stack + this.node.appendChild(this._defs.node) + } + + return this._defs + } + // custom parent method + , parent: function() { + return this.node.parentNode.nodeName == '#document' ? null : this.node.parentNode + } + // Fix for possible sub-pixel offset. See: + // https://bugzilla.mozilla.org/show_bug.cgi?id=608812 + , spof: function(spof) { + var pos = this.node.getScreenCTM() + + if (pos) + this + .style('left', (-pos.e % 1) + 'px') + .style('top', (-pos.f % 1) + 'px') + + return this + } + + // Removes the doc from the DOM + , remove: function() { + if(this.parent()) { + this.parent().removeChild(this.node); + } + + return this; + } + } + +}) + +SVG.Shape = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Element + +}) + +SVG.Bare = SVG.invent({ + // Initialize + create: function(element, inherit) { + // construct element + this.constructor.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(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)) + } + // Add symbol element +, symbol: function() { + return this.defs().element('symbol', SVG.Container) + } + +}) +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.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) + } + } +}) +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.bbox(), width, height) + + return this + .rx(new SVG.Number(p.width).divide(2)) + .ry(new SVG.Number(p.height).divide(2)) + } +}) +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 (arguments.length == 4) + 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.bbox(), 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) { + return this.put(new SVG.Line).plot(x1, y1, x2, y2) + } + } +}) + +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) { + return this.put(new SVG.Polyline).plot(p) + } + } +}) + +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) { + return this.put(new SVG.Polygon).plot(p) + } + } +}) + +// 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 this.attr('points', (this._array = new SVG.PointArray(p))) + } + // 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.bbox(), 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) + } +}) +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 poly points + , plot: function(p) { + return this.attr('d', (this._array = new SVG.PathArray(p))) + } + // 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.bbox(), 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) { + return this.put(new SVG.Path).plot(d) + } + } +}) +SVG.Image = SVG.invent({ + // Initialize node + create: 'image' + + // Inherit from +, inherit: SVG.Shape + + // Add class methods +, extend: { + // (re)load image + load: function(url) { + if (!url) return this + + var self = this + , img = document.createElement('img') + + // preload image + img.onload = function() { + var p = self.parent(SVG.Pattern) + + if(p === null) return + + // ensure image size + if (self.width() == 0 && self.height() == 0) + self.size(img.width, img.height) + + // ensure pattern size if not set + if (p && p.width() == 0 && p.height() == 0) + p.size(self.width(), self.height()) + + // callback + if (typeof self._loaded === 'function') + self._loaded.call(self, { + width: img.width + , height: img.height + , ratio: img.width / img.height + , url: url + }) + } + + return this.attr('href', (img.src = this.src = url), SVG.xlink) + } + // Add loaded callback + , loaded: function(loaded) { + this._loaded = loaded + return this + } + } + + // Add parent method +, construct: { + // create image element, load image and set its size + image: function(source, width, height) { + return this.put(new SVG.Image).load(source).size(width || 0, height || width || 0) + } + } + +}) +SVG.Text = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, 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.Shape + + // Add class methods +, extend: { + clone: function(){ + // clone element and assign new id + var clone = assignNewId(this.node.cloneNode(true)) + + // insert the clone after myself + this.after(clone) + + return clone + } + // Move over x-axis + , x: function(x) { + // act as getter + if (x == null) + return this.attr('x') + + // move lines as well if no textPath is present + if (!this.textPath) + this.lines().each(function() { if (this.dom.newLined) this.x(x) }) + + return this.attr('x', x) + } + // Move over y-axis + , y: function(y) { + var oy = this.attr('y') + , 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 (typeof text === 'undefined'){ + var text = '' + var children = this.node.childNodes + for(var i = 0, len = children.length; i < len; ++i){ + + // add newline if its not the first child and newLined is set to true + if(i != 0 && 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 i = 0, il = text.length; i < il; i++) + this.tspan(text[i]).newLine() + } + + // disable build mode and rebuild lines + return this.build(false).rebuild() + } + // Set font size + , size: function(size) { + return this.attr('font-size', size).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() + } + // Get all the first level lines + , lines: function() { + // filter tspans and map them to SVG.js instances + var lines = SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(el){ + return SVG.adopt(el) + }) + + // return an instance of SVG.set + return new SVG.Set(lines) + } + // 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 + , blankLineOffset = 0 + , dy = this.dom.leading * new SVG.Number(this.attr('font-size')) + + this.lines().each(function() { + if (this.dom.newLined) { + if (!this.textPath) + 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.Shape + + // 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 hy¡n + 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 node = (this.textPath && this.textPath() || this).node + , tspan = new SVG.Tspan + + // clear if build mode is disabled + if (this._build === false) + this.clear() + + // add new tspan + node.appendChild(tspan.node) + + return tspan.text(text) + } + // Clear all lines +, clear: function() { + var node = (this.textPath && this.textPath() || this).node + + // remove existing child nodes + while (node.hasChildNodes()) + node.removeChild(node.lastChild) + + return this + } + // Get length of text element +, length: function() { + return this.node.getComputedTextLength() + } +}) + +SVG.TextPath = SVG.invent({ + // Initialize node + create: 'textPath' + + // Inherit from +, inherit: SVG.Element + + // Define parent class +, parent: SVG.Text + + // Add parent method +, construct: { + // Create path for text to run on + path: function(d) { + // create textPath element + var path = new SVG.TextPath + , track = this.doc().defs().path(d) + + // move lines to textpath + while (this.node.hasChildNodes()) + path.node.appendChild(this.node.firstChild) + + // add textPath element as child node + this.node.appendChild(path.node) + + // link textPath to path and add content + path.attr('href', '#' + track, SVG.xlink) + + return this + } + // Plot path if any + , plot: function(d) { + var track = this.track() + + if (track) + track.plot(d) + + return this + } + // Get the path track element + , track: function() { + var path = this.textPath() + + if (path) + return path.reference('href') + } + // Get the textPath child + , textPath: function() { + if (this.node.firstChild && this.node.firstChild.nodeName == 'textPath') + return SVG.adopt(this.node.firstChild) + } + } +}) +SVG.Nested = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('svg')) + + this.style('overflow', 'visible') + } + + // Inherit from +, inherit: SVG.Container + + // Add parent method +, construct: { + // Create nested svg document + nested: function() { + return this.put(new SVG.Nested) + } + } +}) +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 show attribute + , show: function(target) { + return this.attr('show', target, 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) + } + +}) +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 i, extension = {} + + extension[m] = function(o) { + 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 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) { + return this.transform({ flip: a, offset: o }) + } + // Map matrix to transform +, matrix: function(m) { + return this.attr('transform', new SVG.Matrix(m)) + } + // Opacity +, opacity: function(value) { + return this.attr('opacity', value) + } + // Relative move over x axis +, dx: function(x) { + return this.x((this.target || this).x() + x) + } + // Relative move over y axis +, dy: function(y) { + return this.y((this.target || this).y() + y) + } + // 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 == 'radial' || type == 'circle' ? + 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 this.node.getPointAtLength(length) + } +}) + +SVG.extend(SVG.Parent, SVG.Text, SVG.FX, { + // Set font + font: function(o) { + for (var k in o) + k == 'leading' ? + this.leading(o[k]) : + k == 'anchor' ? + this.attr('text-anchor', o[k]) : + k == 'size' || k == 'family' || k == 'weight' || k == 'stretch' || k == 'variant' || k == 'style' ? + this.attr('font-'+ k, o[k]) : + this.attr(k, o[k]) + + return this + } +}) + + +SVG.Set = SVG.invent({ + // Initialize + create: function(members) { + // Set initial state + Array.isArray(members) ? this.members = members : this.clear() + } + + // Add class methods +, extend: { + // Add element to set + add: function() { + var i, il, elements = [].slice.call(arguments) + + for (i = 0, il = elements.length; i < il; i++) + this.members.push(elements[i]) + + return this + } + // Remove element from set + , remove: function(element) { + var i = this.index(element) + + // remove given child + if (i > -1) + this.members.splice(i, 1) + + return this + } + // Iterate over all members + , each: function(block) { + for (var i = 0, il = this.members.length; i < il; i++) + block.apply(this.members[i], [i, this.members]) + + return this + } + // Restore to defaults + , clear: function() { + // initialize store + this.members = [] + + return this + } + // Get the length of a set + , length: function() { + return this.members.length + } + // Checks if a given element is present in set + , has: function(element) { + return this.index(element) >= 0 + } + // retuns index of given element in set + , index: function(element) { + return this.members.indexOf(element) + } + // Get member at given index + , get: function(i) { + return this.members[i] + } + // Get first member + , first: function() { + return this.get(0) + } + // Get last member + , last: function() { + return this.get(this.members.length - 1) + } + // Default value + , valueOf: function() { + return this.members + } + // Get the bounding box of all members included or empty box if set has no items + , bbox: function(){ + var box = new SVG.BBox() + + // return an empty box of there are no members + if (this.members.length == 0) + return box + + // get the first rbox and update the target bbox + var rbox = this.members[0].rbox() + box.x = rbox.x + box.y = rbox.y + box.width = rbox.width + box.height = rbox.height + + this.each(function() { + // user rbox for correct position and visual representation + box = box.merge(this.rbox()) + }) + + return box + } + } + + // Add parent method +, construct: { + // Create a new set + set: function(members) { + return new SVG.Set(members) + } + } +}) + +SVG.FX.Set = SVG.invent({ + // Initialize node + create: function(set) { + // store reference to set + this.set = set + } + +}) + +// Alias methods +SVG.Set.inherit = function() { + var m + , methods = [] + + // gather shape methods + for(var m in SVG.Shape.prototype) + if (typeof SVG.Shape.prototype[m] == 'function' && typeof SVG.Set.prototype[m] != 'function') + methods.push(m) + + // apply shape aliasses + methods.forEach(function(method) { + SVG.Set.prototype[method] = function() { + for (var i = 0, il = this.members.length; i < il; i++) + if (this.members[i] && typeof this.members[i][method] == 'function') + this.members[i][method].apply(this.members[i], arguments) + + return method == 'animate' ? (this.fx || (this.fx = new SVG.FX.Set(this))) : this + } + }) + + // clear methods for the next round + methods = [] + + // gather fx methods + for(var m in SVG.FX.prototype) + if (typeof SVG.FX.prototype[m] == 'function' && typeof SVG.FX.Set.prototype[m] != 'function') + methods.push(m) + + // apply fx aliasses + methods.forEach(function(method) { + SVG.FX.Set.prototype[method] = function() { + for (var i = 0, il = this.set.members.length; i < il; i++) + this.set.members[i].fx[method].apply(this.set.members[i].fx, arguments) + + return this + } + }) +} + + + + +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 + } +}) +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 v in k) + this.remember(v, k[v]) + + // retrieve memory + else if (arguments.length == 1) + return this.memory()[k] + + // store memory + else + 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 = {}) + } + +}) +// 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 new SVG.Set( + SVG.utils.map((parent || document).querySelectorAll(query), function(node) { + return SVG.adopt(node) + }) + ) +} + +SVG.extend(SVG.Parent, { + // Scoped select method + select: function(query) { + return SVG.select(query, this.node) + } + +}) +// 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(box, width, height) { + if (height == null) + height = box.height / box.width * width + else if (width == null) + width = box.width / box.height * height + + 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 +} + +// Convert string to matrix +function stringToMatrix(source) { + // remove matrix wrapper and split to individual numbers + source = source + .replace(SVG.regex.whitespace, '') + .replace(SVG.regex.matrix, '') + .split(SVG.regex.matrixElements) + + // convert string values to floats and convert to a matrix-formatted object + return arrayToMatrix( + SVG.utils.map(source, function(n) { + return parseFloat(n) + }) + ) +} + +// Calculate position according to from and to +function at(o, pos) { + // number recalculation (don't bother converting to SVG.Number for performance reasons) + return typeof o.from == 'number' ? + o.from + (o.to - o.from) * pos : + + // instance recalculation + o instanceof SVG.Color || o instanceof SVG.Number || o instanceof SVG.Matrix ? o.at(pos) : + + // for all other values wait until pos has reached 1 to return the final value + pos < 1 ? o.from : o.to +} + +// 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.childNodes.length - 1; i >= 0; i--) + if (node.childNodes[i] instanceof SVGElement) + assignNewId(node.childNodes[i]) + + return SVG.adopt(node).id(SVG.eid(node.nodeName)) +} + +// 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('') +// Add CustomEvent to IE9 and IE10 +if (typeof CustomEvent !== 'function') { + // Code from: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent + var CustomEvent = function(event, options) { + options = options || { bubbles: false, cancelable: false, detail: undefined } + var e = document.createEvent('CustomEvent') + e.initCustomEvent(event, options.bubbles, options.cancelable, options.detail) + return e + } + + CustomEvent.prototype = window.Event.prototype + + window.CustomEvent = CustomEvent +} + +// requestAnimationFrame / cancelAnimationFrame Polyfill with fallback based on Paul Irish +(function(w) { + var lastTime = 0 + var vendors = ['moz', 'webkit'] + + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame'] + w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame'] || + w[vendors[x] + 'CancelRequestAnimationFrame'] + } + + w.requestAnimationFrame = w.requestAnimationFrame || + function(callback) { + var currTime = new Date().getTime() + var timeToCall = Math.max(0, 16 - (currTime - lastTime)) + + var id = w.setTimeout(function() { + callback(currTime + timeToCall) + }, timeToCall) + + lastTime = currTime + timeToCall + return id + } + + w.cancelAnimationFrame = w.cancelAnimationFrame || w.clearTimeout; + +}(window)) + +return SVG + +})); \ No newline at end of file diff --git a/node_modules/svgjs/dist/svg.min.js b/node_modules/svgjs/dist/svg.min.js new file mode 100644 index 0000000..5e502ab --- /dev/null +++ b/node_modules/svgjs/dist/svg.min.js @@ -0,0 +1,2 @@ +/*! svg.js v2.2.5 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,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function i(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function r(t){return t.charAt(0).toUpperCase()+t.slice(1)}function s(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 o(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function a(t,e,n){return null==n?n=t.height/t.width*e:null==e&&(e=t.width/t.height*n),{width:e,height:n}}function h(t,e,n){return{x:e*t.a+n*t.c+0,y:e*t.b+n*t.d+0}}function u(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function l(t){return t instanceof y.Matrix||(t=new y.Matrix(t)),t}function c(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function f(t){return t=t.replace(y.regex.whitespace,"").replace(y.regex.matrix,"").split(y.regex.matrixElements),u(y.utils.map(t,function(t){return parseFloat(t)}))}function d(t,e){return"number"==typeof t.from?t.from+(t.to-t.from)*e:t instanceof y.Color||t instanceof y.Number||t instanceof y.Matrix?t.at(e):1>e?t.from:t.to}function p(t){for(var e=0,n=t.length,i="";n>e;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 m(t){for(var e=t.childNodes.length-1;e>=0;e--)t.childNodes[e]instanceof SVGElement&&m(t.childNodes[e]);return y.adopt(t).id(y.eid(t.nodeName))}function x(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 g(t){var e=t.toString().match(y.regex.reference);return e?e[1]:void 0}var y=this.SVG=function(t){return y.supported?(t=new y.Doc(t),y.parser||y.prepare(t),t):void 0};if(y.ns="http://www.w3.org/2000/svg",y.xmlns="http://www.w3.org/2000/xmlns/",y.xlink="http://www.w3.org/1999/xlink",y.svgjs="http://svgjs.com/svgjs",y.supported=function(){return!!e.createElementNS&&!!e.createElementNS(y.ns,"svg").createSVGRect}(),!y.supported)return!1;y.did=1e3,y.eid=function(t){return"Svgjs"+r(t)+y.did++},y.create=function(t){var n=e.createElementNS(this.ns,t);return n.setAttribute("id",this.eid(t)),n},y.extend=function(){var t,e,n,i;for(t=[].slice.call(arguments),e=t.pop(),i=t.length-1;i>=0;i--)if(t[i])for(n in e)t[i].prototype[n]=e[n];y.Set&&y.Set.inherit&&y.Set.inherit()},y.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,y.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&y.extend(e,t.extend),t.construct&&y.extend(t.parent||y.Container,t.construct),e},y.adopt=function(t){if(!t)return null;if(t.instance)return t.instance;var e;return e="svg"==t.nodeName?t.parentNode instanceof SVGElement?new y.Nested:new y.Doc:"linearGradient"==t.nodeName?new y.Gradient("linear"):"radialGradient"==t.nodeName?new y.Gradient("radial"):y[r(t.nodeName)]?new(y[r(t.nodeName)]):new y.Element(t),e.type=t.nodeName,e.node=t,t.instance=e,e instanceof y.Doc&&e.namespace().defs(),e.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}),e},y.prepare=function(t){var n=e.getElementsByTagName("body")[0],i=(n?new y.Doc(n):t.nested()).size(2,0),r=y.create("path");i.node.appendChild(r),y.parser={body:n||t.parent(),draw:i.style("opacity:0;position:fixed;left:100%;top:100%;overflow:hidden"),poly:i.polyline().node,path:r}},y.regex={unit:/^(-?[\d\.]+)([a-z%]{0,2})$/,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,matrix:/matrix\(|\)/g,matrixElements:/,*\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,negExp:/e\-/gi,comma:/,/g,hyphen:/\-/g,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,whitespaces:/\s+/,X:/X/g},y.utils={map:function(t,e){var n,i=t.length,r=[];for(n=0;i>n;n++)r.push(e(t[n]));return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(t){return[].filter.call(t,function(t){return t instanceof SVGElement})}},y.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"}},y.Color=function(t){var e;this.r=0,this.g=0,this.b=0,"string"==typeof t?y.regex.isRgb.test(t)?(e=y.regex.rgb.exec(t.replace(/\s/g,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):y.regex.isHex.test(t)&&(e=y.regex.hex.exec(s(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)},y.extend(y.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+o(this.r)+o(this.g)+o(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 y.Color(t),this},at:function(t){return this.destination?(t=0>t?0:t>1?1:t,new y.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}}),y.Color.test=function(t){return t+="",y.regex.isHex.test(t)||y.regex.isRgb.test(t)},y.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},y.Color.isColor=function(t){return y.Color.isRgb(t)||y.Color.test(t)},y.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},y.extend(y.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.lengtht;t++)-1==n.indexOf(this.value[t])&&n.push(this.value[t]);return this.value=n},at:function(t){if(!this.destination)return this;for(var e=0,n=this.value.length,i=[];n>e;e++)i.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new y.Array(i)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:this.split(t)},split:function(t){return t.trim().split(/\s+/)},reverse:function(){return this.value.reverse(),this}}),y.PointArray=function(t,e){this.constructor.call(this,t,e||[[0,0]])},y.PointArray.prototype=new y.Array,y.extend(y.PointArray,{toString:function(){for(var t=0,e=this.value.length,n=[];e>t;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=[];n>e;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 y.PointArray(i)},parse:function(t){if(t=t.valueOf(),Array.isArray(t))return t;t=this.split(t);for(var e,n=0,i=t.length,r=[];i>n;n++)e=t[n].split(","),r.push([parseFloat(e[0]),parseFloat(e[1])]);return r},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--)this.value[n][0]=(this.value[n][0]-i.x)*t/i.width+i.x,this.value[n][1]=(this.value[n][1]-i.y)*e/i.height+i.y;return this},bbox:function(){return y.parser.poly.setAttribute("points",this.toString()),y.parser.poly.getBBox()}}),y.PathArray=function(t,e){this.constructor.call(this,t,e||[["M",0,0]])},y.PathArray.prototype=new y.Array,y.extend(y.PathArray,{toString:function(){return p(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},parse:function(t){if(t instanceof y.PathArray)return t.valueOf();var e,n,i,r,s,o,a=0,h=0,u={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7};if("string"==typeof t){for(t=t.replace(y.regex.negExp,"X").replace(y.regex.pathLetters," $& ").replace(y.regex.hyphen," -").replace(y.regex.comma," ").replace(y.regex.X,"e-").trim().split(y.regex.whitespaces),e=t.length;--e;)if(t[e].indexOf(".")!=t[e].lastIndexOf(".")){var l=t[e].split("."),c=[l.shift(),l.shift()].join(".");t.splice.apply(t,[e,1].concat(c,l.map(function(t){return"."+t})))}}else t=t.reduce(function(t,e){return[].concat.apply(t,e)},[]);var o=[];do{for(y.regex.isPathLetter.test(t[0])?(r=t[0],t.shift()):"M"==r?r="L":"m"==r&&(r="l"),s=[r.toUpperCase()],e=0;et?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(y.regex.unit),e&&(this.value=parseFloat(e[1]),"%"==e[2]?this.value/=100:"s"==e[2]&&(this.value*=1e3),this.unit=e[2])):t instanceof y.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 new y.Number(this+new y.Number(t),this.unit)},minus:function(t){return this.plus(-new y.Number(t))},times:function(t){return new y.Number(this*new y.Number(t),this.unit)},divide:function(t){return new y.Number(this/new y.Number(t),this.unit)},to:function(t){var e=new y.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new y.Number(t),this},at:function(t){return this.destination?new y.Number(this.destination).minus(this).times(t).plus(this):this}}}),y.ViewBox=function(t){var e,n,i,r,s=1,o=1,a=t.bbox(),h=(t.attr("viewBox")||"").match(/-?[\d\.]+/g),u=t,l=t;for(i=new y.Number(t.width()),r=new y.Number(t.height());"%"==i.unit;)s*=i.value,i=new y.Number(u instanceof y.Doc?u.parent().offsetWidth:u.parent().width()),u=u.parent();for(;"%"==r.unit;)o*=r.value,r=new y.Number(l instanceof y.Doc?l.parent().offsetHeight:l.parent().height()),l=l.parent();this.x=a.x,this.y=a.y,this.width=i*s,this.height=r*o,this.zoom=1,h&&(e=parseFloat(h[0]),n=parseFloat(h[1]),i=parseFloat(h[2]),r=parseFloat(h[3]),this.zoom=this.width/this.height>i/r?this.height/r:this.width/i,this.x=e,this.y=n,this.width=i,this.height=r)},y.extend(y.ViewBox,{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}}),y.Element=y.invent({create:function(t){this._stroke=y.defaults.attrs.stroke,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this,this._stroke=t.getAttribute("stroke")||this._stroke)},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=a(this.bbox(),t,e);return this.width(new y.Number(n.width)).height(new y.Number(n.height))},clone:function(){var t=m(this.node.cloneNode(!0));return this.after(t),t},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t/,"").replace(/<\/svg>$/,"");n.innerHTML=""+t.replace(/\n/,"").replace(/<(\w+)([^<]+?)\/>/g,"<$1$2>")+"";for(var i=0,r=n.firstChild.childNodes.length;r>i;i++)this.node.appendChild(n.firstChild.firstChild);return this},writeDataToDom:function(){if(this.each||this.lines){var t=this.each?this:this.lines();t.each(function(){this.writeDataToDom()})}return 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}}}),y.FX=y.invent({create:function(t){this.target=t},extend:{animate:function(t,e,n){var i,r,s,o=this.target,a=this;return"object"==typeof t&&(n=t.delay,e=t.ease,t=t.duration),t="="==t?t:null==t?1e3:new y.Number(t).valueOf(),e=e||"<>",a.at=function(t){var n;if(t=0>t?0:t>1?1:t,null==i){i=[];for(s in a.attrs)i.push(s);if(o.morphArray&&(a.destination.plot||i.indexOf("points")>-1)){var h,u=new o.morphArray(a.destination.plot||a.attrs.points||o.array());a.destination.size&&u.size(a.destination.size.width.to,a.destination.size.height.to),h=u.bbox(),a.destination.x?u.move(a.destination.x.to,h.y):a.destination.cx&&u.move(a.destination.cx.to-h.width/2,h.y),h=u.bbox(),a.destination.y?u.move(h.x,a.destination.y.to):a.destination.cy&&u.move(h.x,a.destination.cy.to-h.height/2),a.destination={plot:o.array().morph(u)}}}if(null==r){r=[];for(s in a.styles)r.push(s)}for(t="<>"==e?-Math.cos(t*Math.PI)/2+.5:">"==e?Math.sin(t*Math.PI/2):"<"==e?-Math.cos(t*Math.PI/2)+1:"-"==e?t:"function"==typeof e?e(t):t,a.destination.plot?o.plot(a.destination.plot.at(t)):(a.destination.x?o.x(a.destination.x.at(t)):a.destination.cx&&o.cx(a.destination.cx.at(t)),a.destination.y?o.y(a.destination.y.at(t)):a.destination.cy&&o.cy(a.destination.cy.at(t)),a.destination.size&&o.size(a.destination.size.width.at(t),a.destination.size.height.at(t))),a.destination.viewbox&&o.viewbox(a.destination.viewbox.x.at(t),a.destination.viewbox.y.at(t),a.destination.viewbox.width.at(t),a.destination.viewbox.height.at(t)),a.destination.leading&&o.leading(a.destination.leading.at(t)),n=i.length-1;n>=0;n--)o.attr(i[n],d(a.attrs[i[n]],t));for(n=r.length-1;n>=0;n--)o.style(r[n],d(a.styles[r[n]],t));a.situation.during&&a.situation.during.call(o,t,function(e,n){return d({from:e,to:n},t)})},"number"==typeof t&&(this.timeout=setTimeout(function(){var i=(new Date).getTime();a.situation.start=i,a.situation.play=!0,a.situation.finish=i+t,a.situation.duration=t,a.situation.ease=e,a.render=function(){if(a.situation.play===!0){var i=(new Date).getTime(),r=i>a.situation.finish?1:(i-a.situation.start)/t;a.situation.reversing&&(r=-r+1),a.at(r),i>a.situation.finish?(a.destination.plot&&o.plot(new y.PointArray(a.destination.plot.destination).settle()),a.situation.loop===!0||"number"==typeof a.situation.loop&&a.situation.loop>0?(a.situation.reverse&&(a.situation.reversing=!a.situation.reversing),"number"==typeof a.situation.loop&&((!a.situation.reverse||a.situation.reversing)&&--a.situation.loop,a.situation.reverse||1!=a.situation.loop||--a.situation.loop),a.animate(t,e,n)):a.situation.after?a.situation.after.apply(o,[a]):a.stop()):a.animationFrame=requestAnimationFrame(a.render)}else a.animationFrame=requestAnimationFrame(a.render)},a.render()},new y.Number(n).valueOf())),this},bbox:function(){return this.target.bbox()},attr:function(t,e){if("object"==typeof t)for(var n in t)this.attr(n,t[n]);else{var i=this.target.attr(t);"transform"==t?(this.attrs[t]&&(e=this.attrs[t].destination.multiply(e)),this.attrs[t]=new y.Matrix(this.target).morph(e),this.param&&(e=this.target.transform("rotation"),this.attrs[t].param={from:this.target.param||{rotation:e,cx:this.param.cx,cy:this.param.cy},to:this.param})):this.attrs[t]=y.Color.isColor(e)?new y.Color(i).morph(e):y.regex.unit.test(e)?new y.Number(i).morph(e):{from:i,to:e}}return this},style:function(t,e){if("object"==typeof t)for(var n in t)this.style(n,t[n]);else this.styles[t]={from:this.target.style(t),to:e};return this},x:function(t){return this.destination.x=new y.Number(this.target.x()).morph(t),this},y:function(t){return this.destination.y=new y.Number(this.target.y()).morph(t),this},cx:function(t){return this.destination.cx=new y.Number(this.target.cx()).morph(t),this},cy:function(t){return this.destination.cy=new y.Number(this.target.cy()).morph(t),this},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 y.Text)this.attr("font-size",t);else{var n=this.target.bbox();this.destination.size={width:new y.Number(n.width).morph(t),height:new y.Number(n.height).morph(e)}}return this},plot:function(t){return this.destination.plot=t,this},leading:function(t){return this.target.destination.leading&&(this.destination.leading=new y.Number(this.target.destination.leading).morph(t)),this},viewbox:function(t,e,n,i){if(this.target instanceof y.Container){var r=this.target.viewbox();this.destination.viewbox={x:new y.Number(r.x).morph(t),y:new y.Number(r.y).morph(e),width:new y.Number(r.width).morph(n),height:new y.Number(r.height).morph(i)}}return this},update:function(t){return this.target instanceof y.Stop&&(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 y.Number(t.offset))),this},during:function(t){return this.situation.during=t,this},after:function(t){return this.situation.after=t,this},loop:function(t,e){return this.situation.loop=this.situation.loops=t||!0,this.situation.reverse=!!e,this},stop:function(t){return t===!0?(this.animate(0),this.situation.after&&this.situation.after.apply(this.target,[this])):(clearTimeout(this.timeout),cancelAnimationFrame(this.animationFrame),this.attrs={},this.styles={},this.situation={},this.destination={}),this},pause:function(){return this.situation.play===!0&&(this.situation.play=!1,this.situation.pause=(new Date).getTime()),this},play:function(){if(this.situation.play===!1){var t=(new Date).getTime()-this.situation.pause;this.situation.finish+=t,this.situation.start+=t,this.situation.play=!0}return this}},parent:y.Element,construct:{animate:function(t,e,n){return(this.fx||(this.fx=new y.FX(this))).stop().animate(t,e,n)},stop:function(t){return this.fx&&this.fx.stop(t),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this}}}),y.BBox=y.invent({create:function(t){if(t){var e;try{e=t.node.getBBox()}catch(n){if(t instanceof y.Shape){var i=t.clone().addTo(y.parser.draw);e=i.bbox(),i.remove()}else e={x:t.node.clientLeft,y:t.node.clientTop,width:t.node.clientWidth,height:t.node.clientHeight}}this.x=e.x,this.y=e.y,this.width=e.width,this.height=e.height}x(this)},parent:y.Element,construct:{bbox:function(){return new y.BBox(this)}}}),y.TBox=y.invent({create:function(t){if(t){var e=t.ctm().extract(),n=t.bbox();this.width=n.width*e.scaleX,this.height=n.height*e.scaleY,this.x=n.x+e.x,this.y=n.y+e.y}x(this)},parent:y.Element,construct:{tbox:function(){return new y.TBox(this)}}}),y.RBox=y.invent({create:function(e){if(e){var n=e.doc().parent(),i=e.node.getBoundingClientRect(),r=1;for(this.x=i.left,this.y=i.top,this.x-=n.offsetLeft,this.y-=n.offsetTop;n=n.offsetParent;)this.x-=n.offsetLeft,this.y-=n.offsetTop;for(n=e;n.parent&&(n=n.parent());)n.viewbox&&(r*=n.viewbox().zoom,this.x-=n.x()||0,this.y-=n.y()||0);this.width=i.width/=r,this.height=i.height/=r}x(this),this.x+=t.pageXOffset,this.y+=t.pageYOffset},parent:y.Element,construct:{rbox:function(){return new y.RBox(this)}}}),[y.BBox,y.TBox,y.RBox].forEach(function(t){y.extend(t,{merge:function(e){var n=new t;return n.x=Math.min(this.x,e.x),n.y=Math.min(this.y,e.y),n.width=Math.max(this.x+this.width,e.x+e.width)-n.x,n.height=Math.max(this.y+this.height,e.y+e.height)-n.y,x(n)}})}),y.Matrix=y.invent({create:function(t){var e,n=u([1,0,0,1,0,0]);for(t=t instanceof y.Element?t.matrixify():"string"==typeof t?f(t):6==arguments.length?u([].slice.call(arguments)):"object"==typeof t?t:n,e=b.length-1;e>=0;e--)this[b[e]]=t&&"number"==typeof t[b[e]]?t[b[e]]:n[b[e]]},extend:{extract:function(){var t=h(this,0,1),e=h(this,1,0),n=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,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}},clone:function(){return new y.Matrix(this)},morph:function(t){return this.destination=new y.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new y.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});if(this.param&&this.param.to){var n={rotation:this.param.from.rotation+(this.param.to.rotation-this.param.from.rotation)*t,cx:this.param.from.cx,cy:this.param.from.cy};e=e.rotate((this.param.to.rotation-2*this.param.from.rotation)*t,n.cx,n.cy),e.param=n}return e},multiply:function(t){return new y.Matrix(this.native().multiply(l(t).native()))},inverse:function(){return new y.Matrix(this.native().inverse())},translate:function(t,e){return new y.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,n,i){return(1==arguments.length||3==arguments.length)&&(e=t),3==arguments.length&&(i=n,n=e),this.around(n,i,new y.Matrix(t,0,0,e,0,0))},rotate:function(t,e,n){return t=y.utils.radians(t),this.around(e,n,new y.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):this.scale(1,-1,0,e)},skew:function(t,e,n,i){return this.around(n,i,this.native().skewX(t||0).skewY(e||0))},skewX:function(t,e,n){return this.around(e,n,this.native().skewX(t||0))},skewY:function(t,e,n){return this.around(e,n,this.native().skewY(t||0))},around:function(t,e,n){return this.multiply(new y.Matrix(1,0,0,1,t||0,e||0)).multiply(n).multiply(new y.Matrix(1,0,0,1,-t||0,-e||0))},"native":function(){for(var t=y.parser.draw.node.createSVGMatrix(),e=b.length-1;e>=0;e--)t[b[e]]=this[b[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:y.Element,construct:{ctm:function(){return new y.Matrix(this.node.getCTM())},screenCTM:function(){return new y.Matrix(this.node.getScreenCTM())}}}),y.Point=y.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!=e?{x:t,y:e}:i,this.x=n.x,this.y=n.y},extend:{clone:function(){return new y.Point(this)},morph:function(t){return this.destination=new y.Point(t),this},at:function(t){if(!this.destination)return this;var e=new y.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},"native":function(){var t=y.parser.draw.node.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new y.Point(this.native().matrixTransform(t.native()))}}}),y.extend(y.Element,{point:function(t,e){return new y.Point(t,e).transform(this.screenCTM().inverse())}}),y.extend(y.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]=y.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?y.defaults.attrs[t]:y.regex.isNumber.test(e)?parseFloat(e):e;"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),("fill"==t||"stroke"==t)&&(y.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof y.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new y.Number(e):y.Color.isColor(e)?e=new y.Color(e):Array.isArray(e)?e=new y.Array(e):e instanceof y.Matrix&&e.param&&(this.param=e.param),"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}}),y.extend(y.Element,y.FX,{transform:function(t,e){var n,i=this.target||this;if("object"!=typeof t)return n=new y.Matrix(i).extract(),"object"==typeof this.param&&(n.rotation=this.param.rotation,n.cx=this.param.cx,n.cy=this.param.cy),"string"==typeof t?n[t]:n;if(n=this instanceof y.FX&&this.attrs.transform?this.attrs.transform:new y.Matrix(i),e=!!e||!!t.relative,null!=t.a)n=e?n.multiply(new y.Matrix(t)):new y.Matrix(t);else if(null!=t.rotation)c(t,i),e&&(t.rotation+=this.param&&null!=this.param.rotation?this.param.rotation:n.extract().rotation),this.param=t,this instanceof y.Element&&(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(c(t,i),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 r=n.extract();t.scaleX=1*t.scaleX/r.scaleX,t.scaleY=1*t.scaleY/r.scaleY}n=n.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skewX||null!=t.skewY){if(c(t,i),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,!e){var r=n.extract();n=n.multiply((new y.Matrix).skew(r.skewX,r.skewY,t.cx,t.cy).inverse())}n=n.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?n=n.flip(t.flip,null==t.offset?i.bbox()["c"+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(this instanceof y.Pattern?"patternTransform":this instanceof y.Gradient?"gradientTransform":"transform",n)}}),y.extend(y.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(/\)\s*/).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(y.regex.matrixElements).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"==e[0]?t.multiply(u(e[1])):t[e[0]].apply(t,e[1])},new y.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),n=t.rect(1,1),i=n.screenCTM().inverse();return n.remove(),this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),y.extend(y.Element,{style:function(t,e){if(0==arguments.length)return this.node.style.cssText||"";if(arguments.length<2)if("object"==typeof t)for(e in t)this.style(e,t[e]);else{if(!y.regex.isCss.test(t))return this.node.style[i(t)];t=t.split(";");for(var n=0;n=0},index:function(t){return this.children().indexOf(t)},get:function(t){return this.children()[t]},first:function(){return this.children()[0]},last:function(){return this.children()[this.children().length-1]},each:function(t,e){var n,i,r=this.children();for(n=0,i=r.length;i>n;n++)r[n]instanceof y.Element&&t.apply(r[n],[n,r]),e&&r[n]instanceof y.Container&&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},defs:function(){return this.doc().defs()}}}),y.extend(y.Parent,{ungroup:function(t,e){return 0===e||this instanceof y.Defs?this:(t=t||(this instanceof y.Doc?this:this.parent(y.Parent)),e=e||1/0,this.each(function(){return this instanceof y.Defs?this:this instanceof y.Parent?this.ungroup(t,e-1):this.toParent(t)}),this.node.firstChild||this.remove(),this)},flatten:function(t,e){return this.ungroup(t,e) +}}),y.Container=y.invent({create:function(t){this.constructor.call(this,t)},inherit:y.Parent,extend:{viewbox:function(t){return 0==arguments.length?new y.ViewBox(this):(t=1==arguments.length?[t.x,t.y,t.width,t.height]:[].slice.call(arguments),this.attr("viewBox",t))}}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){y.Element.prototype[t]=function(e){var n=this;return this.node["on"+t]="function"==typeof e?function(){return e.apply(n,arguments)}:null,this}}),y.listeners=[],y.handlerMap=[],y.on=function(t,e,n,i){var r=n.bind(i||t.instance||t),s=(y.handlerMap.indexOf(t)+1||y.handlerMap.push(t))-1,o=e.split(".")[0],a=e.split(".")[1]||"*";y.listeners[s]=y.listeners[s]||{},y.listeners[s][o]=y.listeners[s][o]||{},y.listeners[s][o][a]=y.listeners[s][o][a]||{},y.listeners[s][o][a][n]=r,t.addEventListener(o,r,!1)},y.off=function(t,e,n){var i=y.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1];if(-1!=i)if(n)y.listeners[i][r]&&y.listeners[i][r][s||"*"]&&(t.removeEventListener(r,y.listeners[i][r][s||"*"][n],!1),delete y.listeners[i][r][s||"*"][n]);else if(s&&r){if(y.listeners[i][r]&&y.listeners[i][r][s]){for(n in y.listeners[i][r][s])y.off(t,[r,s].join("."),n);delete y.listeners[i][r][s]}}else if(s)for(e in y.listeners[i])for(namespace in y.listeners[i][e])s===namespace&&y.off(t,[e,s].join("."));else if(r){if(y.listeners[i][r]){for(namespace in y.listeners[i][r])y.off(t,[r,namespace].join("."));delete y.listeners[i][r]}}else{for(e in y.listeners[i])y.off(t,e);delete y.listeners[i]}},y.extend(y.Element,{on:function(t,e,n){return y.on(this.node,t,e,n),this},off:function(t,e){return y.off(this.node,t,e),this},fire:function(t,e){return t instanceof Event?this.node.dispatchEvent(t):this.node.dispatchEvent(new w(t,{detail:e})),this}}),y.Defs=y.invent({create:"defs",inherit:y.Container}),y.G=y.invent({create:"g",inherit:y.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.tbox().cx:this.x(t-this.tbox().width/2)},cy:function(t){return null==t?this.tbox().cy:this.y(t-this.tbox().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 y.G)}}}),y.extend(y.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},previous: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 y.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 y.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}}),y.Mask=y.invent({create:function(){this.constructor.call(this,y.create("mask")),this.targets=[]},inherit:y.Container,extend:{remove:function(){for(var t=this.targets.length-1;t>=0;t--)this.targets[t]&&this.targets[t].unmask();return this.targets=[],this.parent().removeElement(this),this}},construct:{mask:function(){return this.defs().put(new y.Mask)}}}),y.extend(y.Element,{maskWith:function(t){return this.masker=t instanceof y.Mask?t:this.parent().mask().add(t),this.masker.targets.push(this),this.attr("mask",'url("#'+this.masker.attr("id")+'")')},unmask:function(){return delete this.masker,this.attr("mask",null)}}),y.ClipPath=y.invent({create:function(){this.constructor.call(this,y.create("clipPath")),this.targets=[]},inherit:y.Container,extend:{remove:function(){for(var t=this.targets.length-1;t>=0;t--)this.targets[t]&&this.targets[t].unclip();return this.targets=[],this.parent().removeElement(this),this}},construct:{clip:function(){return this.defs().put(new y.ClipPath)}}}),y.extend(y.Element,{clipWith:function(t){return this.clipper=t instanceof y.ClipPath?t:this.parent().clip().add(t),this.clipper.targets.push(this),this.attr("clip-path",'url("#'+this.clipper.attr("id")+'")')},unclip:function(){return delete this.clipper,this.attr("clip-path",null)}}),y.Gradient=y.invent({create:function(t){this.constructor.call(this,y.create(t+"Gradient")),this.type=t},inherit:y.Container,extend:{at:function(t,e,n){return this.put(new y.Stop).update(t,e,n)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,n){return"transform"==t&&(t="gradientTransform"),y.Container.prototype.attr.call(this,t,e,n)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),y.extend(y.Gradient,y.FX,{from:function(t,e){return"radial"==(this.target||this).type?this.attr({fx:new y.Number(t),fy:new y.Number(e)}):this.attr({x1:new y.Number(t),y1:new y.Number(e)})},to:function(t,e){return"radial"==(this.target||this).type?this.attr({cx:new y.Number(t),cy:new y.Number(e)}):this.attr({x2:new y.Number(t),y2:new y.Number(e)})}}),y.extend(y.Defs,{gradient:function(t,e){return this.put(new y.Gradient(t)).update(e)}}),y.Stop=y.invent({create:"stop",inherit:y.Element,extend:{update:function(t){return("number"==typeof t||t instanceof y.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 y.Number(t.offset)),this}}}),y.Pattern=y.invent({create:"pattern",inherit:y.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,n){return"transform"==t&&(t="patternTransform"),y.Container.prototype.attr.call(this,t,e,n)}},construct:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}}}),y.extend(y.Defs,{pattern:function(t,e,n){return this.put(new y.Pattern).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),y.Doc=y.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,y.create("svg")),t.appendChild(this.node)),this.namespace().size("100%","100%").defs())},inherit:y.Container,extend:{namespace:function(){return this.attr({xmlns:y.ns,version:"1.1"}).attr("xmlns:xlink",y.xlink,y.xmlns).attr("xmlns:svgjs",y.svgjs,y.xmlns)},defs:function(){if(!this._defs){var t;this._defs=(t=this.node.getElementsByTagName("defs")[0])?y.adopt(t):new y.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(){var t=this.node.getScreenCTM();return t&&this.style("left",-t.e%1+"px").style("top",-t.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this}}}),y.Shape=y.invent({create:function(t){this.constructor.call(this,t)},inherit:y.Element}),y.Bare=y.invent({create:function(t,e){if(this.constructor.call(this,y.create(t)),e)for(var n in e.prototype)"function"==typeof e.prototype[n]&&(this[n]=e.prototype[n])},inherit:y.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),y.extend(y.Parent,{element:function(t,e){return this.put(new y.Bare(t,e))},symbol:function(){return this.defs().element("symbol",y.Container)}}),y.Use=y.invent({create:"use",inherit:y.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,y.xlink)}},construct:{use:function(t,e){return this.put(new y.Use).element(t,e)}}}),y.Rect=y.invent({create:"rect",inherit:y.Shape,construct:{rect:function(t,e){return this.put(new y.Rect).size(t,e)}}}),y.Circle=y.invent({create:"circle",inherit:y.Shape,construct:{circle:function(t){return this.put(new y.Circle).rx(new y.Number(t).divide(2)).move(0,0)}}}),y.extend(y.Circle,y.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),y.Ellipse=y.invent({create:"ellipse",inherit:y.Shape,construct:{ellipse:function(t,e){return this.put(new y.Ellipse).size(t,e).move(0,0)}}}),y.extend(y.Ellipse,y.Rect,y.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),y.extend(y.Circle,y.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 y.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new y.Number(t).divide(2))},size:function(t,e){var n=a(this.bbox(),t,e);return this.rx(new y.Number(n.width).divide(2)).ry(new y.Number(n.height).divide(2))}}),y.Line=y.invent({create:"line",inherit:y.Shape,extend:{array:function(){return new y.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,n,i){return t=4==arguments.length?{x1:t,y1:e,x2:n,y2:i}:new y.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=a(this.bbox(),t,e);return this.attr(this.array().size(n.width,n.height).toLine())}},construct:{line:function(t,e,n,i){return this.put(new y.Line).plot(t,e,n,i)}}}),y.Polyline=y.invent({create:"polyline",inherit:y.Shape,construct:{polyline:function(t){return this.put(new y.Polyline).plot(t)}}}),y.Polygon=y.invent({create:"polygon",inherit:y.Shape,construct:{polygon:function(t){return this.put(new y.Polygon).plot(t)}}}),y.extend(y.Polyline,y.Polygon,{array:function(){return this._array||(this._array=new y.PointArray(this.attr("points")))},plot:function(t){return this.attr("points",this._array=new y.PointArray(t))},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var n=a(this.bbox(),t,e);return this.attr("points",this.array().size(n.width,n.height))}}),y.extend(y.Line,y.Polyline,y.Polygon,{morphArray:y.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)}}),y.Path=y.invent({create:"path",inherit:y.Shape,extend:{morphArray:y.PathArray,array:function(){return this._array||(this._array=new y.PathArray(this.attr("d")))},plot:function(t){return this.attr("d",this._array=new y.PathArray(t))},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=a(this.bbox(),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 y.Path).plot(t)}}}),y.Image=y.invent({create:"image",inherit:y.Shape,extend:{load:function(t){if(!t)return this;var n=this,i=e.createElement("img");return i.onload=function(){var e=n.parent(y.Pattern);null!==e&&(0==n.width()&&0==n.height()&&n.size(i.width,i.height),e&&0==e.width()&&0==e.height()&&e.size(n.width(),n.height()),"function"==typeof n._loaded&&n._loaded.call(n,{width:i.width,height:i.height,ratio:i.width/i.height,url:t}))},this.attr("href",i.src=this.src=t,y.xlink)},loaded:function(t){return this._loaded=t,this}},construct:{image:function(t,e,n){return this.put(new y.Image).load(t).size(e||0,n||e||0)}}}),y.Text=y.invent({create:function(){this.constructor.call(this,y.create("text")),this.dom.leading=new y.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",y.defaults.attrs["font-family"])},inherit:y.Shape,extend:{clone:function(){var t=m(this.node.cloneNode(!0));return this.after(t),t},x:function(t){return null==t?this.attr("x"):(this.textPath||this.lines().each(function(){this.dom.newLined&&this.x(t)}),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("undefined"==typeof t){for(var t="",e=this.node.childNodes,n=0,i=e.length;i>n;++n)0!=n&&3!=e[n].nodeType&&1==y.adopt(e[n]).dom.newLined&&(t+="\n"),t+=e[n].textContent;return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var n=0,r=t.length;r>n;n++)this.tspan(t[n]).newLine()}return this.build(!1).rebuild()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new y.Number(t),this.rebuild())},lines:function(){var t=y.utils.map(y.utils.filterSVGElements(this.node.childNodes),function(t){return y.adopt(t)});return new y.Set(t)},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,n=0,i=this.dom.leading*new y.Number(this.attr("font-size"));this.lines().each(function(){this.dom.newLined&&(this.textPath||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 y.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new y.Text).text(t)},plain:function(t){return this.put(new y.Text).plain(t)}}}),y.Tspan=y.invent({create:"tspan",inherit:y.Shape,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(y.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),y.extend(y.Text,y.Tspan,{plain:function(t){return this._build===!1&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=(this.textPath&&this.textPath()||this).node,n=new y.Tspan;return this._build===!1&&this.clear(),e.appendChild(n.node),n.text(t)},clear:function(){for(var t=(this.textPath&&this.textPath()||this).node;t.hasChildNodes();)t.removeChild(t.lastChild);return this},length:function(){return this.node.getComputedTextLength()}}),y.TextPath=y.invent({create:"textPath",inherit:y.Element,parent:y.Text,construct:{path:function(t){for(var e=new y.TextPath,n=this.doc().defs().path(t);this.node.hasChildNodes();)e.node.appendChild(this.node.firstChild);return this.node.appendChild(e.node),e.attr("href","#"+n,y.xlink),this},plot:function(t){var e=this.track();return e&&e.plot(t),this},track:function(){var t=this.textPath();return t?t.reference("href"):void 0},textPath:function(){return this.node.firstChild&&"textPath"==this.node.firstChild.nodeName?y.adopt(this.node.firstChild):void 0}}}),y.Nested=y.invent({create:function(){this.constructor.call(this,y.create("svg")),this.style("overflow","visible")},inherit:y.Container,construct:{nested:function(){return this.put(new y.Nested)}}}),y.A=y.invent({create:"a",inherit:y.Container,extend:{to:function(t){return this.attr("href",t,y.xlink)},show:function(t){return this.attr("show",t,y.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new y.A).to(t)}}}),y.extend(y.Element,{linkTo:function(t){var e=new y.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),y.Marker=y.invent({create:"marker",inherit:y.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)}}}),y.extend(y.Defs,{marker:function(t,e,n){return this.put(new y.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(n)}}),y.extend(y.Line,y.Polyline,y.Polygon,y.Path,{marker:function(t,e,n,i){var r=["marker"];return"all"!=t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof y.Marker?arguments[1]:this.doc().marker(e,n,i),this.attr(r,t)}});var v={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("string"==typeof n||y.Color.isRgb(n)||n&&"function"==typeof n.fill)this.attr(t,n);else for(e=v[t].length-1;e>=0;e--)null!=n[v[t][e]]&&this.attr(v.prefix(t,v[t][e]),n[v[t][e]]);return this},y.extend(y.Element,y.FX,n)}),y.extend(y.Element,y.FX,{rotate:function(t,e,n){return this.transform({rotation:t,cx:e,cy:n})},skew:function(t,e,n,i){return 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 this.transform({flip:t,offset:e})},matrix:function(t){return this.attr("transform",new y.Matrix(t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x((this.target||this).x()+t)},dy:function(t){return this.y((this.target||this).y()+t)},dmove:function(t,e){return this.dx(t).dy(e)}}),y.extend(y.Rect,y.Ellipse,y.Circle,y.Gradient,y.FX,{radius:function(t,e){var n=(this.target||this).type;return"radial"==n||"circle"==n?this.attr({r:new y.Number(t)}):this.rx(t).ry(null==e?t:e)}}),y.extend(y.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return this.node.getPointAtLength(t)}}),y.extend(y.Parent,y.Text,y.FX,{font:function(t){for(var e in t)"leading"==e?this.leading(t[e]):"anchor"==e?this.attr("text-anchor",t[e]):"size"==e||"family"==e||"weight"==e||"stretch"==e||"variant"==e||"style"==e?this.attr("font-"+e,t[e]):this.attr(e,t[e]);return this}}),y.Set=y.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){var t,e,n=[].slice.call(arguments);for(t=0,e=n.length;e>t;t++)this.members.push(n[t]);return this},remove:function(t){var e=this.index(t);return e>-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,n=this.members.length;n>e;e++)t.apply(this.members[e],[e,this.members]);return this},clear:function(){return this.members=[],this},length:function(){return this.members.length},has:function(t){return this.index(t)>=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members},bbox:function(){var t=new y.BBox;if(0==this.members.length)return t;var e=this.members[0].rbox();return t.x=e.x,t.y=e.y,t.width=e.width,t.height=e.height,this.each(function(){t=t.merge(this.rbox())}),t}},construct:{set:function(t){return new y.Set(t)}}}),y.FX.Set=y.invent({create:function(t){this.set=t}}),y.Set.inherit=function(){var t,e=[];for(var t in y.Shape.prototype)"function"==typeof y.Shape.prototype[t]&&"function"!=typeof y.Set.prototype[t]&&e.push(t);e.forEach(function(t){y.Set.prototype[t]=function(){for(var e=0,n=this.members.length;n>e;e++)this.members[e]&&"function"==typeof this.members[e][t]&&this.members[e][t].apply(this.members[e],arguments);return"animate"==t?this.fx||(this.fx=new y.FX.Set(this)):this}}),e=[];for(var t in y.FX.prototype)"function"==typeof y.FX.prototype[t]&&"function"!=typeof y.FX.Set.prototype[t]&&e.push(t);e.forEach(function(t){y.FX.Set.prototype[t]=function(){for(var e=0,n=this.set.members.length;n>e;e++)this.set.members[e].fx[t].apply(this.set.members[e].fx,arguments);return this}})},y.extend(y.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(i){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:n===!0||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this}}),y.extend(y.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var e in t)this.remember(e,t[e]);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={})}}),y.get=function(t){var n=e.getElementById(g(t)||t);return y.adopt(n)},y.select=function(t,n){return new y.Set(y.utils.map((n||e).querySelectorAll(t),function(t){return y.adopt(t)}))},y.extend(y.Parent,{select:function(t){return y.select(t,this.node)}});var b="abcdef".split("");if("function"!=typeof w){var w=function(t,n){n=n||{bubbles:!1,cancelable:!1,detail:void 0};var i=e.createEvent("CustomEvent");return i.initCustomEvent(t,n.bubbles,n.cancelable,n.detail),i};w.prototype=t.Event.prototype,t.CustomEvent=w}return function(e){for(var n=0,i=["moz","webkit"],r=0;r - <%= pkg.description %>' + , '* @version <%= pkg.version %>' + , '* <%= pkg.homepage %>' + , '*' + , '* @copyright <%= pkg.author %>' + , '* @license <%= pkg.license %>' + , '*' + , '* BUILT: <%= pkg.buildDate %>' + , '*/;' + , ''].join('\n') + +var headerShort = '/*! <%= pkg.name %> v<%= pkg.version %> <%= pkg.license %>*/;' + +// all files in the right order (currently we don't use any dependency management system) +var parts = [ + 'src/svg.js' +, 'src/regex.js' +, 'src/utilities.js' +, 'src/default.js' +, 'src/color.js' +, 'src/array.js' +, 'src/pointarray.js' +, 'src/patharray.js' +, 'src/number.js' +, 'src/viewbox.js' +, 'src/element.js' +, 'src/fx.js' +, 'src/boxes.js' +, 'src/matrix.js' +, 'src/point.js' +, 'src/attr.js' +, 'src/transform.js' +, 'src/style.js' +, 'src/parent.js' +, 'src/ungroup.js' +, 'src/container.js' +, 'src/event.js' +, 'src/defs.js' +, 'src/group.js' +, 'src/arrange.js' +, 'src/mask.js' +, 'src/clip.js' +, 'src/gradient.js' +, 'src/pattern.js' +, 'src/doc.js' +, 'src/shape.js' +, 'src/bare.js' +, 'src/use.js' +, 'src/rect.js' +, 'src/ellipse.js' +, 'src/line.js' +, 'src/poly.js' +, 'src/pointed.js' +, 'src/path.js' +, 'src/image.js' +, 'src/text.js' +, 'src/textpath.js' +, 'src/nested.js' +, 'src/hyperlink.js' +, 'src/marker.js' +, 'src/sugar.js' +, 'src/set.js' +, 'src/data.js' +, 'src/memory.js' +, 'src/selector.js' +, 'src/helpers.js' +, 'src/polyfill.js' +] + +gulp.task('clean', function(cb) { + del([ 'dist/*' ], cb); +}) + +/** + * 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() { + pkg.buildDate = Date() + return gulp.src(parts) + .pipe(concat('svg.js', { newLine: '\n' })) + // 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(644)) + .pipe(gulp.dest('dist')) + .pipe(size({ showFiles: true, title: 'Full' })) +}) + +/** + ‎* uglify the file and show the size of the result + * add the license info + * show the gzipped file size + */ +gulp.task('minify', ['unify'], function() { + return gulp.src('dist/svg.js') + .pipe(uglify()) + .pipe(rename({ suffix:'.min' })) + .pipe(size({ showFiles: true, title: 'Minified' })) + .pipe(header(headerShort, { pkg: pkg })) + .pipe(chmod(644)) + .pipe(gulp.dest('dist')) + .pipe(size({ showFiles: true, gzip: true, title: 'Gzipped' })) +}) + +/** + ‎* rebuild documentation using documentup + */ + +gulp.task('docs', function() { + fs.readFile('README.md', 'utf8', function (err, data) { + request.post( + 'http://documentup.com/compiled' + , { form: { content: data, name: 'SVG.js', theme: 'v1' } } + , function (error, response, body) { + // Replace stylesheet + body = body.replace('//documentup.com/stylesheets/themes/v1.css', 'svgjs.css') + + // Write file + fs.writeFile('docs/index.html', body, function(err) {}) + } + ) + }) +}) + +gulp.task('default', ['clean', 'unify', 'minify'], function() {}) + + + + + diff --git a/node_modules/svgjs/package.json b/node_modules/svgjs/package.json new file mode 100644 index 0000000..31977c8 --- /dev/null +++ b/node_modules/svgjs/package.json @@ -0,0 +1,123 @@ +{ + "_args": [ + [ + { + "raw": "svgjs@^2.2.5", + "scope": null, + "escapedName": "svgjs", + "name": "svgjs", + "rawSpec": "^2.2.5", + "spec": ">=2.2.5 <3.0.0", + "type": "range" + }, + "/Users/yjh/web/annotation_viewer/node_modules/synyi-annotation-tool" + ] + ], + "_from": "svgjs@>=2.2.5 <3.0.0", + "_id": "svgjs@2.2.5", + "_inCache": true, + "_installable": true, + "_location": "/svgjs", + "_nodeVersion": "5.2.0", + "_npmUser": { + "name": "ar7", + "email": "aria@fallah.us" + }, + "_npmVersion": "3.5.2", + "_phantomChildren": {}, + "_requested": { + "raw": "svgjs@^2.2.5", + "scope": null, + "escapedName": "svgjs", + "name": "svgjs", + "rawSpec": "^2.2.5", + "spec": ">=2.2.5 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/synyi-annotation-tool" + ], + "_resolved": "https://registry.npmjs.org/svgjs/-/svgjs-2.2.5.tgz", + "_shasum": "874a3993500f9dfff56c2a322975d24f4f61caff", + "_shrinkwrap": null, + "_spec": "svgjs@^2.2.5", + "_where": "/Users/yjh/web/annotation_viewer/node_modules/synyi-annotation-tool", + "author": { + "name": "Wout Fierens", + "email": "wout@impinc.co.uk" + }, + "bugs": { + "url": "https://github.com/wout/svg.js/issues" + }, + "dependencies": {}, + "description": "A lightweight library for manipulating and animating SVG.", + "devDependencies": { + "del": "^1.2.0", + "gulp": "^3.8.6", + "gulp-chmod": "^1.2.0", + "gulp-concat": "^2.3.3", + "gulp-header": "^1.0.5", + "gulp-jasmine": "^0.3.0", + "gulp-rename": "^1.2.0", + "gulp-size": "^0.4.0", + "gulp-trimlines": "^1.0.0", + "gulp-uglify": "^0.3.1", + "gulp-wrap": "^0.11.0", + "request": "^2.37.0" + }, + "directories": {}, + "dist": { + "shasum": "874a3993500f9dfff56c2a322975d24f4f61caff", + "tarball": "https://registry.npmjs.org/svgjs/-/svgjs-2.2.5.tgz" + }, + "gitHead": "002414dcb0fec12f671c75530245160f6c674a6f", + "github": "https://github.com/wout/svg.js", + "homepage": "http://www.svgjs.com", + "jam": { + "include": [ + "dist/svg.js", + "README.md", + "LICENSE.txt" + ] + }, + "keywords": [ + "svg", + "vector", + "graphics", + "animation" + ], + "license": "MIT", + "licenses": [ + { + "type": "MIT", + "url": "http://www.opensource.org/licenses/mit-license.php" + } + ], + "main": "dist/svg.js", + "maintainers": [ + { + "name": "Wout Fierens", + "email": "wout@svgjs.com", + "url": "http://svgjs.com" + }, + { + "name": "Alex Ewerlöf", + "email": "alex@userpixel.com", + "url": "http://www.ewerlof.name" + }, + { + "name": "Ulrich-Matthias Schäfer", + "email": "ulima.ums@googlemail.com" + } + ], + "name": "svgjs", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/wout/svg.js.git" + }, + "scripts": {}, + "url": "http://svgjs.com", + "version": "2.2.5" +} diff --git a/node_modules/svgjs/spec/index.html b/node_modules/svgjs/spec/index.html new file mode 100644 index 0000000..526cda6 --- /dev/null +++ b/node_modules/svgjs/spec/index.html @@ -0,0 +1,120 @@ + + + + SVG.js - Jasmine Spec Runner + + + + + + + + + + + Some description + + + + + + + + + + + A + B + C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/boot.js b/node_modules/svgjs/spec/lib/jasmine-2.0.1/boot.js new file mode 100644 index 0000000..ec8baa0 --- /dev/null +++ b/node_modules/svgjs/spec/lib/jasmine-2.0.1/boot.js @@ -0,0 +1,181 @@ +/** + Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. + + If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. + + The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. + + [jasmine-gem]: http://github.com/pivotal/jasmine-gem + */ + +(function() { + + /** + * ## Require & Instantiate + * + * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. + */ + window.jasmine = jasmineRequire.core(jasmineRequire); + + /** + * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. + */ + jasmineRequire.html(jasmine); + + /** + * Create the Jasmine environment. This is used to run all specs in a project. + */ + var env = jasmine.getEnv(); + + /** + * ## The Global Interface + * + * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. + */ + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + pending: function() { + return env.pending(); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }) + }; + + /** + * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. + */ + if (typeof window == "undefined" && typeof exports == "object") { + extend(exports, jasmineInterface); + } else { + extend(window, jasmineInterface); + } + + /** + * Expose the interface for adding custom equality testers. + */ + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + /** + * Expose the interface for adding custom expectation matchers + */ + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + /** + * Expose the mock interface for the JavaScript timeout functions + */ + jasmine.clock = function() { + return env.clock; + }; + + /** + * ## Runner Parameters + * + * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. + */ + + var queryString = new jasmine.QueryString({ + getWindowLocation: function() { return window.location; } + }); + + var catchingExceptions = queryString.getParam("catch"); + env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); + + /** + * ## Reporters + * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). + */ + var htmlReporter = new jasmine.HtmlReporter({ + env: env, + onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, + getContainer: function() { return document.body; }, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); }, + timer: new jasmine.Timer() + }); + + /** + * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. + */ + env.addReporter(jasmineInterface.jsApiReporter); + env.addReporter(htmlReporter); + + /** + * Filter which specs will be run by matching the start of the full name against the `spec` query param. + */ + var specFilter = new jasmine.HtmlSpecFilter({ + filterString: function() { return queryString.getParam("spec"); } + }); + + env.specFilter = function(spec) { + return specFilter.matches(spec.getFullName()); + }; + + /** + * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. + */ + window.setTimeout = window.setTimeout; + window.setInterval = window.setInterval; + window.clearTimeout = window.clearTimeout; + window.clearInterval = window.clearInterval; + + /** + * ## Execution + * + * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. + */ + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + htmlReporter.initialize(); + env.execute(); + }; + + /** + * Helper function for readability above. + */ + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + +}()); diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/console.js b/node_modules/svgjs/spec/lib/jasmine-2.0.1/console.js new file mode 100644 index 0000000..c54f72d --- /dev/null +++ b/node_modules/svgjs/spec/lib/jasmine-2.0.1/console.js @@ -0,0 +1,165 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().console = function(jRequire, j$) { + j$.ConsoleReporter = jRequire.ConsoleReporter(); +}; + +getJasmineRequireObj().ConsoleReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function ConsoleReporter(options) { + var print = options.print, + showColors = options.showColors || false, + onComplete = options.onComplete || function() {}, + timer = options.timer || noopTimer, + specCount, + failureCount, + failedSpecs = [], + pendingCount, + ansi = { + green: '\x1B[32m', + red: '\x1B[31m', + yellow: '\x1B[33m', + none: '\x1B[0m' + }; + + this.jasmineStarted = function() { + specCount = 0; + failureCount = 0; + pendingCount = 0; + print('Started'); + printNewline(); + timer.start(); + }; + + this.jasmineDone = function() { + printNewline(); + for (var i = 0; i < failedSpecs.length; i++) { + specFailureDetails(failedSpecs[i]); + } + + if(specCount > 0) { + printNewline(); + + var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + + failureCount + ' ' + plural('failure', failureCount); + + if (pendingCount) { + specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); + } + + print(specCounts); + } else { + print('No specs found'); + } + + printNewline(); + var seconds = timer.elapsed() / 1000; + print('Finished in ' + seconds + ' ' + plural('second', seconds)); + + printNewline(); + + onComplete(failureCount === 0); + }; + + this.specDone = function(result) { + specCount++; + + if (result.status == 'pending') { + pendingCount++; + print(colored('yellow', '*')); + return; + } + + if (result.status == 'passed') { + print(colored('green', '.')); + return; + } + + if (result.status == 'failed') { + failureCount++; + failedSpecs.push(result); + print(colored('red', 'F')); + } + }; + + return this; + + function printNewline() { + print('\n'); + } + + function colored(color, str) { + return showColors ? (ansi[color] + str + ansi.none) : str; + } + + function plural(str, count) { + return count == 1 ? str : str + 's'; + } + + function repeat(thing, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(thing); + } + return arr; + } + + function indent(str, spaces) { + var lines = (str || '').split('\n'); + var newArr = []; + for (var i = 0; i < lines.length; i++) { + newArr.push(repeat(' ', spaces).join('') + lines[i]); + } + return newArr.join('\n'); + } + + function specFailureDetails(result) { + printNewline(); + print(result.fullName); + + for (var i = 0; i < result.failedExpectations.length; i++) { + var failedExpectation = result.failedExpectations[i]; + printNewline(); + print(indent(failedExpectation.stack, 2)); + } + + printNewline(); + } + } + + return ConsoleReporter; +}; diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine-html.js b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine-html.js new file mode 100644 index 0000000..9d95903 --- /dev/null +++ b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine-html.js @@ -0,0 +1,390 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +jasmineRequire.html = function(j$) { + j$.ResultsNode = jasmineRequire.ResultsNode(); + j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); + j$.QueryString = jasmineRequire.QueryString(); + j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); +}; + +jasmineRequire.HtmlReporter = function(j$) { + + var noopTimer = { + start: function() {}, + elapsed: function() { return 0; } + }; + + function HtmlReporter(options) { + var env = options.env || {}, + getContainer = options.getContainer, + createElement = options.createElement, + createTextNode = options.createTextNode, + onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, + timer = options.timer || noopTimer, + results = [], + specsExecuted = 0, + failureCount = 0, + pendingSpecCount = 0, + htmlReporterMain, + symbols; + + this.initialize = function() { + clearPrior(); + htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, + createDom('div', {className: 'banner'}, + createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), + createDom('span', {className: 'version'}, j$.version) + ), + createDom('ul', {className: 'symbol-summary'}), + createDom('div', {className: 'alert'}), + createDom('div', {className: 'results'}, + createDom('div', {className: 'failures'}) + ) + ); + getContainer().appendChild(htmlReporterMain); + + symbols = find('.symbol-summary'); + }; + + var totalSpecsDefined; + this.jasmineStarted = function(options) { + totalSpecsDefined = options.totalSpecsDefined || 0; + timer.start(); + }; + + var summary = createDom('div', {className: 'summary'}); + + var topResults = new j$.ResultsNode({}, '', null), + currentParent = topResults; + + this.suiteStarted = function(result) { + currentParent.addChild(result, 'suite'); + currentParent = currentParent.last(); + }; + + this.suiteDone = function(result) { + if (currentParent == topResults) { + return; + } + + currentParent = currentParent.parent; + }; + + this.specStarted = function(result) { + currentParent.addChild(result, 'spec'); + }; + + var failures = []; + this.specDone = function(result) { + if(noExpectations(result) && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + + if (result.status != 'disabled') { + specsExecuted++; + } + + symbols.appendChild(createDom('li', { + className: noExpectations(result) ? 'empty' : result.status, + id: 'spec_' + result.id, + title: result.fullName + } + )); + + if (result.status == 'failed') { + failureCount++; + + var failure = + createDom('div', {className: 'spec-detail failed'}, + createDom('div', {className: 'description'}, + createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) + ), + createDom('div', {className: 'messages'}) + ); + var messages = failure.childNodes[1]; + + for (var i = 0; i < result.failedExpectations.length; i++) { + var expectation = result.failedExpectations[i]; + messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); + messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); + } + + failures.push(failure); + } + + if (result.status == 'pending') { + pendingSpecCount++; + } + }; + + this.jasmineDone = function() { + var banner = find('.banner'); + banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); + + var alert = find('.alert'); + + alert.appendChild(createDom('span', { className: 'exceptions' }, + createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'), + createDom('input', { + className: 'raise', + id: 'raise-exceptions', + type: 'checkbox' + }) + )); + var checkbox = find('#raise-exceptions'); + + checkbox.checked = !env.catchingExceptions(); + checkbox.onclick = onRaiseExceptionsClick; + + if (specsExecuted < totalSpecsDefined) { + var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; + alert.appendChild( + createDom('span', {className: 'bar skipped'}, + createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) + ) + ); + } + var statusBarMessage = ''; + var statusBarClassName = 'bar '; + + if (totalSpecsDefined > 0) { + statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); + if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } + statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; + } else { + statusBarClassName += 'skipped'; + statusBarMessage += 'No specs found'; + } + + alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); + + var results = find('.results'); + results.appendChild(summary); + + summaryList(topResults, summary); + + function summaryList(resultsTree, domParent) { + var specListNode; + for (var i = 0; i < resultsTree.children.length; i++) { + var resultNode = resultsTree.children[i]; + if (resultNode.type == 'suite') { + var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, + createDom('li', {className: 'suite-detail'}, + createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + ) + ); + + summaryList(resultNode, suiteListNode); + domParent.appendChild(suiteListNode); + } + if (resultNode.type == 'spec') { + if (domParent.getAttribute('class') != 'specs') { + specListNode = createDom('ul', {className: 'specs'}); + domParent.appendChild(specListNode); + } + var specDescription = resultNode.result.description; + if(noExpectations(resultNode.result)) { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } + specListNode.appendChild( + createDom('li', { + className: resultNode.result.status, + id: 'spec-' + resultNode.result.id + }, + createDom('a', {href: specHref(resultNode.result)}, specDescription) + ) + ); + } + } + } + + if (failures.length) { + alert.appendChild( + createDom('span', {className: 'menu bar spec-list'}, + createDom('span', {}, 'Spec List | '), + createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); + alert.appendChild( + createDom('span', {className: 'menu bar failure-list'}, + createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), + createDom('span', {}, ' | Failures '))); + + find('.failures-menu').onclick = function() { + setMenuModeTo('failure-list'); + }; + find('.spec-list-menu').onclick = function() { + setMenuModeTo('spec-list'); + }; + + setMenuModeTo('failure-list'); + + var failureNode = find('.failures'); + for (var i = 0; i < failures.length; i++) { + failureNode.appendChild(failures[i]); + } + } + }; + + return this; + + function find(selector) { + return getContainer().querySelector('.jasmine_html-reporter ' + selector); + } + + function clearPrior() { + // return the reporter + var oldReporter = find(''); + + if(oldReporter) { + getContainer().removeChild(oldReporter); + } + } + + function createDom(type, attrs, childrenVarArgs) { + var el = createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == 'className') { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; + } + + function pluralize(singular, count) { + var word = (count == 1 ? singular : singular + 's'); + + return '' + count + ' ' + word; + } + + function specHref(result) { + return '?spec=' + encodeURIComponent(result.fullName); + } + + function setMenuModeTo(mode) { + htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); + } + + function noExpectations(result) { + return (result.failedExpectations.length + result.passedExpectations.length) === 0 && + result.status === 'passed'; + } + } + + return HtmlReporter; +}; + +jasmineRequire.HtmlSpecFilter = function() { + function HtmlSpecFilter(options) { + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); + var filterPattern = new RegExp(filterString); + + this.matches = function(specName) { + return filterPattern.test(specName); + }; + } + + return HtmlSpecFilter; +}; + +jasmineRequire.ResultsNode = function() { + function ResultsNode(result, type, parent) { + this.result = result; + this.type = type; + this.parent = parent; + + this.children = []; + + this.addChild = function(result, type) { + this.children.push(new ResultsNode(result, type, this)); + }; + + this.last = function() { + return this.children[this.children.length - 1]; + }; + } + + return ResultsNode; +}; + +jasmineRequire.QueryString = function() { + function QueryString(options) { + + this.setParam = function(key, value) { + var paramMap = queryStringToParamMap(); + paramMap[key] = value; + options.getWindowLocation().search = toQueryString(paramMap); + }; + + this.getParam = function(key) { + return queryStringToParamMap()[key]; + }; + + return this; + + function toQueryString(paramMap) { + var qStrPairs = []; + for (var prop in paramMap) { + qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); + } + return '?' + qStrPairs.join('&'); + } + + function queryStringToParamMap() { + var paramStr = options.getWindowLocation().search.substring(1), + params = [], + paramMap = {}; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + var value = decodeURIComponent(p[1]); + if (value === 'true' || value === 'false') { + value = JSON.parse(value); + } + paramMap[decodeURIComponent(p[0])] = value; + } + } + + return paramMap; + } + + } + + return QueryString; +}; diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.css b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.css new file mode 100644 index 0000000..c54ff30 --- /dev/null +++ b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.css @@ -0,0 +1,59 @@ +body { overflow-y: scroll; } + +.jasmine_html-reporter { background-color: #eeeeee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +.jasmine_html-reporter a { text-decoration: none; } +.jasmine_html-reporter a:hover { text-decoration: underline; } +.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } +.jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } +.jasmine_html-reporter .banner { position: relative; } +.jasmine_html-reporter .banner .title { background: url('data:image/png;base64,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') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } +.jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } +.jasmine_html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; } +.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } +.jasmine_html-reporter .version { color: #aaaaaa; } +.jasmine_html-reporter .banner { margin-top: 14px; } +.jasmine_html-reporter .duration { color: #aaaaaa; float: right; } +.jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } +.jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } +.jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.failed { line-height: 9px; } +.jasmine_html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.jasmine_html-reporter .symbol-summary li.disabled { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.pending { line-height: 17px; } +.jasmine_html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } +.jasmine_html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +.jasmine_html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +.jasmine_html-reporter .bar.failed { background-color: #ca3a11; } +.jasmine_html-reporter .bar.passed { background-color: #007069; } +.jasmine_html-reporter .bar.skipped { background-color: #bababa; } +.jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } +.jasmine_html-reporter .bar.menu a { color: #333333; } +.jasmine_html-reporter .bar a { color: white; } +.jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; } +.jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; } +.jasmine_html-reporter .running-alert { background-color: #666666; } +.jasmine_html-reporter .results { margin-top: 14px; } +.jasmine_html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +.jasmine_html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +.jasmine_html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter.showDetails .summary { display: none; } +.jasmine_html-reporter.showDetails #details { display: block; } +.jasmine_html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter .summary { margin-top: 14px; } +.jasmine_html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } +.jasmine_html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } +.jasmine_html-reporter .summary li.passed a { color: #007069; } +.jasmine_html-reporter .summary li.failed a { color: #ca3a11; } +.jasmine_html-reporter .summary li.empty a { color: #ba9d37; } +.jasmine_html-reporter .summary li.pending a { color: #ba9d37; } +.jasmine_html-reporter .description + .suite { margin-top: 0; } +.jasmine_html-reporter .suite { margin-top: 14px; } +.jasmine_html-reporter .suite a { color: #333333; } +.jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; } +.jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; } +.jasmine_html-reporter .failures .spec-detail .description a { color: white; } +.jasmine_html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } +.jasmine_html-reporter .result-message span.result { display: block; } +.jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.js b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.js new file mode 100644 index 0000000..c943db1 --- /dev/null +++ b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine.js @@ -0,0 +1,2516 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().core = function(jRequire) { + var j$ = {}; + + jRequire.base(j$); + j$.util = jRequire.util(); + j$.Any = jRequire.Any(); + j$.CallTracker = jRequire.CallTracker(); + j$.MockDate = jRequire.MockDate(); + j$.Clock = jRequire.Clock(); + j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); + j$.Env = jRequire.Env(j$); + j$.ExceptionFormatter = jRequire.ExceptionFormatter(); + j$.Expectation = jRequire.Expectation(); + j$.buildExpectationResult = jRequire.buildExpectationResult(); + j$.JsApiReporter = jRequire.JsApiReporter(); + j$.matchersUtil = jRequire.matchersUtil(j$); + j$.ObjectContaining = jRequire.ObjectContaining(j$); + j$.pp = jRequire.pp(j$); + j$.QueueRunner = jRequire.QueueRunner(j$); + j$.ReportDispatcher = jRequire.ReportDispatcher(); + j$.Spec = jRequire.Spec(j$); + j$.SpyStrategy = jRequire.SpyStrategy(); + j$.Suite = jRequire.Suite(); + j$.Timer = jRequire.Timer(); + j$.version = jRequire.version(); + + j$.matchers = jRequire.requireMatchers(jRequire, j$); + + return j$; +}; + +getJasmineRequireObj().requireMatchers = function(jRequire, j$) { + var availableMatchers = [ + 'toBe', + 'toBeCloseTo', + 'toBeDefined', + 'toBeFalsy', + 'toBeGreaterThan', + 'toBeLessThan', + 'toBeNaN', + 'toBeNull', + 'toBeTruthy', + 'toBeUndefined', + 'toContain', + 'toEqual', + 'toHaveBeenCalled', + 'toHaveBeenCalledWith', + 'toMatch', + 'toThrow', + 'toThrowError' + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](j$); + } + + return matchers; +}; + +getJasmineRequireObj().base = (function (jasmineGlobal) { + if (typeof module !== 'undefined' && module.exports) { + jasmineGlobal = global; + } + + return function(j$) { + j$.unimplementedMethod_ = function() { + throw new Error('unimplemented method'); + }; + + j$.MAX_PRETTY_PRINT_DEPTH = 40; + j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + + j$.getGlobal = function() { + return jasmineGlobal; + }; + + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; + }; + + j$.isArray_ = function(value) { + return j$.isA_('Array', value); + }; + + j$.isString_ = function(value) { + return j$.isA_('String', value); + }; + + j$.isNumber_ = function(value) { + return j$.isA_('Number', value); + }; + + j$.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; + }; + + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; + + j$.any = function(clazz) { + return new j$.Any(clazz); + }; + + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; + + j$.createSpy = function(name, originalFn) { + + var spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function() { return spy; } + }), + callTracker = new j$.CallTracker(), + spy = function() { + callTracker.track({ + object: this, + args: Array.prototype.slice.apply(arguments) + }); + return spyStrategy.exec.apply(this, arguments); + }; + + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); + } + + spy[prop] = originalFn[prop]; + } + + spy.and = spyStrategy; + spy.calls = callTracker; + + return spy; + }; + + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; + + j$.createSpyObj = function(baseName, methodNames) { + if (!j$.isArray_(methodNames) || methodNames.length === 0) { + throw 'createSpyObj requires a non-empty array of method names to create spies for'; + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + } + return obj; + }; + }; +})(this); + +getJasmineRequireObj().util = function() { + + var util = {}; + + util.inherit = function(childClass, parentClass) { + var Subclass = function() { + }; + Subclass.prototype = parentClass.prototype; + childClass.prototype = new Subclass(); + }; + + util.htmlEscape = function(str) { + if (!str) { + return str; + } + return str.replace(/&/g, '&') + .replace(//g, '>'); + }; + + util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) { + arrayOfArgs.push(args[i]); + } + return arrayOfArgs; + }; + + util.isUndefined = function(obj) { + return obj === void 0; + }; + + util.arrayContains = function(array, search) { + var i = array.length; + while (i--) { + if (array[i] == search) { + return true; + } + } + return false; + }; + + return util; +}; + +getJasmineRequireObj().Spec = function(j$) { + function Spec(attrs) { + this.expectationFactory = attrs.expectationFactory; + this.resultCallback = attrs.resultCallback || function() {}; + this.id = attrs.id; + this.description = attrs.description || ''; + this.fn = attrs.fn; + this.beforeFns = attrs.beforeFns || function() { return []; }; + this.afterFns = attrs.afterFns || function() { return []; }; + this.onStart = attrs.onStart || function() {}; + this.exceptionFormatter = attrs.exceptionFormatter || function() {}; + this.getSpecName = attrs.getSpecName || function() { return ''; }; + this.expectationResultFactory = attrs.expectationResultFactory || function() { }; + this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; + this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + + if (!this.fn) { + this.pend(); + } + + this.result = { + id: this.id, + description: this.description, + fullName: this.getFullName(), + failedExpectations: [], + passedExpectations: [] + }; + } + + Spec.prototype.addExpectationResult = function(passed, data) { + var expectationResult = this.expectationResultFactory(data); + if (passed) { + this.result.passedExpectations.push(expectationResult); + } else { + this.result.failedExpectations.push(expectationResult); + } + }; + + Spec.prototype.expect = function(actual) { + return this.expectationFactory(actual, this); + }; + + Spec.prototype.execute = function(onComplete) { + var self = this; + + this.onStart(this); + + if (this.markedPending || this.disabled) { + complete(); + return; + } + + var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); + + this.queueRunnerFactory({ + fns: allFns, + onException: onException, + onComplete: complete, + enforceTimeout: function() { return true; } + }); + + function onException(e) { + if (Spec.isPendingSpecException(e)) { + self.pend(); + return; + } + + self.addExpectationResult(false, { + matcherName: '', + passed: false, + expected: '', + actual: '', + error: e + }); + } + + function complete() { + self.result.status = self.status(); + self.resultCallback(self.result); + + if (onComplete) { + onComplete(); + } + } + }; + + Spec.prototype.disable = function() { + this.disabled = true; + }; + + Spec.prototype.pend = function() { + this.markedPending = true; + }; + + Spec.prototype.status = function() { + if (this.disabled) { + return 'disabled'; + } + + if (this.markedPending) { + return 'pending'; + } + + if (this.result.failedExpectations.length > 0) { + return 'failed'; + } else { + return 'passed'; + } + }; + + Spec.prototype.getFullName = function() { + return this.getSpecName(this); + }; + + Spec.pendingSpecExceptionMessage = '=> marked Pending'; + + Spec.isPendingSpecException = function(e) { + return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); + }; + + return Spec; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Spec = jasmineRequire.Spec; +} + +getJasmineRequireObj().Env = function(j$) { + function Env(options) { + options = options || {}; + + var self = this; + var global = options.global || j$.getGlobal(); + + var totalSpecsDefined = 0; + + var catchExceptions = true; + + var realSetTimeout = j$.getGlobal().setTimeout; + var realClearTimeout = j$.getGlobal().clearTimeout; + this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); + + var runnableLookupTable = {}; + + var spies = []; + + var currentSpec = null; + var currentSuite = null; + + var reporter = new j$.ReportDispatcher([ + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' + ]); + + this.specFilter = function() { + return true; + }; + + var equalityTesters = []; + + var customEqualityTesters = []; + this.addCustomEqualityTester = function(tester) { + customEqualityTesters.push(tester); + }; + + j$.Expectation.addCoreMatchers(j$.matchers); + + var nextSpecId = 0; + var getNextSpecId = function() { + return 'spec' + nextSpecId++; + }; + + var nextSuiteId = 0; + var getNextSuiteId = function() { + return 'suite' + nextSuiteId++; + }; + + var expectationFactory = function(actual, spec) { + return j$.Expectation.Factory({ + util: j$.matchersUtil, + customEqualityTesters: customEqualityTesters, + actual: actual, + addExpectationResult: addExpectationResult + }); + + function addExpectationResult(passed, result) { + return spec.addExpectationResult(passed, result); + } + }; + + var specStarted = function(spec) { + currentSpec = spec; + reporter.specStarted(spec.result); + }; + + var beforeFns = function(suite) { + return function() { + var befores = []; + while(suite) { + befores = befores.concat(suite.beforeFns); + suite = suite.parentSuite; + } + return befores.reverse(); + }; + }; + + var afterFns = function(suite) { + return function() { + var afters = []; + while(suite) { + afters = afters.concat(suite.afterFns); + suite = suite.parentSuite; + } + return afters; + }; + }; + + var getSpecName = function(spec, suite) { + return suite.getFullName() + ' ' + spec.description; + }; + + // TODO: we may just be able to pass in the fn instead of wrapping here + var buildExpectationResult = j$.buildExpectationResult, + exceptionFormatter = new j$.ExceptionFormatter(), + expectationResultFactory = function(attrs) { + attrs.messageFormatter = exceptionFormatter.message; + attrs.stackFormatter = exceptionFormatter.stack; + + return buildExpectationResult(attrs); + }; + + // TODO: fix this naming, and here's where the value comes in + this.catchExceptions = function(value) { + catchExceptions = !!value; + return catchExceptions; + }; + + this.catchingExceptions = function() { + return catchExceptions; + }; + + var maximumSpecCallbackDepth = 20; + var currentSpecCallbackDepth = 0; + + function clearStack(fn) { + currentSpecCallbackDepth++; + if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) { + currentSpecCallbackDepth = 0; + realSetTimeout(fn, 0); + } else { + fn(); + } + } + + var catchException = function(e) { + return j$.Spec.isPendingSpecException(e) || catchExceptions; + }; + + var queueRunnerFactory = function(options) { + options.catchException = catchException; + options.clearStack = options.clearStack || clearStack; + options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; + + new j$.QueueRunner(options).execute(); + }; + + var topSuite = new j$.Suite({ + env: this, + id: getNextSuiteId(), + description: 'Jasmine__TopLevel__Suite', + queueRunner: queueRunnerFactory, + resultCallback: function() {} // TODO - hook this up + }); + runnableLookupTable[topSuite.id] = topSuite; + currentSuite = topSuite; + + this.topSuite = function() { + return topSuite; + }; + + this.execute = function(runnablesToRun) { + runnablesToRun = runnablesToRun || [topSuite.id]; + + var allFns = []; + for(var i = 0; i < runnablesToRun.length; i++) { + var runnable = runnableLookupTable[runnablesToRun[i]]; + allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable)); + } + + reporter.jasmineStarted({ + totalSpecsDefined: totalSpecsDefined + }); + + queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone}); + }; + + this.addReporter = function(reporterToAdd) { + reporter.addReporter(reporterToAdd); + }; + + this.addMatchers = function(matchersToAdd) { + j$.Expectation.addMatchers(matchersToAdd); + }; + + this.spyOn = function(obj, methodName) { + if (j$.util.isUndefined(obj)) { + throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); + } + + if (j$.util.isUndefined(obj[methodName])) { + throw new Error(methodName + '() method does not exist'); + } + + if (obj[methodName] && j$.isSpy(obj[methodName])) { + //TODO?: should this return the current spy? Downside: may cause user confusion about spy state + throw new Error(methodName + ' has already been spied upon'); + } + + var spy = j$.createSpy(methodName, obj[methodName]); + + spies.push({ + spy: spy, + baseObj: obj, + methodName: methodName, + originalValue: obj[methodName] + }); + + obj[methodName] = spy; + + return spy; + }; + + var suiteFactory = function(description) { + var suite = new j$.Suite({ + env: self, + id: getNextSuiteId(), + description: description, + parentSuite: currentSuite, + queueRunner: queueRunnerFactory, + onStart: suiteStarted, + resultCallback: function(attrs) { + reporter.suiteDone(attrs); + } + }); + + runnableLookupTable[suite.id] = suite; + return suite; + }; + + this.describe = function(description, specDefinitions) { + var suite = suiteFactory(description); + + var parentSuite = currentSuite; + parentSuite.addChild(suite); + currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch (e) { + declarationError = e; + } + + if (declarationError) { + this.it('encountered a declaration exception', function() { + throw declarationError; + }); + } + + currentSuite = parentSuite; + + return suite; + }; + + this.xdescribe = function(description, specDefinitions) { + var suite = this.describe(description, specDefinitions); + suite.disable(); + return suite; + }; + + var specFactory = function(description, fn, suite) { + totalSpecsDefined++; + + var spec = new j$.Spec({ + id: getNextSpecId(), + beforeFns: beforeFns(suite), + afterFns: afterFns(suite), + expectationFactory: expectationFactory, + exceptionFormatter: exceptionFormatter, + resultCallback: specResultCallback, + getSpecName: function(spec) { + return getSpecName(spec, suite); + }, + onStart: specStarted, + description: description, + expectationResultFactory: expectationResultFactory, + queueRunnerFactory: queueRunnerFactory, + fn: fn + }); + + runnableLookupTable[spec.id] = spec; + + if (!self.specFilter(spec)) { + spec.disable(); + } + + return spec; + + function removeAllSpies() { + for (var i = 0; i < spies.length; i++) { + var spyEntry = spies[i]; + spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; + } + spies = []; + } + + function specResultCallback(result) { + removeAllSpies(); + j$.Expectation.resetMatchers(); + customEqualityTesters = []; + currentSpec = null; + reporter.specDone(result); + } + }; + + var suiteStarted = function(suite) { + reporter.suiteStarted(suite.result); + }; + + this.it = function(description, fn) { + var spec = specFactory(description, fn, currentSuite); + currentSuite.addChild(spec); + return spec; + }; + + this.xit = function(description, fn) { + var spec = this.it(description, fn); + spec.pend(); + return spec; + }; + + this.expect = function(actual) { + if (!currentSpec) { + throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); + } + + return currentSpec.expect(actual); + }; + + this.beforeEach = function(beforeEachFunction) { + currentSuite.beforeEach(beforeEachFunction); + }; + + this.afterEach = function(afterEachFunction) { + currentSuite.afterEach(afterEachFunction); + }; + + this.pending = function() { + throw j$.Spec.pendingSpecExceptionMessage; + }; + } + + return Env; +}; + +getJasmineRequireObj().JsApiReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function JsApiReporter(options) { + var timer = options.timer || noopTimer, + status = 'loaded'; + + this.started = false; + this.finished = false; + + this.jasmineStarted = function() { + this.started = true; + status = 'started'; + timer.start(); + }; + + var executionTime; + + this.jasmineDone = function() { + this.finished = true; + executionTime = timer.elapsed(); + status = 'done'; + }; + + this.status = function() { + return status; + }; + + var suites = {}; + + this.suiteStarted = function(result) { + storeSuite(result); + }; + + this.suiteDone = function(result) { + storeSuite(result); + }; + + function storeSuite(result) { + suites[result.id] = result; + } + + this.suites = function() { + return suites; + }; + + var specs = []; + this.specStarted = function(result) { }; + + this.specDone = function(result) { + specs.push(result); + }; + + this.specResults = function(index, length) { + return specs.slice(index, index + length); + }; + + this.specs = function() { + return specs; + }; + + this.executionTime = function() { + return executionTime; + }; + + } + + return JsApiReporter; +}; + +getJasmineRequireObj().Any = function() { + + function Any(expectedObject) { + this.expectedObject = expectedObject; + } + + Any.prototype.jasmineMatches = function(other) { + if (this.expectedObject == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedObject == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedObject == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedObject == Object) { + return typeof other == 'object'; + } + + if (this.expectedObject == Boolean) { + return typeof other == 'boolean'; + } + + return other instanceof this.expectedObject; + }; + + Any.prototype.jasmineToString = function() { + return ''; + }; + + return Any; +}; + +getJasmineRequireObj().CallTracker = function() { + + function CallTracker() { + var calls = []; + + this.track = function(context) { + calls.push(context); + }; + + this.any = function() { + return !!calls.length; + }; + + this.count = function() { + return calls.length; + }; + + this.argsFor = function(index) { + var call = calls[index]; + return call ? call.args : []; + }; + + this.all = function() { + return calls; + }; + + this.allArgs = function() { + var callArgs = []; + for(var i = 0; i < calls.length; i++){ + callArgs.push(calls[i].args); + } + + return callArgs; + }; + + this.first = function() { + return calls[0]; + }; + + this.mostRecent = function() { + return calls[calls.length - 1]; + }; + + this.reset = function() { + calls = []; + }; + } + + return CallTracker; +}; + +getJasmineRequireObj().Clock = function() { + function Clock(global, delayedFunctionScheduler, mockDate) { + var self = this, + realTimingFunctions = { + setTimeout: global.setTimeout, + clearTimeout: global.clearTimeout, + setInterval: global.setInterval, + clearInterval: global.clearInterval + }, + fakeTimingFunctions = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval + }, + installed = false, + timer; + + + self.install = function() { + replace(global, fakeTimingFunctions); + timer = fakeTimingFunctions; + installed = true; + + return self; + }; + + self.uninstall = function() { + delayedFunctionScheduler.reset(); + mockDate.uninstall(); + replace(global, realTimingFunctions); + + timer = realTimingFunctions; + installed = false; + }; + + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + + self.setTimeout = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); + } + return timer.setTimeout(fn, delay); + } + return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); + }; + + self.setInterval = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); + } + return timer.setInterval(fn, delay); + } + return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); + }; + + self.clearTimeout = function(id) { + return Function.prototype.call.apply(timer.clearTimeout, [global, id]); + }; + + self.clearInterval = function(id) { + return Function.prototype.call.apply(timer.clearInterval, [global, id]); + }; + + self.tick = function(millis) { + if (installed) { + mockDate.tick(millis); + delayedFunctionScheduler.tick(millis); + } else { + throw new Error('Mock clock is not installed, use jasmine.clock().install()'); + } + }; + + return self; + + function legacyIE() { + //if these methods are polyfilled, apply will be present + return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; + } + + function replace(dest, source) { + for (var prop in source) { + dest[prop] = source[prop]; + } + } + + function setTimeout(fn, delay) { + return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); + } + + function clearTimeout(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function setInterval(fn, interval) { + return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); + } + + function clearInterval(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function argSlice(argsObj, n) { + return Array.prototype.slice.call(argsObj, n); + } + } + + return Clock; +}; + +getJasmineRequireObj().DelayedFunctionScheduler = function() { + function DelayedFunctionScheduler() { + var self = this; + var scheduledLookup = []; + var scheduledFunctions = {}; + var currentTime = 0; + var delayedFnCount = 0; + + self.tick = function(millis) { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime); + currentTime = endTime; + }; + + self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { + var f; + if (typeof(funcToCall) === 'string') { + /* jshint evil: true */ + f = function() { return eval(funcToCall); }; + /* jshint evil: false */ + } else { + f = funcToCall; + } + + millis = millis || 0; + timeoutKey = timeoutKey || ++delayedFnCount; + runAtMillis = runAtMillis || (currentTime + millis); + + var funcToSchedule = { + runAtMillis: runAtMillis, + funcToCall: f, + recurring: recurring, + params: params, + timeoutKey: timeoutKey, + millis: millis + }; + + if (runAtMillis in scheduledFunctions) { + scheduledFunctions[runAtMillis].push(funcToSchedule); + } else { + scheduledFunctions[runAtMillis] = [funcToSchedule]; + scheduledLookup.push(runAtMillis); + scheduledLookup.sort(function (a, b) { + return a - b; + }); + } + + return timeoutKey; + }; + + self.removeFunctionWithId = function(timeoutKey) { + for (var runAtMillis in scheduledFunctions) { + var funcs = scheduledFunctions[runAtMillis]; + var i = indexOfFirstToPass(funcs, function (func) { + return func.timeoutKey === timeoutKey; + }); + + if (i > -1) { + if (funcs.length === 1) { + delete scheduledFunctions[runAtMillis]; + deleteFromLookup(runAtMillis); + } else { + funcs.splice(i, 1); + } + + // intervals get rescheduled when executed, so there's never more + // than a single scheduled function with a given timeoutKey + break; + } + } + }; + + self.reset = function() { + currentTime = 0; + scheduledLookup = []; + scheduledFunctions = {}; + delayedFnCount = 0; + }; + + return self; + + function indexOfFirstToPass(array, testFn) { + var index = -1; + + for (var i = 0; i < array.length; ++i) { + if (testFn(array[i])) { + index = i; + break; + } + } + + return index; + } + + function deleteFromLookup(key) { + var value = Number(key); + var i = indexOfFirstToPass(scheduledLookup, function (millis) { + return millis === value; + }); + + if (i > -1) { + scheduledLookup.splice(i, 1); + } + } + + function reschedule(scheduledFn) { + self.scheduleFunction(scheduledFn.funcToCall, + scheduledFn.millis, + scheduledFn.params, + true, + scheduledFn.timeoutKey, + scheduledFn.runAtMillis + scheduledFn.millis); + } + + function runScheduledFunctions(endTime) { + if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { + return; + } + + do { + currentTime = scheduledLookup.shift(); + + var funcsToRun = scheduledFunctions[currentTime]; + delete scheduledFunctions[currentTime]; + + for (var i = 0; i < funcsToRun.length; ++i) { + var funcToRun = funcsToRun[i]; + funcToRun.funcToCall.apply(null, funcToRun.params || []); + + if (funcToRun.recurring) { + reschedule(funcToRun); + } + } + } while (scheduledLookup.length > 0 && + // checking first if we're out of time prevents setTimeout(0) + // scheduled in a funcToRun from forcing an extra iteration + currentTime !== endTime && + scheduledLookup[0] <= endTime); + } + } + + return DelayedFunctionScheduler; +}; + +getJasmineRequireObj().ExceptionFormatter = function() { + function ExceptionFormatter() { + this.message = function(error) { + var message = ''; + + if (error.name && error.message) { + message += error.name + ': ' + error.message; + } else { + message += error.toString() + ' thrown'; + } + + if (error.fileName || error.sourceURL) { + message += ' in ' + (error.fileName || error.sourceURL); + } + + if (error.line || error.lineNumber) { + message += ' (line ' + (error.line || error.lineNumber) + ')'; + } + + return message; + }; + + this.stack = function(error) { + return error ? error.stack : null; + }; + } + + return ExceptionFormatter; +}; + +getJasmineRequireObj().Expectation = function() { + + var matchers = {}; + + function Expectation(options) { + this.util = options.util || { buildFailureMessage: function() {} }; + this.customEqualityTesters = options.customEqualityTesters || []; + this.actual = options.actual; + this.addExpectationResult = options.addExpectationResult || function(){}; + this.isNot = options.isNot; + + for (var matcherName in matchers) { + this[matcherName] = matchers[matcherName]; + } + } + + Expectation.prototype.wrapCompare = function(name, matcherFactory) { + return function() { + var args = Array.prototype.slice.call(arguments, 0), + expected = args.slice(0), + message = ''; + + args.unshift(this.actual); + + var matcher = matcherFactory(this.util, this.customEqualityTesters), + matcherCompare = matcher.compare; + + function defaultNegativeCompare() { + var result = matcher.compare.apply(null, args); + result.pass = !result.pass; + return result; + } + + if (this.isNot) { + matcherCompare = matcher.negativeCompare || defaultNegativeCompare; + } + + var result = matcherCompare.apply(null, args); + + if (!result.pass) { + if (!result.message) { + args.unshift(this.isNot); + args.unshift(name); + message = this.util.buildFailureMessage.apply(null, args); + } else { + if (Object.prototype.toString.apply(result.message) === '[object Function]') { + message = result.message(); + } else { + message = result.message; + } + } + } + + if (expected.length == 1) { + expected = expected[0]; + } + + // TODO: how many of these params are needed? + this.addExpectationResult( + result.pass, + { + matcherName: name, + passed: result.pass, + message: message, + actual: this.actual, + expected: expected // TODO: this may need to be arrayified/sliced + } + ); + }; + }; + + Expectation.addCoreMatchers = function(matchers) { + var prototype = Expectation.prototype; + for (var matcherName in matchers) { + var matcher = matchers[matcherName]; + prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); + } + }; + + Expectation.addMatchers = function(matchersToAdd) { + for (var name in matchersToAdd) { + var matcher = matchersToAdd[name]; + matchers[name] = Expectation.prototype.wrapCompare(name, matcher); + } + }; + + Expectation.resetMatchers = function() { + for (var name in matchers) { + delete matchers[name]; + } + }; + + Expectation.Factory = function(options) { + options = options || {}; + + var expect = new Expectation(options); + + // TODO: this would be nice as its own Object - NegativeExpectation + // TODO: copy instead of mutate options + options.isNot = true; + expect.not = new Expectation(options); + + return expect; + }; + + return Expectation; +}; + +//TODO: expectation result may make more sense as a presentation of an expectation. +getJasmineRequireObj().buildExpectationResult = function() { + function buildExpectationResult(options) { + var messageFormatter = options.messageFormatter || function() {}, + stackFormatter = options.stackFormatter || function() {}; + + return { + matcherName: options.matcherName, + expected: options.expected, + actual: options.actual, + message: message(), + stack: stack(), + passed: options.passed + }; + + function message() { + if (options.passed) { + return 'Passed.'; + } else if (options.message) { + return options.message; + } else if (options.error) { + return messageFormatter(options.error); + } + return ''; + } + + function stack() { + if (options.passed) { + return ''; + } + + var error = options.error; + if (!error) { + try { + throw new Error(message()); + } catch (e) { + error = e; + } + } + return stackFormatter(error); + } + } + + return buildExpectationResult; +}; + +getJasmineRequireObj().MockDate = function() { + function MockDate(global) { + var self = this; + var currentTime = 0; + + if (!global || !global.Date) { + self.install = function() {}; + self.tick = function() {}; + self.uninstall = function() {}; + return self; + } + + var GlobalDate = global.Date; + + self.install = function(mockDate) { + if (mockDate instanceof GlobalDate) { + currentTime = mockDate.getTime(); + } else { + currentTime = new GlobalDate().getTime(); + } + + global.Date = FakeDate; + }; + + self.tick = function(millis) { + millis = millis || 0; + currentTime = currentTime + millis; + }; + + self.uninstall = function() { + currentTime = 0; + global.Date = GlobalDate; + }; + + createDateProperties(); + + return self; + + function FakeDate() { + if (arguments.length === 0) { + return new GlobalDate(currentTime); + } else { + return new GlobalDate(arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], arguments[6]); + } + } + + function createDateProperties() { + + FakeDate.now = function() { + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error('Browser does not support Date.now()'); + } + }; + + FakeDate.toSource = GlobalDate.toSource; + FakeDate.toString = GlobalDate.toString; + FakeDate.parse = GlobalDate.parse; + FakeDate.UTC = GlobalDate.UTC; + } + } + + return MockDate; +}; + +getJasmineRequireObj().ObjectContaining = function(j$) { + + function ObjectContaining(sample) { + this.sample = sample; + } + + ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } + + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var hasKey = function(obj, keyName) { + return obj !== null && !j$.util.isUndefined(obj[keyName]); + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); + } + else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { + mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.'); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); + }; + + ObjectContaining.prototype.jasmineToString = function() { + return ''; + }; + + return ObjectContaining; +}; + +getJasmineRequireObj().pp = function(j$) { + + function PrettyPrinter() { + this.ppNestLevel_ = 0; + this.seen = []; + } + + PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (j$.util.isUndefined(value)) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === 0 && 1/value === -Infinity) { + this.emitScalar('-0'); + } else if (value === j$.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (j$.isSpy(value)) { + this.emitScalar('spy on ' + value.and.identity()); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (j$.util.arrayContains(this.seen, value)) { + this.emitScalar(''); + } else if (j$.isArray_(value) || j$.isA_('Object', value)) { + this.seen.push(value); + if (j$.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + this.seen.pop(); + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } + }; + + PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } + fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && + obj.__lookupGetter__(property) !== null) : false); + } + }; + + PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; + + function StringPrettyPrinter() { + PrettyPrinter.call(this); + + this.string = ''; + } + + j$.util.inherit(StringPrettyPrinter, PrettyPrinter); + + StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); + }; + + StringPrettyPrinter.prototype.emitString = function(value) { + this.append('\'' + value + '\''); + }; + + StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Array'); + return; + } + var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + this.append('[ '); + for (var i = 0; i < length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + if(array.length > length){ + this.append(', ...'); + } + this.append(' ]'); + }; + + StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Object'); + return; + } + + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(': '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); + }; + + StringPrettyPrinter.prototype.append = function(value) { + this.string += value; + }; + + return function(value) { + var stringPrettyPrinter = new StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; + }; +}; + +getJasmineRequireObj().QueueRunner = function(j$) { + + function once(fn) { + var called = false; + return function() { + if (!called) { + called = true; + fn(); + } + }; + } + + function QueueRunner(attrs) { + this.fns = attrs.fns || []; + this.onComplete = attrs.onComplete || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + this.onException = attrs.onException || function() {}; + this.catchException = attrs.catchException || function() { return true; }; + this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; + this.userContext = {}; + this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; + } + + QueueRunner.prototype.execute = function() { + this.run(this.fns, 0); + }; + + QueueRunner.prototype.run = function(fns, recursiveIndex) { + var length = fns.length, + self = this, + iterativeIndex; + + for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { + var fn = fns[iterativeIndex]; + if (fn.length > 0) { + return attemptAsync(fn); + } else { + attemptSync(fn); + } + } + + var runnerDone = iterativeIndex >= length; + + if (runnerDone) { + this.clearStack(this.onComplete); + } + + function attemptSync(fn) { + try { + fn.call(self.userContext); + } catch (e) { + handleException(e); + } + } + + function attemptAsync(fn) { + var clearTimeout = function () { + Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); + }, + next = once(function () { + clearTimeout(timeoutId); + self.run(fns, iterativeIndex + 1); + }), + timeoutId; + + if (self.enforceTimeout()) { + timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { + self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); + next(); + }, j$.DEFAULT_TIMEOUT_INTERVAL]]); + } + + try { + fn.call(self.userContext, next); + } catch (e) { + handleException(e); + next(); + } + } + + function handleException(e) { + self.onException(e); + if (!self.catchException(e)) { + //TODO: set a var when we catch an exception and + //use a finally block to close the loop in a nice way.. + throw e; + } + } + }; + + return QueueRunner; +}; + +getJasmineRequireObj().ReportDispatcher = function() { + function ReportDispatcher(methods) { + + var dispatchedMethods = methods || []; + + for (var i = 0; i < dispatchedMethods.length; i++) { + var method = dispatchedMethods[i]; + this[method] = (function(m) { + return function() { + dispatch(m, arguments); + }; + }(method)); + } + + var reporters = []; + + this.addReporter = function(reporter) { + reporters.push(reporter); + }; + + return this; + + function dispatch(method, args) { + for (var i = 0; i < reporters.length; i++) { + var reporter = reporters[i]; + if (reporter[method]) { + reporter[method].apply(reporter, args); + } + } + } + } + + return ReportDispatcher; +}; + + +getJasmineRequireObj().SpyStrategy = function() { + + function SpyStrategy(options) { + options = options || {}; + + var identity = options.name || 'unknown', + originalFn = options.fn || function() {}, + getSpy = options.getSpy || function() {}, + plan = function() {}; + + this.identity = function() { + return identity; + }; + + this.exec = function() { + return plan.apply(this, arguments); + }; + + this.callThrough = function() { + plan = originalFn; + return getSpy(); + }; + + this.returnValue = function(value) { + plan = function() { + return value; + }; + return getSpy(); + }; + + this.throwError = function(something) { + var error = (something instanceof Error) ? something : new Error(something); + plan = function() { + throw error; + }; + return getSpy(); + }; + + this.callFake = function(fn) { + plan = fn; + return getSpy(); + }; + + this.stub = function(fn) { + plan = function() {}; + return getSpy(); + }; + } + + return SpyStrategy; +}; + +getJasmineRequireObj().Suite = function() { + function Suite(attrs) { + this.env = attrs.env; + this.id = attrs.id; + this.parentSuite = attrs.parentSuite; + this.description = attrs.description; + this.onStart = attrs.onStart || function() {}; + this.resultCallback = attrs.resultCallback || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + + this.beforeFns = []; + this.afterFns = []; + this.queueRunner = attrs.queueRunner || function() {}; + this.disabled = false; + + this.children = []; + + this.result = { + id: this.id, + status: this.disabled ? 'disabled' : '', + description: this.description, + fullName: this.getFullName() + }; + } + + Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + if (parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + } + return fullName; + }; + + Suite.prototype.disable = function() { + this.disabled = true; + }; + + Suite.prototype.beforeEach = function(fn) { + this.beforeFns.unshift(fn); + }; + + Suite.prototype.afterEach = function(fn) { + this.afterFns.unshift(fn); + }; + + Suite.prototype.addChild = function(child) { + this.children.push(child); + }; + + Suite.prototype.execute = function(onComplete) { + var self = this; + if (this.disabled) { + complete(); + return; + } + + var allFns = []; + + for (var i = 0; i < this.children.length; i++) { + allFns.push(wrapChildAsAsync(this.children[i])); + } + + this.onStart(this); + + this.queueRunner({ + fns: allFns, + onComplete: complete + }); + + function complete() { + self.resultCallback(self.result); + + if (onComplete) { + onComplete(); + } + } + + function wrapChildAsAsync(child) { + return function(done) { child.execute(done); }; + } + }; + + return Suite; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Suite = jasmineRequire.Suite; +} + +getJasmineRequireObj().Timer = function() { + var defaultNow = (function(Date) { + return function() { return new Date().getTime(); }; + })(Date); + + function Timer(options) { + options = options || {}; + + var now = options.now || defaultNow, + startTime; + + this.start = function() { + startTime = now(); + }; + + this.elapsed = function() { + return now() - startTime; + }; + } + + return Timer; +}; + +getJasmineRequireObj().matchersUtil = function(j$) { + // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? + + return { + equals: function(a, b, customTesters) { + customTesters = customTesters || []; + + return eq(a, b, [], [], customTesters); + }, + + contains: function(haystack, needle, customTesters) { + customTesters = customTesters || []; + + if (Object.prototype.toString.apply(haystack) === '[object Array]') { + for (var i = 0; i < haystack.length; i++) { + if (eq(haystack[i], needle, [], [], customTesters)) { + return true; + } + } + return false; + } + return !!haystack && haystack.indexOf(needle) >= 0; + }, + + buildFailureMessage: function() { + var args = Array.prototype.slice.call(arguments, 0), + matcherName = args[0], + isNot = args[1], + actual = args[2], + expected = args.slice(3), + englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + + var message = 'Expected ' + + j$.pp(actual) + + (isNot ? ' not ' : ' ') + + englishyPredicate; + + if (expected.length > 0) { + for (var i = 0; i < expected.length; i++) { + if (i > 0) { + message += ','; + } + message += ' ' + j$.pp(expected[i]); + } + } + + return message + '.'; + } + }; + + // Equality function lovingly adapted from isEqual in + // [Underscore](http://underscorejs.org) + function eq(a, b, aStack, bStack, customTesters) { + var result = true; + + for (var i = 0; i < customTesters.length; i++) { + var customTesterResult = customTesters[i](a, b); + if (!j$.util.isUndefined(customTesterResult)) { + return customTesterResult; + } + } + + if (a instanceof j$.Any) { + result = a.jasmineMatches(b); + if (result) { + return true; + } + } + + if (b instanceof j$.Any) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } + + if (b instanceof j$.ObjectContaining) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } + + if (a instanceof Error && b instanceof Error) { + return a.message == b.message; + } + + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) { return a !== 0 || 1 / a == 1 / b; } + // A strict comparison is necessary because `null == undefined`. + if (a === null || b === null) { return a === b; } + var className = Object.prototype.toString.call(a); + if (className != Object.prototype.toString.call(b)) { return false; } + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') { return false; } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) { return bStack[length] == b; } + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; } + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) && + isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; } + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (has(b, key) && !(size--)) { break; } + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + + return result; + + function has(obj, key) { + return obj.hasOwnProperty(key); + } + + function isFunction(obj) { + return typeof obj === 'function'; + } + } +}; + +getJasmineRequireObj().toBe = function() { + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; + } + + return toBe; +}; + +getJasmineRequireObj().toBeCloseTo = function() { + + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } + + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; + } + + return toBeCloseTo; +}; + +getJasmineRequireObj().toBeDefined = function() { + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; + } + + return toBeDefined; +}; + +getJasmineRequireObj().toBeFalsy = function() { + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; + } + + return toBeFalsy; +}; + +getJasmineRequireObj().toBeGreaterThan = function() { + + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } + + return toBeGreaterThan; +}; + + +getJasmineRequireObj().toBeLessThan = function() { + function toBeLessThan() { + return { + + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } + + return toBeLessThan; +}; +getJasmineRequireObj().toBeNaN = function(j$) { + + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; + + if (result.pass) { + result.message = 'Expected actual not to be NaN.'; + } else { + result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; + } + + return result; + } + }; + } + + return toBeNaN; +}; + +getJasmineRequireObj().toBeNull = function() { + + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; + } + + return toBeNull; +}; + +getJasmineRequireObj().toBeTruthy = function() { + + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } + + return toBeTruthy; +}; + +getJasmineRequireObj().toBeUndefined = function() { + + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; + } + + return toBeUndefined; +}; + +getJasmineRequireObj().toContain = function() { + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; + } + + return toContain; +}; + +getJasmineRequireObj().toEqual = function() { + + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + var result = { + pass: false + }; + + result.pass = util.equals(actual, expected, customEqualityTesters); + + return result; + } + }; + } + + return toEqual; +}; + +getJasmineRequireObj().toHaveBeenCalled = function(j$) { + + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (arguments.length > 1) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + result.pass = actual.calls.any(); + + result.message = result.pass ? + 'Expected spy ' + actual.and.identity() + ' not to have been called.' : + 'Expected spy ' + actual.and.identity() + ' to have been called.'; + + return result; + } + }; + } + + return toHaveBeenCalled; +}; + +getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { + + function toHaveBeenCalledWith(util, customEqualityTesters) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1), + result = { pass: false }; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (!actual.calls.any()) { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; + return result; + } + + if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + result.pass = true; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; + } else { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; + } + + return result; + } + }; + } + + return toHaveBeenCalledWith; +}; + +getJasmineRequireObj().toMatch = function() { + + function toMatch() { + return { + compare: function(actual, expected) { + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; + } + + return toMatch; +}; + +getJasmineRequireObj().toThrow = function(j$) { + + function toThrow(util) { + return { + compare: function(actual, expected) { + var result = { pass: false }, + threw = false, + thrown; + + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + result.message = 'Expected function to throw an exception.'; + return result; + } + + if (arguments.length == 1) { + result.pass = true; + result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; + + return result; + } + + if (util.equals(thrown, expected)) { + result.pass = true; + result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; + } else { + result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; + } + + return result; + } + }; + } + + return toThrow; +}; + +getJasmineRequireObj().toThrowError = function(j$) { + function toThrowError (util) { + return { + compare: function(actual) { + var threw = false, + pass = {pass: true}, + fail = {pass: false}, + thrown, + errorType, + message, + regexp, + name, + constructorName; + + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } + + extractExpectedParams.apply(null, arguments); + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + fail.message = 'Expected function to throw an Error.'; + return fail; + } + + if (!(thrown instanceof Error)) { + fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; + return fail; + } + + if (arguments.length == 1) { + pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; + return pass; + } + + if (errorType) { + name = fnNameFor(errorType); + constructorName = fnNameFor(thrown.constructor); + } + + if (errorType && message) { + if (thrown.constructor == errorType && util.equals(thrown.message, message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (errorType && regexp) { + if (thrown.constructor == errorType && regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (errorType) { + if (thrown.constructor == errorType) { + pass.message = 'Expected function not to throw ' + name + '.'; + return pass; + } else { + fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; + return fail; + } + } + + if (message) { + if (thrown.message == message) { + pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + if (regexp) { + if (regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } + + function fnNameFor(func) { + return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; + } + + function extractExpectedParams() { + if (arguments.length == 1) { + return; + } + + if (arguments.length == 2) { + var expected = arguments[1]; + + if (expected instanceof RegExp) { + regexp = expected; + } else if (typeof expected == 'string') { + message = expected; + } else if (checkForAnErrorType(expected)) { + errorType = expected; + } + + if (!(errorType || message || regexp)) { + throw new Error('Expected is not an Error, string, or RegExp.'); + } + } else { + if (checkForAnErrorType(arguments[1])) { + errorType = arguments[1]; + } else { + throw new Error('Expected error type is not an Error.'); + } + + if (arguments[2] instanceof RegExp) { + regexp = arguments[2]; + } else if (typeof arguments[2] == 'string') { + message = arguments[2]; + } else { + throw new Error('Expected error message is not a string or RegExp.'); + } + } + } + + function checkForAnErrorType(type) { + if (typeof type !== 'function') { + return false; + } + + var Surrogate = function() {}; + Surrogate.prototype = type.prototype; + return (new Surrogate()) instanceof Error; + } + } + }; + } + + return toThrowError; +}; + +getJasmineRequireObj().version = function() { + return '2.0.1'; +}; diff --git a/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine_favicon.png b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine_favicon.png new file mode 100644 index 0000000..3b84583 Binary files /dev/null and b/node_modules/svgjs/spec/lib/jasmine-2.0.1/jasmine_favicon.png differ diff --git a/node_modules/svgjs/spec/spec/adopter.js b/node_modules/svgjs/spec/spec/adopter.js new file mode 100644 index 0000000..0136d0e --- /dev/null +++ b/node_modules/svgjs/spec/spec/adopter.js @@ -0,0 +1,61 @@ +describe('Adopter', function() { + var path + + beforeEach(function() { + path = SVG.get('lineAB') + polyline = SVG.get('inlineSVG').select('polyline').first() + polygon = SVG.get('inlineSVG').select('polygon').first() + }) + + describe('with SVG.Doc instance', function() { + it('adopts the main svg document when parent() method is called on first level children', function() { + expect(path.parent() instanceof SVG.Doc).toBeTruthy() + }) + it('defines a xmlns attribute', function() { + expect(path.parent().node.getAttribute('xmlns')).toBe(SVG.ns) + }) + it('defines a version attribute', function() { + expect(path.parent().node.getAttribute('version')).toBe('1.1') + }) + it('defines a xmlns:xlink attribute', function() { + expect(path.parent().node.getAttribute('xmlns:xlink')).toBe(SVG.xlink) + }) + it('initializes a defs node', function() { + expect(path.parent()._defs).toBe(path.parent().defs()) + }) + }) + + describe('with SVG.Path instance', function() { + it('adopts an exiting path element', function() { + expect(path instanceof SVG.Path).toBeTruthy() + }) + it('modifies an adopted element', function() { + path.fill('#f06') + expect(path.node.getAttribute('fill')).toBe('#ff0066') + }) + it('parses d attribute to SVG.PathArray', function() { + expect(path.array() instanceof SVG.PathArray).toBeTruthy() + }) + }) + + describe('with SVG.Polyline instance', function() { + it('parses points attribute to SVG.PointArray', function() { + expect(polyline.array() instanceof SVG.PointArray).toBeTruthy() + }) + }) + + describe('with SVG.Polygon instance', function() { + it('parses points attribute to SVG.PointArray', function() { + expect(polygon.array() instanceof SVG.PointArray).toBeTruthy() + }) + }) + + describe('with node that has no matching svg.js class', function() { + it('wraps the node in the base SVG.Element class', function() { + var desc = SVG.get('inlineSVG').select('desc').first() + expect(desc instanceof SVG.Element).toBeTruthy() + }) + }) + + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/arrange.js b/node_modules/svgjs/spec/spec/arrange.js new file mode 100644 index 0000000..07f87d1 --- /dev/null +++ b/node_modules/svgjs/spec/spec/arrange.js @@ -0,0 +1,181 @@ +describe('Arrange', function() { + var e1, e2, e3 + + beforeEach(function() { + draw.clear() + + e1 = draw.rect(100,100).move(10,10).attr('id', 'e1') + e2 = draw.ellipse(100,100).move(20,20).attr('id', 'e2') + e3 = draw.line(0,0,100,100).move(30,30).attr('id', 'e3') + }) + + describe('siblings()', function() { + it('returns all siblings of targeted element', function() { + expect(e1.siblings().length).toBe(3) + expect([e1,e2,e3]).toEqual(e2.siblings()) + }) + }) + + describe('position()', function() { + it('returns the index position within it\'s parent', function() { + expect(e1.siblings().length).toBe(3) + expect(e1.position()).toBe(0) + expect(e2.position()).toBe(1) + expect(e3.position()).toBe(2) + }) + }) + + describe('next()', function() { + it('returns the next sibling within the parent element', function() { + expect(e1.next()).toBe(e2) + expect(e2.next()).toBe(e3) + expect(e3.next()).toBe(undefined) + }) + }) + + describe('previous()', function() { + it('returns the previous sibling within the parent element', function() { + expect(e1.previous()).toBe(undefined) + expect(e2.previous()).toBe(e1) + expect(e3.previous()).toBe(e2) + }) + }) + + describe('forward()', function() { + it('returns the element itself', function() { + expect(e1.forward()).toBe(e1) + }) + it('moves the element one step forward within its parent', function() { + e1.forward() + expect(e1.position()).toBe(1) + expect(e2.position()).toBe(0) + expect(e3.position()).toBe(2) + }) + it('keeps the last element at the same position', function() { + e3.forward() + expect(e3.position()).toBe(2) + }) + it('keeps the defs on top of the stack', function() { + draw.defs() + e3.forward() + expect(draw.node.childNodes[2]).toBe(e3.node) + expect(draw.node.childNodes[3]).toBe(draw.defs().node) + }) + }) + + describe('backward()', function() { + it('returns the element itself', function() { + expect(e1.backward()).toBe(e1) + }) + it('moves the element one step backwards within its parent', function() { + e3.backward() + expect(e1.position()).toBe(0) + expect(e2.position()).toBe(2) + expect(e3.position()).toBe(1) + }) + it('keeps the first element at the same position', function() { + e3.backward() + expect(e1.position()).toBe(0) + }) + }) + + describe('front()', function() { + it('returns the element itself', function() { + expect(e3.front()).toBe(e3) + }) + it('moves the element to the top of the stack within its parent', function() { + e1.front() + expect(e1.position()).toBe(2) + expect(e2.position()).toBe(0) + expect(e3.position()).toBe(1) + }) + it('keeps the last element at the same position', function() { + e3.front() + expect(e3.position()).toBe(2) + }) + it('keeps the defs on top of the stack', function() { + e1.front() + expect(draw.node.childNodes[2]).toBe(e1.node) + expect(draw.node.childNodes[3]).toBe(draw.defs().node) + }) + }) + + describe('back()', function() { + it('returns the element itself', function() { + expect(e3.back()).toBe(e3) + }) + it('moves the element to the bottom of the stack within its parent', function() { + e3.back() + expect(e1.position()).toBe(1) + expect(e2.position()).toBe(2) + expect(e3.position()).toBe(0) + }) + it('keeps the first element at the same position', function() { + e1.back() + expect(e1.position()).toBe(0) + }) + }) + + describe('before()', function() { + it('returns the targeted element itself', function() { + expect(e3.before(e1)).toBe(e3) + }) + it('inserts a given element before the targeted element', function() { + e3.before(e1) + expect(e1.position()).toBe(1) + expect(e2.position()).toBe(0) + expect(e3.position()).toBe(2) + }) + it('moves elements between containers', function() { + var group = draw.group() + , e4 = group.rect(80,120) + , e5 = group.rect(80,120) + , e6 = group.rect(80,120) + + e2.before(e5) + expect(e1.position()).toBe(0) + expect(e2.position()).toBe(2) + expect(e3.position()).toBe(3) + expect(e5.position()).toBe(1) + }) + }) + + describe('after()', function() { + it('returns the targeted element itself', function() { + expect(e3.after(e1)).toBe(e3) + }) + it('inserts a given element after the targeted element', function() { + e3.after(e1) + expect(e1.position()).toBe(2) + expect(e2.position()).toBe(0) + expect(e3.position()).toBe(1) + }) + it('moves elements between containers', function() { + var group = draw.group() + , e4 = group.rect(80,120) + , e5 = group.rect(80,120) + , e6 = group.rect(80,120) + + e2.after(e5) + expect(e1.position()).toBe(0) + expect(e2.position()).toBe(1) + expect(e3.position()).toBe(3) + expect(e5.position()).toBe(2) + }) + }) + +}) + + + + + + + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/array.js b/node_modules/svgjs/spec/spec/array.js new file mode 100644 index 0000000..05ea837 --- /dev/null +++ b/node_modules/svgjs/spec/spec/array.js @@ -0,0 +1,77 @@ +describe('Array', function () { + var array + + it('parses a matrix array correctly to string', function() { + array = new SVG.Array([ .343, .669, .119, 0, 0 + , .249, -.626, .130, 0, 0 + , .172, .334, .111, 0, 0 + , .000, .000, .000, 1, -0 ]) + + expect(array + '').toBe('0.343 0.669 0.119 0 0 0.249 -0.626 0.13 0 0 0.172 0.334 0.111 0 0 0 0 0 1 0') + }) + describe('reverse()', function() { + it('reverses the array', function() { + array = new SVG.Array([1 ,2 ,3, 4, 5]).reverse() + expect(array.value).toEqual([5, 4, 3, 2, 1]) + }) + it('returns itself', function() { + array = new SVG.Array() + expect(array.reverse()).toBe(array) + }) + }) +}) + + +describe('PointArray', function () { + it('parses a string to a point array', function() { + var array = new SVG.PointArray('0,1 -.05,7.95 1000.0001,-200.222') + + expect(array.valueOf()).toEqual([[0, 1], [-0.05, 7.95], [1000.0001, -200.222]]) + }) + it('parses a points array correctly to string', function() { + var array = new SVG.PointArray([[0,.15], [-100,-3.141592654], [50,100]]) + + expect(array + '').toBe('0,0.15 -100,-3.141592654 50,100') + }) +}) + +describe('PathArray', function () { + var p1, p2, p3 + + beforeEach(function() { + p1 = new SVG.PathArray('m10 10 h 80 v 80 h -80 l 300 400 z') + p2 = new SVG.PathArray('m10 80 c 40 10 65 10 95 80 s 150 150 180 80 t 300 300 q 52 10 95 80 z') + p3 = new SVG.PathArray('m80 80 A 45 45, 0, 0, 0, 125 125 L 125 80 z') + }) + + it('converts to absolute values', function() { + expect(p1.toString()).toBe('M10 10H90V90H10L310 490Z ') + expect(p2.toString()).toBe('M10 80C50 90 75 90 105 160S255 310 285 240T585 540Q637 550 680 620Z ') + expect(p3.toString()).toBe('M80 80A45 45 0 0 0 125 125L125 80Z ') + }) + + describe('move()', function() { + it('moves all points in a straight path', function() { + expect(p1.move(100,200).toString()).toBe('M100 200H180V280H100L400 680Z ') + }) + it('moves all points in a curved path', function() { + expect(p2.move(100,200).toString()).toBe('M100 200C140 210 165 210 195 280S345 430 375 360T675 660Q727 670 770 740Z ') + }) + it('moves all points in a arc path', function() { + expect(p3.move(100,200).toString()).toBe('M100 200A45 45 0 0 0 145 245L145 200Z ') + }) + }) + + describe('size()', function() { + it('resizes all points in a straight path', function() { + expect(p1.size(600,200).toString()).toBe('M10 10H170V43.333333333333336H10L610 210Z ') + }) + it('resizes all points in a curved path', function() { + expect(p2.size(600,200).toString()).toBe('M10 80C45.82089552238806 83.70370370370371 68.2089552238806 83.70370370370371 95.07462686567165 109.62962962962963S229.40298507462686 165.1851851851852 256.2686567164179 139.25925925925927T524.9253731343283 250.37037037037038Q571.4925373134329 254.07407407407408 610 280Z ') + }) + it('resizes all points in a arc path', function() { + expect(p3.size(600,200).toString()).toBe('M80 80A599.9998982747568 199.9999660915856 0 0 0 679.9998982747568 279.99996609158563L679.9998982747568 80Z ') + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/bare.js b/node_modules/svgjs/spec/spec/bare.js new file mode 100644 index 0000000..a27dbc3 --- /dev/null +++ b/node_modules/svgjs/spec/spec/bare.js @@ -0,0 +1,40 @@ +describe('Bare', function() { + + describe('element()', function() { + var element + + beforeEach(function() { + element = draw.element('rect') + }) + + it('creates an instance of SVG.Bare', function() { + expect(element instanceof SVG.Bare).toBeTruthy() + }) + it('creates element in called parent', function() { + expect(element.parent()).toBe(draw) + }) + }) + + describe('symbol()', function() { + var symbol + + beforeEach(function() { + symbol = draw.symbol() + }) + + it('creates an instance of SVG.Bare', function() { + expect(symbol instanceof SVG.Bare).toBeTruthy() + }) + it('creates symbol in defs', function() { + expect(symbol.parent() instanceof SVG.Defs).toBeTruthy() + }) + }) + + describe('words()', function() { + it('inserts plain text in a node', function() { + var element = draw.element('title').words('These are some words.').id(null) + expect(element.svg()).toBe('These are some words.') + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/boxes.js b/node_modules/svgjs/spec/spec/boxes.js new file mode 100644 index 0000000..87c25b7 --- /dev/null +++ b/node_modules/svgjs/spec/spec/boxes.js @@ -0,0 +1,206 @@ +describe('BBox', function() { + + afterEach(function() { + draw.clear() + }) + + it('creates a new instance without passing an element', function() { + var box = new SVG.BBox + expect(box.x).toBe(0) + expect(box.y).toBe(0) + expect(box.cx).toBe(0) + expect(box.cy).toBe(0) + expect(box.width).toBe(0) + expect(box.height).toBe(0) + }) + + describe('merge()', function() { + it('merges various bounding boxes', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var box3 = draw.rect(100,100).move(500,100).bbox() + var merged = box1.merge(box2).merge(box3) + expect(merged.x).toBe(50) + expect(merged.y).toBe(50) + expect(merged.cx).toBe(325) + expect(merged.cy).toBe(275) + expect(merged.width).toBe(550) + expect(merged.height).toBe(450) + }) + it('returns a new bbox instance', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var merged = box1.merge(box2) + expect(box1).not.toBe(merged) + expect(box2).not.toBe(merged) + expect(box1.x).toBe(50) + expect(box1.y).toBe(50) + expect(box2.x).toBe(300) + expect(box2.y).toBe(400) + }) + }) + +}) + +describe('TBox', function() { + + afterEach(function() { + draw.clear() + }) + + it('creates a new instance without passing an element', function() { + var box = new SVG.TBox + expect(box.x).toBe(0) + expect(box.y).toBe(0) + expect(box.cx).toBe(0) + expect(box.cy).toBe(0) + expect(box.width).toBe(0) + expect(box.height).toBe(0) + }) + + describe('merge()', function() { + it('merges various bounding boxes', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var box3 = draw.rect(100,100).move(500,100).bbox() + var merged = box1.merge(box2).merge(box3) + expect(merged.x).toBe(50) + expect(merged.y).toBe(50) + expect(merged.cx).toBe(325) + expect(merged.cy).toBe(275) + expect(merged.width).toBe(550) + expect(merged.height).toBe(450) + }) + it('returns a new bbox instance', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var merged = box1.merge(box2) + expect(box1).not.toBe(merged) + expect(box2).not.toBe(merged) + expect(box1.x).toBe(50) + expect(box1.y).toBe(50) + expect(box2.x).toBe(300) + expect(box2.y).toBe(400) + }) + }) + +}) + +describe('RBox', function() { + + afterEach(function() { + draw.clear() + }) + + it('creates a new instance without passing an element', function() { + var box = new SVG.RBox + expect(box.x).toBe(0) + expect(box.y).toBe(0) + expect(box.cx).toBe(0) + expect(box.cy).toBe(0) + expect(box.width).toBe(0) + expect(box.height).toBe(0) + }) + + describe('merge()', function() { + it('merges various bounding boxes', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var box3 = draw.rect(100,100).move(500,100).bbox() + var merged = box1.merge(box2).merge(box3) + expect(merged.x).toBe(50) + expect(merged.y).toBe(50) + expect(merged.cx).toBe(325) + expect(merged.cy).toBe(275) + expect(merged.width).toBe(550) + expect(merged.height).toBe(450) + }) + it('returns a new bbox instance', function() { + var box1 = draw.rect(100,100).move(50,50).bbox() + var box2 = draw.rect(100,100).move(300,400).bbox() + var merged = box1.merge(box2) + expect(box1).not.toBe(merged) + expect(box2).not.toBe(merged) + expect(box1.x).toBe(50) + expect(box1.y).toBe(50) + expect(box2.x).toBe(300) + expect(box2.y).toBe(400) + }) + }) + +}) + +describe('Boxes', function() { + var rect + + beforeEach(function() { + rect = draw.rect(50, 180).move(25, 90).scale(2, 3, 25, 90).translate(10, 11) + }) + afterEach(function() { + draw.clear() + }) + + describe('bbox()', function() { + it('returns an instance of SVG.BBox', function() { + expect(rect.bbox() instanceof SVG.BBox).toBeTruthy() + }) + it('matches the size of the target element, ignoring transformations', function() { + var box = rect.bbox() + expect(box.x).toBe(25) + expect(box.y).toBe(90) + expect(box.cx).toBe(50) + expect(box.cy).toBe(180) + expect(box.width).toBe(50) + expect(box.height).toBe(180) + expect(box.w).toBe(50) + expect(box.h).toBe(180) + expect(box.x2).toBe(75) + expect(box.y2).toBe(270) + }) + }) + + describe('tbox()', function() { + it('returns an instance of SVG.TBox', function() { + expect(rect.tbox() instanceof SVG.TBox).toBeTruthy() + }) + it('matches the size of the target element, including transformations', function() { + var box = rect.tbox() + expect(box.x).toBe(35) + expect(box.y).toBe(101) + expect(box.cx).toBe(85) + expect(box.cy).toBe(371) + expect(box.width).toBe(100) + expect(box.height).toBe(540) + expect(box.w).toBe(100) + expect(box.h).toBe(540) + expect(box.x2).toBe(135) + expect(box.y2).toBe(641) + }) + }) + + describe('rbox()', function() { + it('returns an instance of SVG.RBox', function() { + expect(rect.rbox() instanceof SVG.RBox).toBeTruthy() + }) + it('matches the size of the target element, including transformations', function() { + var box = rect.rbox() + expect(box.x).toBeCloseTo(60) + expect(box.y).toBeCloseTo(281) + expect(box.cx).toBeCloseTo(110) + expect(box.cy).toBeCloseTo(551) + expect(box.width).toBe(100) + expect(box.height).toBe(540) + expect(box.w).toBe(100) + expect(box.h).toBe(540) + expect(box.x2).toBeCloseTo(160) + expect(box.y2).toBeCloseTo(821) + }) + }) + +}) + + + + + + diff --git a/node_modules/svgjs/spec/spec/circle.js b/node_modules/svgjs/spec/spec/circle.js new file mode 100644 index 0000000..498cd3a --- /dev/null +++ b/node_modules/svgjs/spec/spec/circle.js @@ -0,0 +1,185 @@ +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) + }) + it('sets the value of x with the first argument', function() { + circle.x(123) + var box = circle.bbox() + expect(box.x).toBeCloseTo(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(circle.y()).toBe(0) + }) + it('sets the value of cy with the first argument', function() { + circle.y(345) + var box = circle.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + expect(circle.cx()).toBe(120) + }) + it('sets the value of cx with the first argument', function() { + circle.cx(123) + var box = circle.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + expect(circle.cy()).toBe(120) + }) + it('sets the value of cy with the first argument', function() { + circle.cy(345) + var box = circle.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('radius()', function() { + it('sets the r attribute with the first argument', function() { + circle.radius(10) + expect(circle.node.getAttribute('r')).toBe('10') + }) + }) + + describe('rx()', function() { + it('sets the r attribute with the first argument', function() { + circle.rx(11) + expect(circle.node.getAttribute('r')).toBe('11') + }) + it('gets the r attribute without and argument', function() { + circle.rx() + expect(circle.node.getAttribute('r')).toBe('120') + }) + }) + + describe('ry()', function() { + it('sets the r attribute with the first argument', function() { + circle.ry(12) + expect(circle.node.getAttribute('r')).toBe('12') + }) + it('gets the r attribute without and argument', function() { + circle.ry() + expect(circle.node.getAttribute('r')).toBe('120') + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + circle.move(123, 456) + var box = circle.bbox() + expect(box.x).toBeCloseTo(123) + expect(box.y).toBe(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + circle.move(50, 60) + circle.dx(100) + expect(circle.node.getAttribute('cx')).toBe('270') + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + circle.move(50, 60) + circle.dy(120) + expect(circle.node.getAttribute('cy')).toBe('300') + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + circle.move(50,60) + circle.dmove(80, 25) + expect(circle.node.getAttribute('cx')).toBe('250') + expect(circle.node.getAttribute('cy')).toBe('205') + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + circle.center(321,567) + var box = circle.bbox() + expect(box.cx).toBe(321) + expect(box.cy).toBe(567) + }) + }) + + describe('width()', function() { + it('sets the width and height of the element', function() { + circle.width(82) + expect(circle.node.getAttribute('r')).toBe('41') + }) + it('gets the width and height of the element if the argument is null', function() { + expect((circle.width() / 2).toString()).toBe(circle.node.getAttribute('r')) + }) + }) + + describe('height()', function() { + it('sets the height and width of the element', function() { + circle.height(1236) + expect(circle.node.getAttribute('r')).toBe('618') + }) + it('gets the height and width of the element if the argument is null', 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).tbox() + + 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).tbox() + + expect(box.width).toBe(circle.attr('r') * 2 * 2) + expect(box.height).toBe(circle.attr('r') * 2 * 3.5) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + circle.transform({ x: 12, y: 12 }) + expect(circle.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/clip.js b/node_modules/svgjs/spec/spec/clip.js new file mode 100644 index 0000000..eba8df4 --- /dev/null +++ b/node_modules/svgjs/spec/spec/clip.js @@ -0,0 +1,57 @@ +describe('ClipPath', function() { + var rect, circle + + beforeEach(function() { + rect = draw.rect(100,100) + circle = draw.circle(100).move(50, 50) + rect.clipWith(circle) + }) + + afterEach(function() { + draw.clear() + }) + + it('moves the clipping element to a new clip node', function() { + expect(circle.parent() instanceof SVG.ClipPath).toBe(true) + }) + + it('creates the clip node in the defs node', function() { + expect(circle.parent().parent()).toBe(draw.defs()) + }) + + it('sets the "clip-path" attribute on the cliped element with the clip id', function() { + expect(rect.attr('clip-path')).toBe('url("#' + circle.parent().attr('id') + '")') + }) + + it('references the clip element in the masked element', function() { + expect(rect.clipper).toBe(circle.parent()) + }) + + it('references the clipped element in the clipPath target list', function() { + expect(rect.clipper.targets.indexOf(rect) > -1).toBe(true) + }) + + it('unclips all clipped elements when being removed', function() { + rect.clipper.remove() + expect(rect.attr('clip-path')).toBe(undefined) + }) + + describe('unclip()', function() { + + it('clears the "clip-path" attribute on the clipped element', function() { + rect.unclip() + expect(rect.attr('clip-path')).toBe(undefined) + }) + + it('removes the reference to the clipping element', function() { + rect.unclip() + expect(rect.clipper).toBe(undefined) + }) + + it('returns the clipPath element', function() { + expect(rect.unclip()).toBe(rect) + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/color.js b/node_modules/svgjs/spec/spec/color.js new file mode 100644 index 0000000..6bae4c8 --- /dev/null +++ b/node_modules/svgjs/spec/spec/color.js @@ -0,0 +1,82 @@ +describe('Color', function() { + var color + + beforeEach(function() { + color = new SVG.Color({ r: 0, g: 102, b: 255 }) + }) + + it('correclty parses a rgb string', function() { + color = new SVG.Color('rgb(255,0,128)') + expect(color.r).toBe(255) + expect(color.g).toBe(0) + expect(color.b).toBe(128) + }) + + it('correclty parses a 3 digit hex string', function() { + color = new SVG.Color('#f06') + expect(color.r).toBe(255) + expect(color.g).toBe(0) + expect(color.b).toBe(102) + }) + + it('correclty parses a 6 digit hex string', function() { + color = new SVG.Color('#0066ff') + expect(color.r).toBe(0) + expect(color.g).toBe(102) + expect(color.b).toBe(255) + }) + + describe('toHex()', function() { + it('returns a hex color', function() { + expect(color.toHex()).toBe('#0066ff') + }) + }) + + describe('toRgb()', function() { + it('returns a rgb string color', function() { + expect(color.toRgb()).toBe('rgb(0,102,255)') + }) + }) + + describe('brightness()', function() { + it('returns the percieved brightness value of a color', function() { + expect(color.brightness()).toBe(0.346) + }) + }) + + describe('morph()', function() { + it('prepares the color for morphing', function() { + var destination = new SVG.Color + color.morph(destination) + expect(color.destination).toEqual(destination) + }) + }) + + describe('at()', function() { + it('morphes color to a given position', function() { + var destination = new SVG.Color + var morphed = color.morph(destination).at(0.5) + expect(morphed.r).toBe(0) + expect(morphed.g).toBe(51) + expect(morphed.b).toBe(127) + }) + + it('morphes color to 1 with higher values', function() { + var destination = new SVG.Color('#fff') + var morphed = color.morph(destination).at(2) + expect(morphed.r).toBe(255) + expect(morphed.g).toBe(255) + expect(morphed.b).toBe(255) + }) + + it('morphes color to 0 with lower values', function() { + var destination = new SVG.Color('#fff') + var morphed = color.morph(destination).at(-3) + expect(morphed.r).toBe(0) + expect(morphed.g).toBe(102) + expect(morphed.b).toBe(255) + }) + }) + +}) + diff --git a/node_modules/svgjs/spec/spec/container.js b/node_modules/svgjs/spec/spec/container.js new file mode 100644 index 0000000..d300fcd --- /dev/null +++ b/node_modules/svgjs/spec/spec/container.js @@ -0,0 +1,362 @@ +describe('Container', function() { + + beforeEach(function() { + draw.clear() + }) + + describe('rect()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.rect(100,100) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a rect', function() { + expect(draw.rect(100,100).type).toBe('rect') + }) + it('should create an instance of SVG.Rect', function() { + expect(draw.rect(100,100) instanceof SVG.Rect).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.rect(100,100) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.rect(100,100) instanceof SVG.Element).toBe(true) + }) + }) + + describe('ellipse()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.ellipse(100,100) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create an ellipse', function() { + expect(draw.ellipse(100,100).type).toBe('ellipse') + }) + it('should create an instance of SVG.Ellipse', function() { + expect(draw.ellipse(100,100) instanceof SVG.Ellipse).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.ellipse(100,100) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.ellipse(100,100) instanceof SVG.Element).toBe(true) + }) + }) + + describe('circle()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.circle(100) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create an circle', function() { + expect(draw.circle(100).type).toBe('circle') + }) + it('should create an instance of SVG.Circle', function() { + expect(draw.circle(100) instanceof SVG.Circle).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.circle(100) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.circle(100) instanceof SVG.Element).toBe(true) + }) + }) + + describe('line()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.line(0,100,100,0) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a line', function() { + expect(draw.line(0,100,100,0).type).toBe('line') + }) + it('should create an instance of SVG.Line', function() { + expect(draw.line(0,100,100,0) instanceof SVG.Line).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.line(0,100,100,0) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.line(0,100,100,0) instanceof SVG.Element).toBe(true) + }) + }) + + describe('polyline()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.polyline('0,0 100,0 100,100 0,100') + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a polyline', function() { + expect(draw.polyline('0,0 100,0 100,100 0,100').type).toBe('polyline') + }) + it('should be an instance of SVG.Polyline', function() { + expect(draw.polyline('0,0 100,0 100,100 0,100') instanceof SVG.Polyline).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.polyline('0,0 100,0 100,100 0,100') instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.polyline('0,0 100,0 100,100 0,100') instanceof SVG.Element).toBe(true) + }) + }) + + describe('polygon()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.polygon('0,0 100,0 100,100 0,100') + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a polygon', function() { + expect(draw.polygon('0,0 100,0 100,100 0,100').type).toBe('polygon') + }) + it('should be an instance of SVG.Polygon', function() { + expect(draw.polygon('0,0 100,0 100,100 0,100') instanceof SVG.Polygon).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.polygon('0,0 100,0 100,100 0,100') instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.polygon('0,0 100,0 100,100 0,100') instanceof SVG.Element).toBe(true) + }) + }) + + describe('path()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.path(svgPath) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a path', function() { + expect(draw.path(svgPath).type).toBe('path') + }) + it('should be an instance of SVG.Path', function() { + expect(draw.path(svgPath) instanceof SVG.Path).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.path(svgPath) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.path(svgPath) instanceof SVG.Element).toBe(true) + }) + }) + + describe('image()', function() { + it('should increase children by 1', function() { + var initial = draw.children().length + draw.image(imageUrl, 100, 100) + expect(draw.children().length).toBe(initial + 1) + }) + it('should create a rect', function() { + expect(draw.image(imageUrl, 100, 100).type).toBe('image') + }) + it('should create an instance of SVG.Rect', function() { + expect(draw.image(imageUrl, 100, 100) instanceof SVG.Image).toBe(true) + }) + it('should be an instance of SVG.Shape', function() { + expect(draw.image(imageUrl, 100, 100) instanceof SVG.Shape).toBe(true) + }) + it('should be an instance of SVG.Element', function() { + expect(draw.image(imageUrl, 100, 100) instanceof SVG.Element).toBe(true) + }) + }) + + describe('text()', function() { + it('increases children by 1', function() { + var initial = draw.children().length + draw.text(loremIpsum) + expect(draw.children().length).toBe(initial + 1) + }) + it('creates a text element', function() { + expect(draw.text(loremIpsum).type).toBe('text') + }) + it('creates an instance of SVG.Rect', function() { + expect(draw.text(loremIpsum) instanceof SVG.Text).toBe(true) + }) + it('is an instance of SVG.Shape', function() { + expect(draw.text(loremIpsum) instanceof SVG.Shape).toBe(true) + }) + it('is an instance of SVG.Element', function() { + expect(draw.text(loremIpsum) instanceof SVG.Element).toBe(true) + }) + }) + + describe('plain()', function() { + it('increases children by 1', function() { + var initial = draw.children().length + draw.plain(loremIpsum) + expect(draw.children().length).toBe(initial + 1) + }) + it('creates a plain element', function() { + expect(draw.plain(loremIpsum).type).toBe('text') + }) + it('creates an instance of SVG.Rect', function() { + expect(draw.plain(loremIpsum) instanceof SVG.Text).toBe(true) + }) + it('is an instance of SVG.Shape', function() { + expect(draw.plain(loremIpsum) instanceof SVG.Shape).toBe(true) + }) + it('is an instance of SVG.Element', function() { + expect(draw.plain(loremIpsum) instanceof SVG.Element).toBe(true) + }) + }) + + describe('clear()', function() { + it('removes all children', function() { + draw.rect(100,100) + draw.clear() + expect(draw.children().length).toBe(0) + }) + it('creates a new defs node', function() { + var oldDefs = draw.defs() + draw.rect(100,100).maskWith(draw.circle(100, 100)) + draw.clear() + expect(draw.defs()).not.toBe(oldDefs) + }) + it('clears all children in the defs node', function() { + draw.rect(100,100).maskWith(draw.circle(100, 100)) + draw.clear() + expect(draw.defs().children().length).toBe(0) + }) + }) + + describe('each()', function() { + it('should iterate over all children', function() { + var children = [] + + draw.rect(100,100) + draw.ellipse(100, 100) + draw.polygon() + + draw.each(function() { + children.push(this.type) + }) + expect(children).toEqual(['rect', 'ellipse', 'polygon']) + }) + it('should only include the its own children', function() { + var children = [] + , group = draw.group() + + draw.rect(100,200) + draw.circle(300) + + group.rect(100,100) + group.ellipse(100, 100) + group.polygon() + + group.each(function() { + children.push(this) + }) + + expect(children).toEqual(group.children()) + }) + it('should traverse recursively when set to deep', function() { + var children = [] + , group = draw.group() + + draw.rect(100,200) + draw.circle(300) + + group.rect(100,100) + group.ellipse(100, 100) + group.polygon() + + draw.each(function() { + children.push(this) + }, true) + + expect(children.length).toEqual(draw.children().length + group.children().length) + }) + }) + + describe('viewbox()', function() { + + beforeEach(function() { + draw.attr('viewBox', null) + }) + + it('should set the viewbox when four arguments are provided', function() { + draw.viewbox(0,0,100,100) + expect(draw.node.getAttribute('viewBox')).toBe('0 0 100 100') + }) + it('should set the viewbox when an object is provided as first argument', function() { + draw.viewbox({ x: 0, y: 0, width: 50, height: 50 }) + expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') + }) + it('should accept negative values', function() { + draw.size(100,100).viewbox(-100, -100, 50, 50) + expect(draw.node.getAttribute('viewBox')).toEqual('-100 -100 50 50') + }) + it('should get the viewbox if no arguments are given', function() { + draw.viewbox(0, 0, 100, 100) + expect(draw.viewbox()).toEqual(new SVG.ViewBox(draw)) + }) + it('should define the zoom of the viewbox in relation to the canvas size', function() { + draw.size(100,100).viewbox(0,0,50,50) + expect(draw.viewbox().zoom).toEqual(100 / 50) + }) + }) + + describe('get()', function() { + it('gets an element at a given index', function() { + draw.clear() + var rect = draw.rect(100,100) + var circle = draw.circle(100) + var line = draw.line(0,0,100,100) + expect(draw.get(0)).toBe(rect) + expect(draw.get(1)).toBe(circle) + expect(draw.get(2)).toBe(line) + expect(draw.get(3)).toBe(undefined) + }) + }) + + describe('has()', function() { + it('determines if a given element is a child of the parent', function() { + var rect = draw.rect(100,100) + var circle = draw.circle(100) + var group = draw.group() + var line = group.line(0,0,100,100) + expect(draw.has(rect)).toBe(true) + expect(draw.has(circle)).toBe(true) + expect(draw.has(group)).toBe(true) + expect(draw.has(line)).toBe(false) + expect(group.has(line)).toBe(true) + }) + }) + + describe('index()', function() { + it('determines the index of given element', function() { + var rect = draw.rect(100,100) + var circle = draw.circle(100) + var group = draw.group() + var line = group.line(0,0,100,100) + expect(draw.index(rect)).toBe(0) + expect(draw.index(circle)).toBe(1) + expect(draw.index(group)).toBe(2) + expect(draw.index(line)).toBe(-1) + expect(group.index(line)).toBe(0) + }) + }) + + describe('parent()', function() { + it('returns the parent element instance', function() { + var rect = draw.rect(100,100) + expect(rect.parent()).toBe(rect.node.parentNode.instance) + }) + }) + +}) + + + + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/defs.js b/node_modules/svgjs/spec/spec/defs.js new file mode 100644 index 0000000..5e5da08 --- /dev/null +++ b/node_modules/svgjs/spec/spec/defs.js @@ -0,0 +1,12 @@ +describe('Defs', function() { + var defs + + beforeEach(function() { + defs = draw.defs() + }) + + it('creates an instance of SVG.Defs', function() { + expect(defs instanceof SVG.Defs).toBeTruthy() + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/doc.js b/node_modules/svgjs/spec/spec/doc.js new file mode 100644 index 0000000..9696935 --- /dev/null +++ b/node_modules/svgjs/spec/spec/doc.js @@ -0,0 +1,37 @@ +describe('Doc', function() { + + it('is an instance of SVG.Container', function() { + expect(draw instanceof SVG.Container).toBe(true) + }) + + it('is an instance of SVG.Doc', function() { + expect(draw instanceof SVG.Doc).toBe(true) + }) + + it('returns itself as Doc', function() { + expect(draw.doc()).toBe(draw) + }) + + it('has a defs element', function() { + expect(draw.defs() instanceof SVG.Defs).toBe(true) + }) + + describe('defs()', function() { + it('returns defs element', function(){ + expect(draw.defs()).toBe(draw._defs) + }) + it('references parent node', function(){ + expect(draw.defs().parent()).toBe(draw) + }) + }) + + describe('remove()', function() { + it('removes the doc from the dom', function() { + draw.remove() + expect(document.getElementsByTagName('body')[0].querySelectorAll('svg').length).toBe(2) + draw = SVG(drawing).size(100,100); + expect(document.getElementsByTagName('body')[0].querySelectorAll('svg').length).toBe(3) + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/element.js b/node_modules/svgjs/spec/spec/element.js new file mode 100644 index 0000000..96a5ff7 --- /dev/null +++ b/node_modules/svgjs/spec/spec/element.js @@ -0,0 +1,651 @@ +describe('Element', function() { + + beforeEach(function() { + draw.attr('viewBox', null) + }) + + afterEach(function() { + draw.clear() + }) + + it('should create a circular reference on the node', function() { + var rect = draw.rect(100,100) + expect(rect.node.instance).toBe(rect) + }) + + describe('native()', function() { + it('returns the node reference', function() { + var rect = draw.rect(100,100) + expect(rect.native()).toBe(rect.node) + }) + }) + + describe('attr()', function() { + var rect + + beforeEach(function() { + rect = draw.rect(100,100) + }) + + afterEach(function() { + rect.remove() + }) + + it('sets one attribute when two arguments are given', function() { + rect.attr('fill', '#ff0066') + expect(rect.node.getAttribute('fill')).toBe('#ff0066') + }) + it('sets various attributes when an object is given', function() { + rect.attr({ fill: '#00ff66', stroke: '#ff2233', 'stroke-width': 10 }) + expect(rect.node.getAttribute('fill')).toBe('#00ff66') + expect(rect.node.getAttribute('stroke')).toBe('#ff2233') + expect(rect.node.getAttribute('stroke-width')).toBe('10') + }) + it('gets the value of the string value given as first argument', function() { + rect.attr('fill', '#ff0066') + expect(rect.attr('fill')).toEqual('#ff0066') + }) + it('gets an object with all attributes without any arguments', function() { + rect.attr({ fill: '#00ff66', stroke: '#ff2233' }) + var attr = rect.attr() + expect(attr.fill).toBe('#00ff66') + expect(attr.stroke).toBe('#ff2233') + }) + it('removes an attribute if the second argument is explicitly set to null', function() { + rect.attr('stroke-width', 10) + expect(rect.node.getAttribute('stroke-width')).toBe('10') + rect.attr('stroke-width', null) + expect(rect.node.getAttribute('stroke-width')).toBe(null) + }) + it('correctly parses numeric values as a getter', function() { + rect.attr('stroke-width', 11) + expect(rect.node.getAttribute('stroke-width')).toBe('11') + expect(rect.attr('stroke-width')).toBe(11) + }) + it('correctly parses negative numeric values as a getter', function() { + rect.attr('x', -120) + expect(rect.node.getAttribute('x')).toBe('-120') + expect(rect.attr('x')).toBe(-120) + }) + it('falls back on default values if attribute is not present', function() { + expect(rect.attr('stroke-linejoin')).toBe('miter') + }) + it('gets the "style" attribute as a string', function() { + rect.style('cursor', 'pointer') + expect(rect.node.style.cursor).toBe('pointer') + }) + it('redirects to the style() method when setting a style string', function() { + rect.attr('style', 'cursor:move;') + expect(rect.node.style.cursor).toBe('move') + }) + it('removes style attribute on node if the style is empty', function() { + rect.style('cursor', 'move') + rect.style('cursor', '') + expect(rect.style.cursor).toBe(undefined) + }) + it('acts as a global getter when no arguments are given', function() { + rect.fill('#ff0066') + expect(rect.attr().fill).toBe('#ff0066') + }) + it('correctly parses numeric values as a global getter', function() { + rect.stroke({ width: 20 }) + expect(rect.attr()['stroke-width']).toBe(20) + }) + it('correctly parses negative numeric values as a global getter', function() { + rect.x(-30) + expect(rect.attr().x).toBe(-30) + }) + it('leaves unit values alone as a global getter', function() { + rect.attr('x', '69%') + expect(rect.attr().x).toBe('69%') + }) + }) + + describe('id()', function() { + var rect + + beforeEach(function() { + rect = draw.rect(100,100) + }) + + it('gets the value if the id attribute without an argument', function() { + expect(rect.id()).toBe(rect.attr('id')) + }) + it('sets the value of the id', function() { + rect.id('new_id') + expect(rect.attr('id')).toBe('new_id') + }) + }) + + describe('style()', function() { + it('sets the style with key and value arguments', function() { + var rect = draw.rect(100,100).style('cursor', 'crosshair') + expect(stripped(rect.node.style.cssText)).toBe('cursor:crosshair;') + }) + it('sets multiple styles with an object as the first argument', function() { + var rect = draw.rect(100,100).style({ cursor: 'help', display: 'block' }) + expect(stripped(rect.node.style.cssText)).toMatch(/cursor:help;/) + expect(stripped(rect.node.style.cssText)).toMatch(/display:block;/) + expect(stripped(rect.node.style.cssText).length).toBe(('display:block;cursor:help;').length) + }) + it('gets a style with a string key as the fists argument', function() { + var rect = draw.rect(100,100).style({ cursor: 'progress', display: 'block' }) + expect(rect.style('cursor')).toBe('progress') + }) + it('gets a style with a string key as the fists argument', function() { + var rect = draw.rect(100,100).style({ cursor: 's-resize', display: 'none' }) + expect(stripped(rect.style())).toMatch(/display:none;/) + expect(stripped(rect.style())).toMatch(/cursor:s-resize;/) + expect(stripped(rect.style()).length).toBe(('cursor:s-resize;display:none;').length) + }) + it('removes a style if the value is an empty string', function() { + var rect = draw.rect(100,100).style({ cursor: 'n-resize', display: '' }) + expect(stripped(rect.style())).toBe('cursor:n-resize;') + }) + it('removes a style if the value explicitly set to null', function() { + var rect = draw.rect(100,100).style('cursor', 'w-resize') + expect(stripped(rect.style())).toBe('cursor:w-resize;') + rect.style('cursor', null) + expect(rect.style()).toBe('') + }) + }) + + describe('transform()', function() { + var rect, ctm + + beforeEach(function() { + rect = draw.rect(100,100) + }) + + it('gets the current transformations', function() { + expect(rect.transform()).toEqual(new SVG.Matrix(rect).extract()) + }) + it('sets the translation of and element', function() { + rect.transform({ x: 10, y: 11 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(1,0,0,1,10,11)') + }) + it('performs an absolute translation', function() { + rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(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(rect.node.getAttribute('transform')).toBe('matrix(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) + expect(rect.node.getAttribute('transform')).toBe('matrix(1,0,0,1,30,32)') + }) + it('sets the scaleX and scaleY of and element', function() { + rect.transform({ scaleX: 0.5, scaleY: 2 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(0.5,0,0,2,25,-50)') + }) + it('performs a uniform scale with scale given', function() { + rect.transform({ scale: 3 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(3,0,0,3,-100,-100)') + }) + it('performs an absolute scale by default', function() { + rect.transform({ scale: 3 }).transform({ scale: 0.5 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(0.5,0,0,0.5,25,25)') + }) + it('performs a relative scale with a relative flag', function() { + rect.transform({ scaleX: 0.5, scaleY: 2 }).transform({ scaleX: 3, scaleY: 4 }, true) + expect(rect.node.getAttribute('transform')).toBe('matrix(1.5,0,0,8,-25,-350)') + }) + it('sets the skewX of and element with center on the element', function() { + ctm = rect.transform({ skewX: 10 }).ctm() + expect(ctm.a).toBe(1) + expect(ctm.b).toBe(0) + expect(ctm.c).toBeCloseTo(0.17632698070846498) + expect(ctm.d).toBe(1) + expect(ctm.e).toBeCloseTo(-8.81634903542325) + expect(ctm.f).toBe(0) + }) + it('sets the skewX of and element with given center', function() { + ctm = rect.transform({ skewX: 10, cx: 0, cy: 0 }).ctm() + expect(ctm.a).toBe(1) + expect(ctm.b).toBe(0) + expect(ctm.c).toBeCloseTo(0.17632698070846498) + expect(ctm.d).toBe(1) + expect(ctm.e).toBe(0) + expect(ctm.f).toBe(0) + }) + it('sets the skewY of and element', function() { + ctm = rect.transform({ skewY: -10, cx: 0, cy: 0 }).ctm() + expect(ctm.a).toBe(1) + expect(ctm.b).toBeCloseTo(-0.17632698070846498) + expect(ctm.c).toBe(0) + expect(ctm.d).toBe(1) + expect(ctm.e).toBe(0) + 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() + 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() + expect(ctm.a).toBeCloseTo(0.5735765099525452) + expect(ctm.b).toBeCloseTo(0.8191521167755127) + expect(ctm.c).toBeCloseTo(-0.8191521167755127) + expect(ctm.d).toBeCloseTo(0.5735765099525452) + expect(ctm.e).toBeCloseTo(35.75218963623047) + expect(ctm.f).toBeCloseTo(-64.67931365966797) + }) + it('transforms element using a matrix', function() { + rect.transform({ a: 0.5, c: 0.5 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(0.5,0,0.5,1,0,0)') + }) + }) + + describe('untransform()', function() { + var circle + + beforeEach(function() { + circle = draw.circle(100).translate(50, 100) + }) + + it('removes the transform attribute', function() { + expect(circle.node.getAttribute('transform')).toBe('matrix(1,0,0,1,50,100)') + circle.untransform() + expect(circle.node.getAttribute('transform')).toBeNull() + }) + it('resets the current transform matix', function() { + expect(circle.ctm()).toEqual(new SVG.Matrix(1,0,0,1,50,100)) + circle.untransform() + expect(circle.ctm()).toEqual(new SVG.Matrix) + }) + }) + + describe('ctm()', function() { + var rect + + beforeEach(function() { + rect = draw.rect(100, 100) + }) + + it('gets the current transform matrix of the element', function() { + rect.translate(10, 20) + expect(rect.ctm().toString()).toBe('matrix(1,0,0,1,10,20)') + }) + it('returns an instance of SVG.Matrix', function() { + expect(rect.ctm() instanceof SVG.Matrix).toBeTruthy() + }) + }) + + describe('data()', function() { + it('sets a data attribute and convert value to json', function() { + var rect = draw.rect(100,100).data('test', 'value') + expect(rect.node.getAttribute('data-test')).toBe('value') + }) + it('sets a data attribute and not convert value to json if flagged raw', function() { + var rect = draw.rect(100,100).data('test', 'value', true) + expect(rect.node.getAttribute('data-test')).toBe('value') + }) + it('sets multiple data attributes and convert values to json when an object is passed', function() { + var rect = draw.rect(100,100).data({ + forbidden: 'fruit' + , multiple: { + values: 'in' + , an: 'object' + } + }) + expect(rect.node.getAttribute('data-forbidden')).toBe('fruit') + expect(rect.node.getAttribute('data-multiple')).toEqual('{"values":"in","an":"object"}') + }) + it('gets data value if only one argument is passed', function() { + var rect = draw.rect(100,100).data('test', 101) + expect(rect.data('test')).toBe(101) + }) + it('maintains data type for a number', function() { + var rect = draw.rect(100,100).data('test', 101) + expect(typeof rect.data('test')).toBe('number') + }) + it('maintains data type for an object', function() { + var rect = draw.rect(100,100).data('test', { string: 'value', array: [1,2,3] }) + expect(typeof rect.data('test')).toBe('object') + expect(Array.isArray(rect.data('test').array)).toBe(true) + }) + }) + + describe('remove()', function() { + it('removes an element and return it', function() { + var rect = draw.rect(100,100) + expect(rect.remove()).toBe(rect) + }) + it('removes an element from its parent', function() { + var rect = draw.rect(100,100) + rect.remove() + expect(draw.has(rect)).toBe(false) + }) + }) + + describe('addTo()', function() { + it('adds an element to a given parent and returns itself', function() { + var rect = draw.rect(100,100) + , group = draw.group() + + expect(rect.addTo(group)).toBe(rect) + expect(rect.parent()).toBe(group) + }) + }) + + describe('putIn()', function() { + it('adds an element to a given parent and returns parent', function() { + var rect = draw.rect(100,100) + , group = draw.group() + + expect(rect.putIn(group)).toBe(group) + expect(rect.parent()).toBe(group) + }) + }) + + describe('rbox()', function() { + it('returns an instance of SVG.RBox', function() { + var rect = draw.rect(100,100) + expect(rect.rbox() instanceof SVG.RBox).toBe(true) + }) + it('returns the correct rectangular box', function() { + var rect = draw.size(200, 150).viewbox(0, 0, 200, 150).rect(105, 210).move(2, 12) + var box = rect.rbox() + expect(box.x).toBeCloseTo(2,0) + expect(box.y).toBeCloseTo(12) + expect(box.cx).toBeCloseTo(54.5) + expect(box.cy).toBeCloseTo(117) + expect(box.width).toBe(105) + expect(box.height).toBe(210) + }) + it('returns the correct rectangular box within a viewbox', function() { + var rect = draw.size(200,150).viewbox(0,0,100,75).rect(105,210).move(2,12) + var box = rect.rbox() + expect(box.x).toBeCloseTo(4) + expect(box.y).toBeCloseTo(24) + expect(box.cx).toBeCloseTo(56.5) + expect(box.cy).toBeCloseTo(129) + expect(box.width).toBe(105) + expect(box.height).toBe(210) + }) + }) + + describe('doc()', function() { + it('returns the parent document', function() { + var rect = draw.rect(100,100) + expect(rect.doc()).toBe(draw) + }) + }) + + describe('parent()', function() { + it('contains the parent svg', function() { + var rect = draw.rect(100,100) + expect(rect.parent()).toBe(draw) + }) + it('contains the parent group when in a group', function() { + var group = draw.group() + , rect = group.rect(100,100) + expect(rect.parent()).toBe(group) + }) + it('contains the parent which matches type', function() { + var group = draw.group() + , rect = group.rect(100,100) + expect(rect.parent(SVG.Doc)).toBe(draw) + }) + it('contains the parent which matches selector', function() { + var group1 = draw.group().addClass('test') + , group2 = group1.group() + , rect = group2.rect(100,100) + expect(rect.parent('.test')).toBe(group1) + }) + }) + + describe('parents()', function() { + it('returns array of parent up to but not including the dom element filtered by type', function() { + var group1 = draw.group().addClass('test') + , group2 = group1.group() + , rect = group2.rect(100,100) + + expect(rect.parents('.test')[0]).toBe(group1) + expect(rect.parents(SVG.G)[0]).toBe(group2) + expect(rect.parents(SVG.G)[1]).toBe(group1) + expect(rect.parents().length).toBe(3) + }) + }) + + describe('clone()', function() { + var rect, group, circle + + beforeEach(function() { + rect = draw.rect(100,100).center(321,567).fill('#f06') + group = draw.group().add(rect) + circle = group.circle(100) + }) + + it('makes an exact copy of the element', function() { + clone = rect.clone() + expect(clone.attr('id', null).attr()).toEqual(rect.attr('id', null).attr()) + }) + it('assigns a new id to the cloned element', function() { + clone = rect.clone() + expect(clone.attr('id')).not.toBe(rect.attr('id')) + }) + it('copies all child nodes as well', function() { + clone = group.clone() + expect(clone.children().length).toBe(group.children().length) + }) + it('assigns a new id to cloned child elements', function() { + clone = group.clone() + expect(clone.attr('id')).not.toEqual(group.attr('id')) + expect(clone.get(0).attr('id')).not.toBe(group.get(0).attr('id')) + expect(clone.get(1).attr('id')).not.toBe(group.get(1).attr('id')) + }) + it('inserts the clone after the cloned element', function() { + clone = rect.clone() + expect(rect.next()).toBe(clone) + }) + }) + + describe('toString()', function() { + it('returns the element id', function() { + var rect = draw.rect(100,100).center(321,567).fill('#f06') + expect(rect + '').toBe(rect.attr('id')) + }) + }) + + describe('replace()', function() { + it('replaces the original element by another given element', function() { + var rect = draw.rect(100,100).center(321,567).fill('#f06') + var circle = draw.circle(200) + var rectIndex = draw.children().indexOf(rect) + + rect.replace(circle) + + expect(rectIndex).toBe(draw.children().indexOf(circle)) + }) + it('removes the original element', function() { + var rect = draw.rect(100,100).center(321,567).fill('#f06') + + rect.replace(draw.circle(200)) + + expect(draw.has(rect)).toBe(false) + }) + it('returns the new element', function() { + var circle = draw.circle(200) + var element = draw.rect(100,100).center(321,567).fill('#f06').replace(circle) + + expect(element).toBe(circle) + }) + }) + + describe('classes()', function() { + it('returns an array of classes on the node', function() { + var element = draw.rect(100,100) + element.node.setAttribute('class', 'one two') + expect(element.classes()).toEqual(['one', 'two']) + }) + }) + + describe('hasClass()', function() { + it('returns true if the node has the class', function() { + var element = draw.rect(100,100) + element.node.setAttribute('class', 'one') + expect(element.hasClass('one')).toBeTruthy() + }) + + it('returns false if the node does not have the class', function() { + var element = draw.rect(100,100) + element.node.setAttribute('class', 'one') + expect(element.hasClass('two')).toBeFalsy() + }) + }) + + describe('addClass()', function() { + it('adds the class to the node', function() { + var element = draw.rect(100,100) + element.addClass('one') + expect(element.hasClass('one')).toBeTruthy() + }) + + it('does not add duplicate classes', function() { + var element = draw.rect(100,100) + element.addClass('one') + element.addClass('one') + expect(element.node.getAttribute('class')).toEqual('one') + }) + + it('returns the svg instance', function() { + var element = draw.rect(100,100) + expect(element.addClass('one')).toEqual(element) + }) + }) + + describe('removeClass()', function() { + it('removes the class from the node when the class exists', function() { + var element = draw.rect(100,100) + element.addClass('one') + element.removeClass('one') + expect(element.hasClass('one')).toBeFalsy() + }) + + it('does nothing when the class does not exist', function() { + var element = draw.rect(100,100) + element.removeClass('one') + expect(element.hasClass('one')).toBeFalsy() + }) + + it('returns the element', function() { + var element = draw.rect(100,100) + expect(element.removeClass('one')).toEqual(element) + }) + }) + + describe('toggleClass()', function() { + it('adds the class when it does not already exist', function(){ + var element = draw.rect(100,100) + element.toggleClass('one') + expect(element.hasClass('one')).toBeTruthy() + }) + it('removes the class when it already exists', function(){ + var element = draw.rect(100,100) + element.addClass('one') + element.toggleClass('one') + expect(element.hasClass('one')).toBeFalsy() + }) + it('returns the svg instance', function() { + var element = draw.rect(100,100) + expect(element.toggleClass('one')).toEqual(element) + }) + }) + + describe('reference()', function() { + it('gets a referenced element from a given attribute', function() { + var rect = draw.defs().rect(100, 100) + , use = draw.use(rect) + , mark = draw.marker(10, 10) + , path = draw.path(svgPath).marker('end', mark) + + expect(use.reference('href')).toBe(rect) + expect(path.reference('marker-end')).toBe(mark) + }) + }) + + describe('svg()', function() { + describe('without an argument', function() { + it('returns full raw svg when called on the main svg doc', function() { + draw.size(100,100).rect(100,100).id(null) + draw.circle(100).fill('#f06').id(null) + expect(draw.svg()).toBe('') + }) + it('returns partial raw svg when called on a sub group', function() { + var group = draw.group().id(null) + group.rect(100,100).id(null) + group.circle(100).fill('#f06').id(null) + expect(group.svg()).toBe('') + }) + it('returns a single element when called on an element', function() { + var group = draw.group().id(null) + group.rect(100,100).id(null) + var circle = group.circle(100).fill('#f06').id(null) + expect(circle.svg()).toBe('') + }) + }) + describe('with raw svg given', function() { + it('imports a full svg document', function() { + draw.svg('') + expect(draw.get(0).type).toBe('svg') + expect(draw.get(0).children().length).toBe(2) + expect(draw.get(0).get(0).type).toBe('rect') + expect(draw.get(0).get(1).type).toBe('circle') + expect(draw.get(0).get(1).attr('fill')).toBe('#ff0066') + }) + it('imports partial svg content', function() { + draw.svg('') + expect(draw.get(0).type).toBe('g') + expect(draw.get(0).get(0).type).toBe('rect') + expect(draw.get(0).get(1).type).toBe('circle') + expect(draw.get(0).get(1).attr('fill')).toBe('#ff0066') + }) + it('does not import on single elements, even with an argument it acts as a getter', function() { + var rect = draw.rect(100,100).id(null) + , result = rect.svg('') + expect(result).toBe('') + }) + }) + }) + + describe('writeDataToDom()', function() { + it('set all properties in el.dom to the svgjs:data attribute', function(){ + var rect = draw.rect(100,100) + rect.dom.foo = 'bar' + rect.dom.number = new SVG.Number('3px') + + rect.writeDataToDom() + + expect(rect.attr('svgjs:data')).toBe('{"foo":"bar","number":"3px"}') + }) + }) + + describe('setData()', function() { + it('read all data from the svgjs:data attribute and assign it to el.dom', function(){ + var rect = draw.rect(100,100) + + rect.attr('svgjs:data', '{"foo":"bar","number":"3px"}') + rect.setData(JSON.parse(rect.attr('svgjs:data'))) + + expect(rect.dom.foo).toBe('bar') + expect(rect.dom.number).toBe('3px') + }) + }) + + describe('point()', function() { + it('creates a point from screen coordinates transformed in the elements space', function(){ + var rect = draw.rect(100,100) + expect(rect.point(2,5).x).toBeCloseTo(-6) + expect(rect.point(2,5).y).toBeCloseTo(-3) + }) + }) +}) diff --git a/node_modules/svgjs/spec/spec/ellipse.js b/node_modules/svgjs/spec/spec/ellipse.js new file mode 100644 index 0000000..2267d74 --- /dev/null +++ b/node_modules/svgjs/spec/spec/ellipse.js @@ -0,0 +1,187 @@ +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) + }) + it('sets the value of x with the first argument', function() { + ellipse.x(123) + var box = ellipse.bbox() + expect(box.x).toBeCloseTo(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(ellipse.y()).toBe(0) + }) + it('sets the value of cy with the first argument', function() { + ellipse.y(345) + var box = ellipse.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + expect(ellipse.cx()).toBe(120) + }) + it('sets the value of cx with the first argument', function() { + ellipse.cx(123) + var box = ellipse.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + expect(ellipse.cy()).toBe(45) + }) + it('sets the value of cy with the first argument', function() { + ellipse.cy(345) + var box = ellipse.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('radius()', function() { + it('sets the rx and ry', function() { + ellipse.radius(10, 20) + expect(ellipse.node.getAttribute('rx')).toBe('10') + expect(ellipse.node.getAttribute('ry')).toBe('20') + }) + it('sets the rx and ry if only rx given', function() { + ellipse.radius(30) + expect(ellipse.node.getAttribute('rx')).toBe('30') + expect(ellipse.node.getAttribute('ry')).toBe('30') + }) + it('sets the rx and ry value correctly when given 0', function() { + ellipse.radius(11, 0) + expect(ellipse.node.getAttribute('rx')).toBe('11') + expect(ellipse.node.getAttribute('ry')).toBe('0') + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + ellipse.move(123, 456) + var box = ellipse.bbox() + expect(box.x).toBeCloseTo(123) + expect(box.y).toBeCloseTo(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + ellipse.move(50, 60) + ellipse.dx(100) + expect(ellipse.node.getAttribute('cx')).toBe('270') + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + ellipse.move(50, 60) + ellipse.dy(120) + expect(ellipse.node.getAttribute('cy')).toBe('225') + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + ellipse.move(50,60) + ellipse.dmove(80, 25) + expect(ellipse.node.getAttribute('cx')).toBe('250') + expect(ellipse.node.getAttribute('cy')).toBe('130') + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + ellipse.center(321,567) + var box = ellipse.bbox() + expect(box.cx).toBe(321) + expect(box.cy).toBe(567) + }) + }) + + describe('width()', function() { + it('sets the width of the element', function() { + ellipse.width(82) + expect(ellipse.node.getAttribute('rx')).toBe('41') + }) + it('gets the width of the element if the argument is null', function() { + expect((ellipse.width() / 2).toString()).toBe(ellipse.node.getAttribute('rx')) + }) + }) + + describe('height()', function() { + it('sets the height of the element', function() { + ellipse.height(1236) + expect(ellipse.node.getAttribute('ry')).toBe('618') + }) + it('gets the height of the element if the argument is null', 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) + expect(ellipse.node.getAttribute('rx')).toBe((987 / 2).toString()) + expect(ellipse.node.getAttribute('ry')).toBe((654 / 2).toString()) + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = ellipse.bbox() + ellipse.size(500) + expect(ellipse.width()).toBe(500) + expect(ellipse.width() / ellipse.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = ellipse.bbox() + ellipse.size(null, 525) + expect(ellipse.height()).toBe(525) + 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).tbox() + + 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).tbox() + + expect(box.width).toBe(ellipse.attr('rx') * 2 * 2) + expect(box.height).toBe(ellipse.attr('ry') * 2 * 3.5) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + ellipse.transform({ x: 12, y: 12 }) + expect(ellipse.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/event.js b/node_modules/svgjs/spec/spec/event.js new file mode 100644 index 0000000..9c945d0 --- /dev/null +++ b/node_modules/svgjs/spec/spec/event.js @@ -0,0 +1,470 @@ +describe('Event', function() { + var rect, context + , toast = null + , fruitsInDetail = null, + action = function(e) { + toast = 'ready' + context = this + fruitsInDetail = e.detail || null + } + + beforeEach(function() { + rect = draw.rect(100, 100) + }) + + afterEach(function() { + toast = context = null + }) + + if (!window.isTouchDevice) { + + describe('click()', function() { + it('attaches an onclick event to the node of the element', function() { + expect(typeof rect.node.onclick).not.toBe('function') + rect.click(action) + expect(typeof rect.node.onclick).toBe('function') + }) + it('fires the event on click', function() { + dispatchEvent(rect.click(action), 'click') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.click(action), 'click') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.click(action)).toBe(rect) + }) + }) + + describe('dblclick()', function() { + it('attaches an ondblclick event to the node of the element', function() { + expect(typeof rect.node.ondblclick).not.toBe('function') + rect.dblclick(action) + expect(typeof rect.node.ondblclick).toBe('function') + }) + it('fires the event on dblclick', function() { + dispatchEvent(rect.dblclick(action), 'dblclick') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.dblclick(action), 'dblclick') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.dblclick(action)).toBe(rect) + }) + }) + + describe('mousedown()', function() { + it('attaches an onmousedown event to the node of the element', function() { + expect(typeof rect.node.onmousedown).not.toBe('function') + rect.mousedown(action) + expect(typeof rect.node.onmousedown).toBe('function') + }) + it('fires the event on mousedown', function() { + dispatchEvent(rect.mousedown(action), 'mousedown') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mousedown(action), 'mousedown') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mousedown(action)).toBe(rect) + }) + }) + + describe('mouseup()', function() { + it('attaches an onmouseup event to the node of the element', function() { + expect(typeof rect.node.onmouseup).not.toBe('function') + rect.mouseup(action) + expect(typeof rect.node.onmouseup).toBe('function') + }) + it('fires the event on mouseup', function() { + dispatchEvent(rect.mouseup(action), 'mouseup') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mouseup(action), 'mouseup') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mouseup(action)).toBe(rect) + }) + }) + + describe('mouseover()', function() { + it('attaches an onmouseover event to the node of the element', function() { + expect(typeof rect.node.onmouseover).not.toBe('function') + rect.mouseover(action) + expect(typeof rect.node.onmouseover).toBe('function') + }) + it('fires the event on mouseover', function() { + dispatchEvent(rect.mouseover(action), 'mouseover') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mouseover(action), 'mouseover') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mouseover(action)).toBe(rect) + }) + }) + + describe('mouseout()', function() { + it('attaches an onmouseout event to the node of the element', function() { + expect(typeof rect.node.onmouseout).not.toBe('function') + rect.mouseout(action) + expect(typeof rect.node.onmouseout).toBe('function') + }) + it('fires the event on mouseout', function() { + dispatchEvent(rect.mouseout(action), 'mouseout') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mouseout(action), 'mouseout') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mouseout(action)).toBe(rect) + }) + }) + + describe('mousemove()', function() { + it('attaches an onmousemove event to the node of the element', function() { + expect(typeof rect.node.onmousemove).not.toBe('function') + rect.mousemove(action) + expect(typeof rect.node.onmousemove).toBe('function') + }) + it('fires the event on mousemove', function() { + dispatchEvent(rect.mousemove(action), 'mousemove') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mousemove(action), 'mousemove') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mousemove(action)).toBe(rect) + }) + }) + + /*describe('mouseenter()', function() { + it('attaches an onmouseenter event to the node of the element', function() { + expect(typeof rect.node.onmouseenter).not.toBe('function') + rect.mouseenter(action) + expect(typeof rect.node.onmouseenter).toBe('function') + }) + it('fires the event on mouseenter', function() { + dispatchEvent(rect.mouseenter(action), 'mouseenter') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mouseenter(action), 'mouseenter') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mouseenter(action)).toBe(rect) + }) + }) + + describe('mouseleave()', function() { + it('attaches an onmouseleave event to the node of the element', function() { + expect(typeof rect.node.onmouseleave).not.toBe('function') + rect.mouseleave(action) + expect(typeof rect.node.onmouseleave).toBe('function') + }) + it('fires the event on mouseleave', function() { + dispatchEvent(rect.mouseleave(action), 'mouseleave') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.mouseleave(action), 'mouseleave') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.mouseleave(action)).toBe(rect) + }) + })*/ + + } else { + + describe('touchstart()', function() { + it('attaches an ontouchstart event to the node of the element', function() { + expect(typeof rect.node.ontouchstart).not.toBe('function') + rect.touchstart(action) + expect(typeof rect.node.ontouchstart).toBe('function') + }) + it('fires the event on touchstart', function() { + dispatchEvent(rect.touchstart(action), 'touchstart') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.touchstart(action), 'touchstart') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.touchstart(action)).toBe(rect) + }) + }) + + describe('touchmove()', function() { + it('attaches an ontouchmove event to the node of the element', function() { + expect(typeof rect.node.ontouchmove).not.toBe('function') + rect.touchmove(action) + expect(typeof rect.node.ontouchmove).toBe('function') + }) + it('fires the event on touchmove', function() { + dispatchEvent(rect.touchmove(action), 'touchmove') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.touchmove(action), 'touchmove') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.touchmove(action)).toBe(rect) + }) + }) + + describe('touchleave()', function() { + it('attaches an ontouchleave event to the node of the element', function() { + expect(typeof rect.node.ontouchleave).not.toBe('function') + rect.touchleave(action) + expect(typeof rect.node.ontouchleave).toBe('function') + }) + it('fires the event on touchleave', function() { + dispatchEvent(rect.touchleave(action), 'touchleave') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.touchleave(action), 'touchleave') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.touchleave(action)).toBe(rect) + }) + }) + + describe('touchend()', function() { + it('attaches an ontouchend event to the node of the element', function() { + expect(typeof rect.node.ontouchend).not.toBe('function') + rect.touchend(action) + expect(typeof rect.node.ontouchend).toBe('function') + }) + it('fires the event on touchend', function() { + dispatchEvent(rect.touchend(action), 'touchend') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.touchend(action), 'touchend') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.touchend(action)).toBe(rect) + }) + }) + + describe('touchcancel()', function() { + it('attaches an ontouchcancel event to the node of the element', function() { + expect(typeof rect.node.ontouchcancel).not.toBe('function') + rect.touchcancel(action) + expect(typeof rect.node.ontouchcancel).toBe('function') + }) + it('fires the event on touchcancel', function() { + dispatchEvent(rect.touchcancel(action), 'touchcancel') + expect(toast).toBe('ready') + }) + it('applies the element as context', function() { + dispatchEvent(rect.touchcancel(action), 'touchcancel') + expect(context).toBe(rect) + }) + it('returns the called element', function() { + expect(rect.touchcancel(action)).toBe(rect) + }) + }) + + } + + + describe('on()', function() { + + it('attaches and event to the element', function() { + dispatchEvent(rect.on('event', action), 'event') + expect(toast).toBe('ready') + }) + it('attaches multiple handlers on different element', function() { + var listenerCnt = SVG.listeners.length + + var rect2 = draw.rect(100,100); + var rect3 = draw.rect(100,100); + + rect.on('event', action) + rect2.on('event', action) + rect3.on('event', function(){ butter = 'melting' }) + rect3.on('event', action) + + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*']).length).toBe(1) // 1 listener on rect + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['*']).length).toBe(2) // 2 listener on rect3 + expect(SVG.listeners.length).toBe(listenerCnt + 3) // added listeners on 3 different elements + }) + if('attaches a handler to a namespaced event', function(){ + var listenerCnt = SVG.listeners.length + + var rect2 = draw.rect(100,100); + var rect3 = draw.rect(100,100); + + rect.on('event.namespace1', action) + rect2.on('event.namespace2', action) + rect3.on('event.namespace3', function(){ butter = 'melting' }) + rect3.on('event', action) + + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'])).toBeUndefined() // no global listener on rect + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace1']).length).toBe( 1) // 1 namespaced listener on rect + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect2.node)]['event']['namespace2']).length).toBe(1) // 1 namespaced listener on rect + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['*']).length).toBe(1) // 1 gobal listener on rect3 + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['namespace3']).length).toBe(1) // 1 namespaced listener on rect3 + expect(SVG.listeners.length).toBe(listenerCnt + 3) // added listeners on 3 different elements + }) + it('applies the element as context', function() { + dispatchEvent(rect.on('event', action), 'event') + expect(context).toBe(rect) + }) + it('applies given object as context', function() { + dispatchEvent(rect.on('event', action, this), 'event') + expect(context).toBe(this) + }) + it('stores the listener for future reference', function() { + rect.on('event', action) + expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'][action]).not.toBeUndefined() + }) + it('returns the called element', function() { + expect(rect.on('event', action)).toBe(rect) + }) + }) + + describe('off()', function() { + var butter = null + + beforeEach(function() { + butter = null + }) + + it('detaches a specific event listener, all other still working', function() { + rect2 = draw.rect(100,100); + rect3 = draw.rect(100,100); + + rect.on('event', action) + rect2.on('event', action) + rect3.on('event', function(){ butter = 'melting' }) + + rect.off('event', action) + + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*']).length).toBe(0) + + dispatchEvent(rect, 'event') + expect(toast).toBeNull() + + dispatchEvent(rect2, 'event') + expect(toast).toBe('ready') + + dispatchEvent(rect3, 'event') + expect(butter).toBe('melting') + + expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'][action]).toBeUndefined() + }) + it('detaches a specific namespaced event listener, all other still working', function() { + rect2 = draw.rect(100,100); + rect3 = draw.rect(100,100); + + rect.on('event.namespace', action) + rect2.on('event.namespace', action) + rect3.on('event.namespace', function(){ butter = 'melting' }) + + rect.off('event.namespace', action) + + expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace']).length).toBe(0) + + dispatchEvent(rect, 'event') + expect(toast).toBeNull() + + dispatchEvent(rect2, 'event') + expect(toast).toBe('ready') + + dispatchEvent(rect3, 'event') + expect(butter).toBe('melting') + + expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace'][action]).toBeUndefined() + }) + it('detaches all listeners for a specific namespace', function() { + rect.on('event', action) + rect.on('event.namespace', function() { butter = 'melting'; }) + rect.off('.namespace') + + dispatchEvent(rect, 'event') + expect(toast).toBe('ready') + expect(butter).toBeNull() + }) + it('detaches all listeners for an event without a listener given', function() { + rect.on('event', action) + rect.on('event.namespace', function() { butter = 'melting'; }) + rect.off('event') + + dispatchEvent(rect, 'event') + expect(toast).toBeNull() + expect(butter).toBeNull() + expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']).toBeUndefined() + }) + it('detaches all listeners without an argument', function() { + rect.on('event', action) + rect.on('click', function() { butter = 'melting' }) + rect.off() + dispatchEvent(rect, 'event') + dispatchEvent(rect, 'click') + expect(toast).toBeNull() + expect(butter).toBeNull() + expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]).toBeUndefined() + }) + it('returns the called element', function() { + expect(rect.off('event', action)).toBe(rect) + }) + }) + + describe('fire()', function() { + + beforeEach(function() { + rect.on('event', action) + }) + + it('fires an event for the element', function() { + expect(toast).toBeNull() + rect.fire('event') + expect(toast).toBe('ready') + expect(fruitsInDetail).toBe(null) + }) + it('returns the called element', function() { + expect(rect.fire('event')).toBe(rect) + }) + it('fires event with additional data', function() { + expect(fruitsInDetail).toBeNull() + rect.fire('event', {apple:1}) + expect(fruitsInDetail).not.toBe(null) + expect(fruitsInDetail.apple).toBe(1) + }) + it('fires my own event', function() { + toast = null + rect.fire(new CustomEvent('event')) + expect(toast).toBe('ready') + }) + }) + + +}) + + + + + + diff --git a/node_modules/svgjs/spec/spec/fx.js b/node_modules/svgjs/spec/spec/fx.js new file mode 100644 index 0000000..f1171f5 --- /dev/null +++ b/node_modules/svgjs/spec/spec/fx.js @@ -0,0 +1,59 @@ +describe('FX', function() { + var rect, fx; + + beforeEach(function() { + rect = draw.rect(100,100).move(100,100) + fx = rect.animate(500) + }) + + it('creates an instance of SVG.FX', function() { + expect(fx instanceof SVG.FX).toBe(true) + }) + + it('animates the x/y-attr', function(done) { + + fx.move(200,200).after(function(){ + + expect(rect.x()).toBe(200) + expect(rect.y()).toBe(200) + done() + + }); + + setTimeout(function(){ + expect(rect.x()).toBeGreaterThan(100) + expect(rect.y()).toBeGreaterThan(100) + }, 250) + + }) + + it('animates matrix', function(done) { + + 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) + + done() + + }) + + setTimeout(function(){ + + var 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) + }, 250) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/gradient.js b/node_modules/svgjs/spec/spec/gradient.js new file mode 100644 index 0000000..b84ccb9 --- /dev/null +++ b/node_modules/svgjs/spec/spec/gradient.js @@ -0,0 +1,115 @@ +describe('Gradient', function() { + var rect, gradient + + beforeEach(function() { + rect = draw.rect(100,100) + gradient = draw.gradient('linear', function(stop) { + stop.at({ offset: 0, color: '#333', opacity: 1 }) + stop.at({ offset: 1, color: '#fff', opacity: 1 }) + }) + }) + + afterEach(function() { + rect.remove() + gradient.remove() + }) + + it('is an instance of SVG.Gradient', function() { + expect(gradient instanceof SVG.Gradient).toBe(true) + }) + + it('allows creation of a new gradient without block', function() { + gradient = draw.gradient('linear') + expect(gradient.children().length).toBe(0) + }) + + describe('fill()', function() { + it('returns the id of the gradient wrapped in url()', function() { + expect(gradient.fill()).toBe('url(#' + gradient.attr('id') + ')') + }) + }) + + describe('toString()', function() { + it('returns the id of the gradient wrapped in url()', function() { + expect(gradient + '').toBe('url(#' + gradient.attr('id') + ')') + }) + it('is called when instance is passed as an attribute value', function() { + rect.attr('fill', gradient) + expect(rect.attr('fill')).toBe('url(#' + gradient.attr('id') + ')') + }) + }) + + describe('input values', function() { + var s1, s2 + + it('accepts floats', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at({ offset: 0.12, color: '#333', opacity: 1 }) + s2 = stop.at({ offset: 0.93, color: '#fff', opacity: 1 }) + }) + expect(s1.attr('offset')).toBe(0.12) + expect(s2.attr('offset')).toBe(0.93) + }) + it('accepts string floats', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at({ offset: '0.13', color: '#333', opacity: 1 }) + s2 = stop.at({ offset: '0.92', color: '#fff', opacity: 1 }) + }) + expect(s1.attr('offset')).toBe(0.13) + expect(s2.attr('offset')).toBe(0.92) + }) + it('accept percentages', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at({ offset: '14%', color: '#333', opacity: 1 }) + s2 = stop.at({ offset: '91%', color: '#fff', opacity: 1 }) + }) + expect(s1.attr('offset')).toBe('14%') + expect(s2.attr('offset')).toBe('91%') + }) + }) + + describe('update()', function() { + + it('removes all existing children first', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at({ offset: 0.12, color: '#333', opacity: 1 }) + s2 = stop.at({ offset: 0.93, color: '#fff', opacity: 1 }) + }) + expect(gradient.children().length).toBe(2) + gradient.update(function(stop) { + s1 = stop.at({ offset: 0.33, color: '#666', opacity: 1 }) + s2 = stop.at({ offset: 1, color: '#000', opacity: 1 }) + }) + expect(gradient.children().length).toBe(2) + }) + + it('accepts multiple aruments on fixed positions', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at(0.11, '#333') + s2 = stop.at(0.94, '#fff', 0.5) + }) + expect(gradient.children().length).toBe(2) + expect(s1.attr('offset')).toBe(0.11) + expect(s1.attr('stop-color')).toBe('#333333') + expect(s2.attr('offset')).toBe(0.94) + expect(s2.attr('stop-color')).toBe('#ffffff') + expect(s2.attr('stop-opacity')).toBe(0.5) + }) + + }) + + describe('get()', function() { + + it('returns the stop at a given index', function() { + gradient = draw.gradient('linear', function(stop) { + s1 = stop.at({ offset: 0.12, color: '#333', opacity: 1 }) + s2 = stop.at({ offset: 0.93, color: '#fff', opacity: 1 }) + }) + expect(gradient.get(0)).toBe(s1) + expect(gradient.get(1)).toBe(s2) + expect(gradient.get(2)).toBe(undefined) + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/group.js b/node_modules/svgjs/spec/spec/group.js new file mode 100644 index 0000000..63335ae --- /dev/null +++ b/node_modules/svgjs/spec/spec/group.js @@ -0,0 +1,118 @@ +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/node_modules/svgjs/spec/spec/helper.js b/node_modules/svgjs/spec/spec/helper.js new file mode 100644 index 0000000..9cd88cd --- /dev/null +++ b/node_modules/svgjs/spec/spec/helper.js @@ -0,0 +1,42 @@ +// create canavs +var drawing = document.createElement('div') +drawing.id = 'drawing' +document.getElementsByTagName('body')[0].appendChild(drawing) +draw = SVG(drawing).size(100,100) + +// raw path data +svgPath = 'M88.006,61.994c3.203,0,6.216-1.248,8.481-3.514C98.752,56.215,100,53.203,100,50c0-3.204-1.248-6.216-3.513-8.481 c-2.266-2.265-5.278-3.513-8.481-3.513c-2.687,0-5.237,0.877-7.327,2.496h-7.746l5.479-5.479 c5.891-0.757,10.457-5.803,10.457-11.896c0-6.614-5.381-11.995-11.994-11.995c-6.093,0-11.14,4.567-11.896,10.457l-5.479,5.479 v-7.747c1.618-2.089,2.495-4.641,2.495-7.327c0-3.204-1.247-6.216-3.513-8.481C56.216,1.248,53.204,0,50,0 c-3.204,0-6.216,1.248-8.481,3.513c-2.265,2.265-3.513,5.277-3.513,8.481c0,2.686,0.877,5.237,2.495,7.327v7.747l-5.479-5.479 c-0.757-5.89-5.803-10.457-11.896-10.457c-6.614,0-11.995,5.381-11.995,11.995c0,6.093,4.567,11.139,10.458,11.896l5.479,5.479 h-7.747c-2.089-1.619-4.641-2.496-7.327-2.496c-3.204,0-6.216,1.248-8.481,3.513C1.248,43.784,0,46.796,0,50 c0,3.203,1.248,6.216,3.513,8.48c2.265,2.266,5.277,3.514,8.481,3.514c2.686,0,5.237-0.877,7.327-2.496h7.747l-5.479,5.479 c-5.891,0.757-10.458,5.804-10.458,11.896c0,6.614,5.381,11.994,11.995,11.994c6.093,0,11.139-4.566,11.896-10.457l5.479-5.479 v7.749c-3.63,4.7-3.291,11.497,1.018,15.806C43.784,98.752,46.796,100,50,100c3.204,0,6.216-1.248,8.481-3.514 c4.309-4.309,4.647-11.105,1.018-15.806v-7.749l5.479,5.479c0.757,5.891,5.804,10.457,11.896,10.457 c6.613,0,11.994-5.38,11.994-11.994c0-6.093-4.566-11.14-10.457-11.896l-5.479-5.479h7.746 C82.769,61.117,85.319,61.994,88.006,61.994z M76.874,68.354c4.705,0,8.52,3.814,8.52,8.521c0,4.705-3.814,8.52-8.52,8.52 s-8.52-3.814-8.52-8.52l-12.33-12.33V81.98c3.327,3.328,3.327,8.723,0,12.049c-3.327,3.328-8.722,3.328-12.049,0 c-3.327-3.326-3.327-8.721,0-12.049V64.544l-12.33,12.33c0,4.705-3.814,8.52-8.52,8.52s-8.52-3.814-8.52-8.52 c0-4.706,3.814-8.521,8.52-8.521l12.33-12.33H18.019c-3.327,3.328-8.722,3.328-12.049,0c-3.327-3.326-3.327-8.721,0-12.048 s8.722-3.327,12.049,0h17.438l-12.33-12.33c-4.706,0-8.52-3.814-8.52-8.52c0-4.706,3.814-8.52,8.52-8.52s8.52,3.814,8.52,8.52 l12.33,12.33V18.019c-3.327-3.327-3.327-8.722,0-12.049s8.722-3.327,12.049,0s3.327,8.722,0,12.049v17.438l12.33-12.33 c0-4.706,3.814-8.52,8.52-8.52s8.52,3.814,8.52,8.52c0,4.705-3.814,8.52-8.52,8.52l-12.33,12.33h17.438 c3.327-3.327,8.722-3.327,12.049,0s3.327,8.722,0,12.048c-3.327,3.328-8.722,3.328-12.049,0H64.544L76.874,68.354z' + +// image url +imageUrl = '' + +// lorem ipsum text +loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sodales\n imperdiet auctor. Nunc ultrices lectus at erat dictum pharetra\n elementum ante posuere. Duis turpis risus, blandit nec elementum et,\n posuere eget lacus. Aliquam et risus magna, eu aliquet nibh. Fusce\n consequat mi quis purus varius sagittis euismod urna interdum.\n Curabitur aliquet orci quis felis semper vulputate. Vestibulum ac nisi\n magna, id dictum diam. Proin sed metus vel magna blandit\n sodales. Pellentesque at neque ultricies nunc euismod rutrum ut in\n lorem. Mauris euismod tellus in tellus tempus interdum. Phasellus\n mattis sapien et leo feugiat dictum. Vestibulum at volutpat velit.' + +// test for touch device +window.isTouchDevice = 'ontouchstart' in document.documentElement + +// strip spaces from result +function stripped(string) { + return string.replace(/\s+/g, '') +} + +// dispatch an event +function dispatchEvent(element, name) { + var e + + if (document.createEvent) { + e = document.createEvent('HTMLEvents') + e.initEvent(name, true, true) + } else { + e = document.createEventObject() + e.eventType = name + } + + e.eventName = name + + if (document.createEvent) + element.node.dispatchEvent(e) + else + element.node.fireEvent('on' + name, e) +} \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/hyperlink.js b/node_modules/svgjs/spec/spec/hyperlink.js new file mode 100644 index 0000000..affef6d --- /dev/null +++ b/node_modules/svgjs/spec/spec/hyperlink.js @@ -0,0 +1,61 @@ +describe('Hyperlink', function() { + var link + , url = 'http://svgjs.com' + + beforeEach(function() { + link = draw.link(url) + link.rect(100,100) + }) + + afterEach(function() { + draw.clear() + }) + + it('creates a link', function() { + expect(link.attr('href')).toBe(url) + }) + + describe('to()', function() { + it('creates xlink:href attribute', function() { + link.to('http://apple.com') + expect(link.attr('href')).toBe('http://apple.com') + }) + }) + + describe('show()', function() { + it('creates xlink:show attribute', function() { + link.show('replace') + expect(link.attr('show')).toBe('replace') + }) + }) + + describe('target()', function() { + it('creates target attribute', function() { + link.target('_blank') + expect(link.attr('target')).toBe('_blank') + }) + }) + + describe('SVG.Element', function() { + var element + + beforeEach(function() { + element = draw.rect(100,100) + }) + + describe('linkTo()', function() { + it('wraps the called element in a link with given url', function() { + element.linkTo(url) + expect(element.parent().attr('href')).toBe(url) + }) + it('wraps the called element in a link with given block', function() { + element.linkTo(function(link) { + link.to(url).target('_blank') + }) + expect(element.parent().attr('href')).toBe(url) + expect(element.parent().attr('target')).toBe('_blank') + }) + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/image.js b/node_modules/svgjs/spec/spec/image.js new file mode 100644 index 0000000..a764265 --- /dev/null +++ b/node_modules/svgjs/spec/spec/image.js @@ -0,0 +1,177 @@ +describe('Image', function() { + var image + + beforeEach(function() { + image = draw.image(imageUrl, 100, 100) + }) + + afterEach(function() { + draw.clear() + }) + + describe('x()', function() { + it('should return the value of x without an argument', function() { + expect(image.x()).toBe(0) + }) + it('should set the value of x with the first argument', function() { + image.x(123) + var box = image.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('should return the value of y without an argument', function() { + expect(image.y()).toBe(0) + }) + it('should set the value of y with the first argument', function() { + image.y(345) + var box = image.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('should return the value of cx without an argument', function() { + expect(image.cx()).toBe(50) + }) + it('should set the value of cx with the first argument', function() { + image.cx(123) + var box = image.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('should return the value of cy without an argument', function() { + expect(image.cy()).toBe(50) + }) + it('should set the value of cy with the first argument', function() { + image.cy(345) + var box = image.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('move()', function() { + it('should set the x and y position', function() { + image.move(123,456) + expect(image.node.getAttribute('x')).toBe('123') + expect(image.node.getAttribute('y')).toBe('456') + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + image.move(50,60) + image.dx(100) + expect(image.node.getAttribute('x')).toBe('150') + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + image.move(50,60) + image.dy(120) + expect(image.node.getAttribute('y')).toBe('180') + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + image.move(50,60) + image.dmove(80, 25) + expect(image.node.getAttribute('x')).toBe('130') + expect(image.node.getAttribute('y')).toBe('85') + }) + }) + + describe('center()', function() { + it('should set the cx and cy position', function() { + image.center(321,567) + var box = image.bbox() + expect(box.cx).toBe(321) + expect(box.cy).toBe(567) + }) + }) + + describe('width()', function() { + it('sets the width of the element', function() { + image.width(789) + expect(image.node.getAttribute('width')).toBe('789') + }) + it('gets the width of the element if the argument is null', function() { + expect(image.width().toString()).toBe(image.node.getAttribute('width')) + }) + }) + + describe('height()', function() { + it('sets the height of the element', function() { + image.height(1236) + expect(image.node.getAttribute('height')).toBe('1236') + }) + it('gets the height of the element if the argument is null', function() { + expect(image.height().toString()).toBe(image.node.getAttribute('height')) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + image.size(987,654) + expect(image.node.getAttribute('width')).toBe('987') + expect(image.node.getAttribute('height')).toBe('654') + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = image.bbox() + image.size(500) + expect(image.width()).toBe(500) + expect(image.width() / image.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = image.bbox() + image.size(null, 525) + expect(image.height()).toBe(525) + expect(image.width() / image.height()).toBe(box.width / box.height) + }) + }) + + describe('scale()', function() { + it('should scale the element universally with one argument', function() { + var box = image.scale(2).tbox() + + expect(box.width).toBe(image.attr('width') * 2) + expect(box.height).toBe(image.attr('height') * 2) + }) + it('should scale the element over individual x and y axes with two arguments', function() { + var box = image.scale(2, 3.5).tbox() + + expect(box.width).toBe(image.attr('width') * 2) + expect(box.height).toBe(image.attr('height') * 3.5) + }) + }) + + describe('translate()', function() { + it('should set the translation of an element', function() { + image.transform({ x: 12, y: 12 }) + expect(image.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + + + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/line.js b/node_modules/svgjs/spec/spec/line.js new file mode 100644 index 0000000..8e19014 --- /dev/null +++ b/node_modules/svgjs/spec/spec/line.js @@ -0,0 +1,208 @@ +describe('Line', function() { + var line + + beforeEach(function() { + line = draw.line(0,100,100,0) + }) + + afterEach(function() { + draw.clear() + }) + + describe('x()', function() { + it('should return the value of x without an argument', function() { + expect(line.x()).toBe(0) + }) + it('should set the value of x with the first argument', function() { + line.x(123) + var box = line.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('should return the value of y without an argument', function() { + expect(line.y()).toBe(0) + }) + it('should set the value of y with the first argument', function() { + line.y(345) + var box = line.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('should return the value of cx without an argument', function() { + expect(line.cx()).toBe(50) + }) + it('should set the value of cx with the first argument', function() { + line.cx(123) + var box = line.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('should return the value of cy without an argument', function() { + expect(line.cy()).toBe(50) + }) + it('should set the value of cy with the first argument', function() { + line.cy(345) + var box = line.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('move()', function() { + it('should set the x and y position', function() { + line.move(123,456) + var box = line.bbox() + expect(box.x).toBe(123) + expect(box.y + box.height).toBe(556) + expect(box.x + box.width).toBe(223) + expect(box.y).toBe(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + line.move(50,60) + line.dx(100) + var box = line.bbox() + expect(box.x).toBe(150) + expect(box.y + box.height).toBe(160) + expect(box.x + box.width).toBe(250) + expect(box.y).toBe(60) + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + line.move(50, 60) + line.dy(120) + var box = line.bbox() + expect(box.x).toBe(50) + expect(box.y + box.height).toBe(280) + expect(box.x + box.width).toBe(150) + expect(box.y).toBe(180) + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + line.move(50,60) + line.dmove(80, 25) + var box = line.bbox() + expect(box.x).toBe(130) + expect(box.y + box.height).toBe(185) + expect(box.x + box.width).toBe(230) + expect(box.y).toBe(85) + }) + }) + + describe('center()', function() { + it('should set the cx and cy position', function() { + line.center(321,567) + var box = line.bbox() + expect(box.x).toBe(271) + expect(box.y + box.height).toBe(617) + expect(box.x + box.width).toBe(371) + expect(box.y).toBe(517) + }) + }) + + describe('width()', function() { + it('sets the width of the element', function() { + line.width(400) + var box = line.bbox() + expect(box.x).toBe(0) + expect(box.x + box.width).toBe(400) + }) + it('get the width of the element without argument', function() { + line.width(123) + var box = line.bbox() + expect(line.width()).toBe(box.width) + }) + }) + + describe('height()', function() { + it('sets the height of the element', function() { + line.height(300) + var box = line.bbox() + expect(box.y).toBe(0) + expect(box.y + box.height).toBe(300) + }) + it('gets the height of the element without argument', function() { + line.height(456) + var box = line.bbox() + expect(line.height()).toBe(box.height) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + line.size(987,654) + var box = line.bbox() + expect(box.x).toBe(0) + expect(box.y + box.height).toBe(654) + expect(box.x + box.width).toBe(987) + expect(box.y).toBe(0) + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = line.bbox() + line.size(500) + expect(line.width()).toBe(500) + expect(line.width() / line.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = line.bbox() + line.size(null, 525) + expect(line.height()).toBe(525) + expect(line.width() / line.height()).toBe(box.width / box.height) + }) + }) + + describe('scale()', function() { + it('should scale the element universally with one argument', function() { + var box1 = line.tbox() + , box2 = line.scale(2).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 2) + }) + it('should scale the element over individual x and y axes with two arguments', function() { + var box1 = line.tbox() + , box2 = line.scale(2,3.5).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 3.5) + }) + }) + + describe('translate()', function() { + it('should set the translation of an element', function() { + line.transform({ x: 12, y: 12 }) + expect(line.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + + describe('plot()', function() { + it('should update the start and end points', function() { + line.plot(100,200,300,400) + var box = line.bbox() + expect(box.x).toBe(100) + expect(box.y).toBe(200) + expect(box.x + box.width).toBe(300) + expect(box.y + box.height).toBe(400) + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/marker.js b/node_modules/svgjs/spec/spec/marker.js new file mode 100644 index 0000000..7b902d4 --- /dev/null +++ b/node_modules/svgjs/spec/spec/marker.js @@ -0,0 +1,89 @@ +describe('Marker', function() { + + describe('on a container element', function() { + var marker + + beforeEach(function() { + marker = draw.marker(10, 12, function(add) { + add.rect(10, 12) + + this.ref(5, 6) + }) + }) + + it('creates an instance of SVG.Marker', function() { + expect(marker instanceof SVG.Marker).toBeTruthy() + }) + + it('creates marker in defs', function() { + expect(marker.parent() instanceof SVG.Defs).toBeTruthy() + }) + + describe('marker()', function() { + it('returns the marker element', function() { + expect(marker = draw.marker(10, 12)).toBe(marker) + }) + it('sets the refX to half of the given width', function() { + marker = draw.marker(10, 12) + expect(marker.node.getAttribute('refX')).toBe('5') + }) + it('sets the refY to half of the given height', function() { + marker = draw.marker(13, 15) + expect(marker.node.getAttribute('refY')).toBe('7.5') + }) + }) + + }) + + describe('on a target path', function() { + var path, marker + + beforeEach(function() { + path = draw.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') + + path.marker('mid', 10, 12, function(add) { + add.rect(10, 12) + + this.ref(5, 6) + }) + + marker = path.marker('mid', 10, 10) + }) + + it('creates an instance of SVG.Marker', function() { + expect(path.reference('marker-mid') instanceof SVG.Marker).toBeTruthy() + }) + + describe('marker()', function() { + it('returns the target element', function() { + expect(path.marker('start', 10, 12)).toBe(path) + }) + it('creates a marker and applies it to the marker-start attribute', function() { + path.marker('start', 10, 12) + marker = path.reference('marker-start') + + expect(path.node.getAttribute('marker-start')).toBe(marker.toString()) + }) + it('creates a marker and applies it to the marker-mid attribute', function() { + path.marker('mid', 10, 12) + marker = path.reference('marker-mid') + + expect(path.node.getAttribute('marker-mid')).toBe(marker.toString()) + }) + it('creates a marker and applies it to the marker-end attribute', function() { + path.marker('end', 10, 12) + marker = path.reference('marker-end') + + expect(path.node.getAttribute('marker-end')).toBe(marker.toString()) + }) + it('accepts an instance of an existing marker element as the second argument', function() { + marker = draw.marker(11, 11) + path.marker('mid', marker) + + expect(path.node.getAttribute('marker-mid')).toBe(marker.toString()) + }) + }) + }) + + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/mask.js b/node_modules/svgjs/spec/spec/mask.js new file mode 100644 index 0000000..ab367a0 --- /dev/null +++ b/node_modules/svgjs/spec/spec/mask.js @@ -0,0 +1,57 @@ +describe('Mask', function() { + var rect, circle + + beforeEach(function() { + rect = draw.rect(100,100) + circle = draw.circle(100).move(50, 50).fill('#fff') + rect.maskWith(circle) + }) + + afterEach(function() { + draw.clear() + }) + + it('moves the masking element to a new mask node', function() { + expect(circle.parent() instanceof SVG.Mask).toBe(true) + }) + + it('creates the mask node in the defs node', function() { + expect(circle.parent().parent()).toBe(draw.defs()) + }) + + it('sets the "mask" attribute on the masked element with the mask id', function() { + expect(rect.attr('mask')).toBe('url("#' + circle.parent().attr('id') + '")') + }) + + it('references the mask element in the masked element', function() { + expect(rect.masker).toBe(circle.parent()) + }) + + it('references the masked element in the mask target list', function() { + expect(rect.masker.targets.indexOf(rect) > -1).toBe(true) + }) + + it('unmasks all masked elements when being removed', function() { + rect.masker.remove() + expect(rect.attr('mask')).toBe(undefined) + }) + + describe('unmask()', function() { + + it('clears the "mask" attribute on the masked element', function() { + rect.unmask() + expect(rect.attr('mask')).toBe(undefined) + }) + + it('removes the reference to the masking element', function() { + rect.unmask() + expect(rect.masker).toBe(undefined) + }) + + it('returns the element itslef', function() { + expect(rect.unmask()).toBe(rect) + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/matrix.js b/node_modules/svgjs/spec/spec/matrix.js new file mode 100644 index 0000000..5c4776b --- /dev/null +++ b/node_modules/svgjs/spec/spec/matrix.js @@ -0,0 +1,298 @@ +describe('Matrix', function() { + var matrix + + 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)') + }) + }) + }) + + 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) + }) + + }) + + }) + + 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) + }) + }) + + }) + + 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)') + }) + }) + + 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) + , 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)') + }) + 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') + + expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)') + expect(matrix2.toString()).toBe('matrix(2,0,0,5,8,15)') + }) + }) + + describe('inverse()', function() { + it('inverses matrix', function() { + var matrix1 = new SVG.Matrix(2, 0, 0, 5, 4, 3) + , matrix2 = matrix1.inverse() + + expect(matrix1.toString()).toBe('matrix(2,0,0,5,4,3)') + expect(matrix2.toString()).toBe('matrix(0.5,0,0,0.2,-2,-0.6)') + }) + }) + + 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) + }) + }) + + describe('scale()', function() { + it('performs a uniformal scale with one value', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3) + + expect(matrix.a).toBe(3) + expect(matrix.d).toBe(3) + expect(matrix.e).toBe(4) + expect(matrix.f).toBe(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) + }) + 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) + + expect(matrix.a).toBe(3) + expect(matrix.d).toBe(3) + expect(matrix.e).toBe(-2) + expect(matrix.f).toBe(-197) + }) + it('performs a non-uniformal scale at a given center point with our values', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3, 2, 150, 100) + + expect(matrix.a).toBe(3) + expect(matrix.d).toBe(2) + expect(matrix.e).toBe(-296) + expect(matrix.f).toBe(-97) + }) + }) + + describe('rotate()', function() { + it('performs a rotation with one argument', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 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) + }) + 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) + + expect(matrix.a).toBeCloseTo(0.8660254037844387) + expect(matrix.d).toBeCloseTo(0.8660254037844387) + expect(matrix.e).toBeCloseTo(74.0961894323342) + expect(matrix.f).toBeCloseTo(-58.60254037844388) + }) + }) + + describe('flip()', function() { + describe('with x given', function() { + it('performs a flip over the horizontal axis with one argument', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip('x') + + expect(matrix.a).toBe(-1) + expect(matrix.d).toBe(1) + 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() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip('x', 150) + + expect(matrix.a).toBe(-1) + expect(matrix.d).toBe(1) + expect(matrix.e).toBe(304) + expect(matrix.f).toBe(3) + }) + }) + describe('with y given', function() { + it('performs a flip over the vertical axis with one argument', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip('y') + + expect(matrix.a).toBe(1) + expect(matrix.d).toBe(-1) + expect(matrix.e).toBe(4) + 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) + + expect(matrix.a).toBe(1) + expect(matrix.d).toBe(-1) + expect(matrix.e).toBe(4) + expect(matrix.f).toBe(203) + }) + }) + }) + + describe('skew()', function() { + it('performs a skew two arguments', function() { + var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3)//.skew(0, 0) + + expect(matrix.a).toBe(1) + expect(matrix.b).toBe(0) + expect(matrix.c).toBe(0) + expect(matrix.d).toBe(1) + expect(matrix.e).toBe(4) + expect(matrix.f).toBe(3) + }) + }) + + describe('native()', function() { + it('returns the node reference', function() { + expect(new SVG.Matrix().native() instanceof SVGMatrix).toBeTruthy() + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/memory.js b/node_modules/svgjs/spec/spec/memory.js new file mode 100644 index 0000000..c7bb942 --- /dev/null +++ b/node_modules/svgjs/spec/spec/memory.js @@ -0,0 +1,59 @@ +describe('Memory', function () { + var rect, circle + + beforeEach(function() { + rect = draw.rect(100,120) + circle = draw.circle(100) + }) + + afterEach(function() { + draw.clear() + }) + + describe('remember()', function() { + it('accepts an object with values', function() { + rect.remember({ bbox: rect.bbox() }) + rect.size(200,300) + expect(rect.remember('bbox').width).toBe(100) + }) + it('accepts key / value arguments', function() { + rect.remember('fill', rect.attr('fill')) + rect.fill('#f09') + expect(rect.remember('fill')).toBe('#000000') + }) + it('acts as a getter with one string argument', function() { + rect.remember('opacity', 0.85) + expect(rect.remember('opacity')).toBe(0.85) + }) + it('saves values to individual objects', function() { + rect.remember('opacity', 0.85) + circle.remember('opacity', 0.5) + expect(rect.remember('opacity')).toBe(0.85) + expect(circle.remember('opacity')).toBe(0.5) + }) + }) + + describe('forget()', function() { + it('deletes a given memory', function() { + rect.remember({ grass: 'is green', one: 1 }) + rect.forget('grass') + expect(rect.remember('grass')).toBe(undefined) + expect(rect.remember('one')).toBe(1) + }) + it('accepts multiple arguments as different memories', function() { + rect.remember({ grass: 'might be purple', two: 2, sea: true }) + rect.forget('grass', 'sea') + expect(rect.remember('grass')).toBe(undefined) + expect(rect.remember('sea')).toBe(undefined) + expect(rect.remember('two')).toBe(2) + }) + it('clears the whole memory without arguments', function() { + rect.remember({ grass: 'is never pink', three: 3, tree: true }) + rect.forget() + expect(rect.remember('grass')).toBe(undefined) + expect(rect.remember('tree')).toBe(undefined) + expect(rect.remember('three')).toBe(undefined) + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/number.js b/node_modules/svgjs/spec/spec/number.js new file mode 100644 index 0000000..de00481 --- /dev/null +++ b/node_modules/svgjs/spec/spec/number.js @@ -0,0 +1,216 @@ +describe('Number', function() { + var number + + beforeEach(function() { + number = new SVG.Number + }) + + describe('new', function() { + it('is zero', function() { + expect(number.value).toBe(0) + }) + it('has a blank unit', function() { + expect(number.unit).toBe('') + }) + it('accepts the unit as a second argument', function() { + number = new SVG.Number(30, '%') + expect(number.value).toBe(30) + expect(number.unit).toBe('%') + }) + it('parses a pixel value', function() { + number = new SVG.Number('20px') + expect(number.value).toBe(20) + expect(number.unit).toBe('px') + }) + it('parses a percent value', function() { + number = new SVG.Number('99%') + expect(number.value).toBe(0.99) + expect(number.unit).toBe('%') + }) + it('parses a seconds value', function() { + number = new SVG.Number('2s') + expect(number.value).toBe(2000) + expect(number.unit).toBe('s') + }) + it('parses a negative percent value', function() { + number = new SVG.Number('-89%') + expect(number.value).toBe(-0.89) + expect(number.unit).toBe('%') + }) + it('falls back to 0 if given value is NaN', function() { + number = new SVG.Number(NaN) + expect(number.value).toBe(0) + }) + it('falls back to maximum value if given number is positive infinite', function() { + number = new SVG.Number(1.7976931348623157E+10308) + expect(number.value).toBe(3.4e+38) + }) + it('falls back to minimum value if given number is negative infinite', function() { + number = new SVG.Number(-1.7976931348623157E+10308) + expect(number.value).toBe(-3.4e+38) + }) + }) + + describe('toString()', function() { + it('converts the number to a string', function() { + expect(number.toString()).toBe('0') + }) + it('appends the unit', function() { + number.value = 1.21 + number.unit = 'px' + expect(number.toString()).toBe('1.21px') + }) + it('converts percent values properly', function() { + number.value = 1.36 + number.unit = '%' + expect(number.toString()).toBe('136%') + }) + it('converts second values properly', function() { + number.value = 2500 + number.unit = 's' + expect(number.toString()).toBe('2.5s') + }) + }) + + describe('valueOf()', function() { + it('returns a numeric value for default units', function() { + expect(typeof number.valueOf()).toBe('number') + number = new SVG.Number('12') + expect(typeof number.valueOf()).toBe('number') + number = new SVG.Number(13) + expect(typeof number.valueOf()).toBe('number') + }) + it('returns a numeric value for pixel units', function() { + number = new SVG.Number('10px') + expect(typeof number.valueOf()).toBe('number') + }) + it('returns a numeric value for percent units', function() { + number = new SVG.Number('20%') + expect(typeof number.valueOf()).toBe('number') + }) + it('converts to a primitive when multiplying', function() { + number.value = 80 + expect(number * 4).toBe(320) + }) + }) + + describe('to()', function() { + beforeEach(function() { + number = number.plus(4) + }) + it('returns a new instance', function() { + expect(number.to('em')).not.toBe(number) + expect(number.to('em') instanceof SVG.Number).toBeTruthy() + }) + it('changes the unit value', function() { + number = number.to('%') + expect(number.unit).toBe('%') + }) + it('changes the output value', function() { + var oldNumber = number.valueOf() + number = number.to('%') + expect(number.toString()).toBe('400%') + }) + }) + + describe('plus()', function() { + it('returns a new instance', function() { + expect(number.plus(4.5)).not.toBe(number) + expect(number.plus(4.5) instanceof SVG.Number).toBeTruthy() + }) + it('adds a given number', function() { + expect(number.plus(3.5).valueOf()).toBe(3.5) + }) + it('adds a given percentage value', function() { + expect(number.plus('225%').valueOf()).toBe(2.25) + }) + it('adds a given pixel value', function() { + expect(number.plus('83px').valueOf()).toBe(83) + }) + }) + + describe('minus()', function() { + it('subtracts a given number', function() { + expect(number.minus(3.7).valueOf()).toBe(-3.7) + }) + it('subtracts a given percentage value', function() { + expect(number.minus('223%').valueOf()).toBe(-2.23) + }) + it('subtracts a given pixel value', function() { + expect(number.minus('85px').valueOf()).toBe(-85) + }) + }) + + describe('times()', function() { + beforeEach(function() { + number = number.plus(4) + }) + it('multiplies with a given number', function() { + expect(number.times(3).valueOf()).toBe(12) + }) + it('multiplies with a given percentage value', function() { + expect(number.times('110%').valueOf()).toBe(4.4) + }) + it('multiplies with a given pixel value', function() { + expect(number.times('85px').valueOf()).toBe(340) + }) + }) + + describe('divide()', function() { + beforeEach(function() { + number = number.plus(90) + }) + it('divides by a given number', function() { + expect(number.divide(3).valueOf()).toBe(30) + }) + it('divides by a given percentage value', function() { + expect(number.divide('3000%').valueOf()).toBe(3) + }) + it('divides by a given pixel value', function() { + expect(number.divide('45px').valueOf()).toBe(2) + }) + }) + + describe('morph()', function() { + it('returns itself', function() { + expect(number.morph(new SVG.Number)).toBe(number) + }) + it('prepares the color for morphing', function() { + var destination = new SVG.Number + number.morph(destination) + expect(number.destination).toEqual(destination) + }) + }) + + describe('at()', function() { + it('returns a new instance', function() { + var destination = new SVG.Number(200) + var morphed = number.morph(destination).at(0.4) + expect(morphed).not.toBe(number) + expect(morphed).not.toBe(destination) + }) + it('morphes number to a given position', function() { + var destination = new SVG.Number(200) + var morphed = number.morph(destination).at(0.4) + expect(morphed.valueOf()).toBe(80) + }) + it('morphes number to a given percentage position', function() { + var destination = new SVG.Number('100%') + var morphed = number.morph(destination).at(0.72) + expect(morphed.toString()).toBe('72%') + }) + }) + +}) + + + + + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/path.js b/node_modules/svgjs/spec/spec/path.js new file mode 100644 index 0000000..b333002 --- /dev/null +++ b/node_modules/svgjs/spec/spec/path.js @@ -0,0 +1,225 @@ +describe('Path', function() { + var path + + beforeEach(function() { + path = draw.path(svgPath) + }) + + afterEach(function() { + draw.clear() + }) + + describe('array()', function() { + it('returns an instance of SVG.PathArray', function() { + expect(path.array() instanceof SVG.PathArray).toBeTruthy() + }) + it('returns the value stored in the private variable _array', function() { + expect(path.array()).toBe(path._array) + }) + }) + + describe('x()', function() { + it('returns the value of x without an argument', function() { + expect(path.x()).toBe(0) + }) + it('sets the value of x with the first argument', function() { + path.x(123) + var box = path.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(path.y()).toBe(0) + }) + it('sets the value of y with the first argument', function() { + path.y(345) + var box = path.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + expect(path.cx()).toBe(50) + }) + it('sets the value of cx with the first argument', function() { + path.cx(123) + var box = path.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + expect(path.cy()).toBe(50) + }) + it('sets the value of cy with the first argument', function() { + path.cy(345) + var box = path.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + path.move(123,456) + var box = path.bbox() + expect(box.x).toBe(123) + expect(box.y).toBe(456) + }) + it('sets the x and y position when scaled to half its size', function() { + path.scale(0.5, 0, 0).move(123,456) + var box = path.bbox() + expect(box.x).toBe(123) + expect(box.y).toBe(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + path.move(50,60) + path.dx(100) + var box = path.bbox() + expect(box.x).toBe(150) + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + path.move(50, 60) + path.dy(120) + var box = path.bbox() + expect(box.y).toBe(180) + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + path.move(50,60) + path.dmove(80, 25) + var box = path.bbox() + expect(box.x).toBe(130) + expect(box.y).toBe(85) + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + path.center(321,567) + var box = path.bbox() + expect(box.x).toBe(271) + expect(box.y).toBe(517) + }) + }) + + describe('width()', function() { + it('sets the width of the element', function() { + path.width(234) + var box = path.bbox() + expect(box.width).toBeCloseTo(234) + }) + it('gets the width of the element aithout an agrument', function() { + path.width(456) + expect(path.width()).toBeCloseTo(456) + }) + }) + + describe('height()', function() { + it('sets the height of the element', function() { + path.height(654) + var box = path.bbox() + expect(box.height).toBeCloseTo(654) + }) + it('gets the height of the element aithout an agrument', function() { + path.height(321) + expect(path.height()).toBeCloseTo(321) + }) + }) + + describe('size()', function() { + it('defines the width and height of the element', function() { + path.size(987,654) + var box = path.bbox() + expect(box.width).toBeCloseTo(987) + expect(box.height).toBeCloseTo(654) + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = path.bbox() + path.size(500) + expect(path.width()).toBe(500) + expect(path.width() / path.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = path.bbox() + path.size(null, 525) + expect(path.height()).toBe(525) + expect(path.width() / path.height()).toBe(box.width / box.height) + }) + }) + + describe('scale()', function() { + it('should scale the element universally with one argument', function() { + var box1 = path.tbox() + , box2 = path.scale(2).tbox() + + expect(box1.width * 2).toBe(box2.width) + expect(box1.height * 2).toBe(box2.height) + }) + it('should scale the element over individual x and y axes with two arguments', function() { + var box1 = path.tbox() + , box2 = path.scale(2, 3.5).tbox() + + expect(box1.width * 2).toBe(box2.width) + expect(box1.height * 3.5).toBe(box2.height) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + path.transform({ x: 12, y: 12 }) + expect(path.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + + describe('plot()', function() { + it('falls back to a single point without an argument', function() { + path = draw.path() + expect(path.node.getAttribute('d')).toBe('M0 0 ') + }) + }) + + describe('toString()', function() { + it('renders path array correctly to string', function() { + path = path.plot('M 50 60 A 60 60 0 0 0 50 -60 H 100 V 100 L 20 30 C 10 20 30 40 50 60 ') + expect(path.node.getAttribute('d')).toBe('M50 60A60 60 0 0 0 50 -60H100V100L20 30C10 20 30 40 50 60 ') + }) + it('renders path array correctly to string', function() { + path = path.plot('M 50 60 A 60 60 1 1 0 50 -60 H 100 V 100 L 20 30 C 10 20 30 40 50 60 ') + expect(path.node.getAttribute('d')).toBe('M50 60A60 60 1 1 0 50 -60H100V100L20 30C10 20 30 40 50 60 ') + }) + }) + + describe('length()', function() { + it('gets the total length of the path', function() { + expect(path.length()).toBe(path.node.getTotalLength()) + }) + }) + + describe('pointAt()', function() { + it('gets a point at given length', function() { + expect(path.pointAt(100)).toEqual(path.node.getPointAtLength(100)) + }) + }) + + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/pattern.js b/node_modules/svgjs/spec/spec/pattern.js new file mode 100644 index 0000000..4abdadc --- /dev/null +++ b/node_modules/svgjs/spec/spec/pattern.js @@ -0,0 +1,63 @@ +describe('Pattern', function() { + var rect, pattern + + beforeEach(function() { + rect = draw.rect(100,100) + pattern = draw.pattern(20, 30, function(add) { + add.rect(10,10).move(10,10) + add.circle(30) + }) + }) + + afterEach(function() { + rect.remove() + pattern.remove() + }) + + it('is an instance of SVG.Pattern', function() { + expect(pattern instanceof SVG.Pattern).toBe(true) + }) + + it('allows creation of a new gradient without block', function() { + pattern = draw.pattern(10,30) + expect(pattern.children().length).toBe(0) + }) + + describe('fill()', function() { + it('returns the id of the pattern wrapped in url()', function() { + expect(pattern.fill()).toBe('url(#' + pattern.attr('id') + ')') + }) + }) + + describe('toString()', function() { + it('returns the id of the pattern wrapped in url()', function() { + expect(pattern + '').toBe('url(#' + pattern.attr('id') + ')') + }) + it('is called when instance is passed as an attribute value', function() { + rect.attr('fill', pattern) + expect(rect.attr('fill')).toBe('url(#' + pattern.attr('id') + ')') + }) + it('is called when instance is passed in a fill() method', function() { + rect.fill(pattern) + expect(rect.attr('fill')).toBe('url(#' + pattern.attr('id') + ')') + }) + }) + + describe('update()', function() { + + it('removes all existing children first', function() { + pattern = draw.pattern(30, 30, function(add) { + add.rect(10,10).move(10,10) + add.circle(30) + }) + expect(pattern.children().length).toBe(2) + pattern.update(function(add) { + add.rect(10,10).move(10,10) + add.circle(30) + }) + expect(pattern.children().length).toBe(2) + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/point.js b/node_modules/svgjs/spec/spec/point.js new file mode 100644 index 0000000..ce28781 --- /dev/null +++ b/node_modules/svgjs/spec/spec/point.js @@ -0,0 +1,120 @@ +describe('Point', function() { + var point + + describe('initialization', function() { + + describe('without a source', function() { + + point(function() { + matrix = new SVG.Point + }) + + it('creates a new point with default values', function() { + expect(point.x).toBe(0) + expect(point.y).toBe(0) + }) + + }) + + describe('with x and y given', function() { + it('creates a point with given values', function() { + var point = new SVG.Point(2,4) + + expect(point.x).toBe(2) + expect(point.y).toBe(4) + }) + }) + + describe('with array given', function() { + it('creates a point from array', function() { + var point = new SVG.Point([2,4]) + + expect(point.x).toBe(2) + expect(point.y).toBe(4) + }) + }) + + describe('with object given', function() { + it('creates a point from object', function() { + var point = new SVG.Point({x:2,y:4}) + + expect(point.x).toBe(2) + expect(point.y).toBe(4) + }) + }) + + describe('with SVG.Point given', function() { + it('creates a point from SVG.Point', function() { + var point = new SVG.Point(new SVG.Point(2,4)) + + expect(point.x).toBe(2) + expect(point.y).toBe(4) + }) + }) + + describe('with native SVGPoint given', function() { + it('creates a point from native SVGPoint', function() { + var point = new SVG.Point(new SVG.Point(2,4).native()) + + expect(point.x).toBe(2) + expect(point.y).toBe(4) + }) + }) + + }) + + describe('clone()', function() { + it('returns cloned point', function() { + var point1 = new SVG.Point(1,1) + , point2 = new SVG.Point(point1) + + expect(point1).toEqual(point2) + expect(point1).not.toBe(point2) + }) + }) + + describe('morph()', function() { + it('stores a given point for morphing', function() { + var point1 = new SVG.Point(1,1) + , point2 = new SVG.Matrix(2,2) + + point1.morph(point2) + + expect(point1.destination).toEqual(point2) + }) + it('stores a clone, not the given matrix itself', function() { + var point1 = new SVG.Point(1,1) + , point2 = new SVG.Matrix(2,2) + + point1.morph(point2) + + expect(point1.destination).not.toBe(point2) + }) + }) + + describe('at()', function() { + it('returns a morphed point at a given position', function() { + var point1 = new SVG.Point(1,1) + , point2 = new SVG.Point(2,2) + , matrix3 = matrix1.morph(matrix2).at(0.5) + + expect(matrix3).toEqual(new SVG.Point(1.5, 1.5)) + }) + }) + + describe('transform()', function() { + it('returns a point transformed with given matrix', function() { + var point = new SVG.Point(1,5) + , matrix = new SVG.Matrix(0,0,1,0,0,1) + + expect(point.transform(matrox)).toEqual(new SVG.Point(5,1)) + }) + } + + describe('native()', function() { + it('returns native SVGPoint', function() { + expect(new SVG.Point().native() instanceof SVGPoint).toBeTruthy() + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/polygon.js b/node_modules/svgjs/spec/spec/polygon.js new file mode 100644 index 0000000..b6dc40d --- /dev/null +++ b/node_modules/svgjs/spec/spec/polygon.js @@ -0,0 +1,188 @@ +describe('Polygon', function() { + var polygon + + beforeEach(function() { + polygon = draw.polygon('0,0 100,0 100,100 0,100') + }) + + afterEach(function() { + draw.clear() + }) + + describe('array()', function() { + it('returns an instance of SVG.PointArray', function() { + expect(polygon.array() instanceof SVG.PointArray).toBeTruthy() + }) + it('returns the value stored in the private variable _array', function() { + expect(polygon.array()).toBe(polygon._array) + }) + }) + + describe('x()', function() { + it('returns the value of x without an argument', function() { + expect(polygon.x()).toBe(0) + }) + it('sets the value of x with the first argument', function() { + polygon.x(123) + var box = polygon.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(polygon.y()).toBe(0) + }) + it('sets the value of y with the first argument', function() { + polygon.y(345) + var box = polygon.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + expect(polygon.cx()).toBe(50) + }) + it('sets the value of cx with the first argument', function() { + polygon.cx(123) + var box = polygon.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + expect(polygon.cy()).toBe(50) + }) + it('sets the value of cy with the first argument', function() { + polygon.cy(345) + var box = polygon.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + polygon.move(123,456) + var box = polygon.bbox() + expect(box.x).toBe(123) + expect(box.y).toBe(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + polygon.move(50,60) + polygon.dx(100) + var box = polygon.bbox() + expect(box.x).toBe(150) + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + polygon.move(50, 60) + polygon.dy(120) + var box = polygon.bbox() + expect(box.y).toBe(180) + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + polygon.move(50,60) + polygon.dmove(80, 25) + var box = polygon.bbox() + expect(box.x).toBe(130) + expect(box.y).toBe(85) + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + polygon.center(321,567) + var box = polygon.bbox() + expect(box.x).toBe(271) + expect(box.y).toBe(517) + }) + }) + + describe('width()', function() { + it('sets the width and height of the element', function() { + polygon.width(987) + var box = polygon.bbox() + expect(box.width).toBeCloseTo(987) + }) + it('gets the width and height of the element without an argument', function() { + polygon.width(789) + expect(polygon.width()).toBeCloseTo(789) + }) + }) + + describe('height()', function() { + it('sets the height and height of the element', function() { + polygon.height(987) + var box = polygon.bbox() + expect(box.height).toBeCloseTo(987) + }) + it('gets the height and height of the element without an argument', function() { + polygon.height(789) + expect(polygon.height()).toBeCloseTo(789) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + polygon.size(987,654) + var box = polygon.bbox() + expect(box.width).toBeCloseTo(987) + expect(box.height).toBeCloseTo(654) + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = polygon.bbox() + polygon.size(500) + expect(polygon.width()).toBe(500) + expect(polygon.width() / polygon.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = polygon.bbox() + polygon.size(null, 525) + expect(polygon.height()).toBe(525) + expect(polygon.width() / polygon.height()).toBe(box.width / box.height) + }) + }) + + describe('scale()', function() { + it('should scale the element universally with one argument', function() { + var box1 = polygon.tbox() + , box2 = polygon.scale(2).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 2) + }) + it('should scale the element over individual x and y axes with two arguments', function() { + var box1 = polygon.tbox() + , box2 = polygon.scale(2, 3.5).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 3.5) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + polygon.transform({ x: 12, y: 12 }) + expect(polygon.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/polyline.js b/node_modules/svgjs/spec/spec/polyline.js new file mode 100644 index 0000000..eeb761f --- /dev/null +++ b/node_modules/svgjs/spec/spec/polyline.js @@ -0,0 +1,188 @@ +describe('Polyline', function() { + var polyline + + beforeEach(function() { + polyline = draw.polyline('0,0 100,0 100,100 0,100') + }) + + afterEach(function() { + draw.clear() + }) + + describe('array()', function() { + it('returns an instance of SVG.PointArray', function() { + expect(polyline.array() instanceof SVG.PointArray).toBeTruthy() + }) + it('returns the value stored in the private variable _array', function() { + expect(polyline.array()).toBe(polyline._array) + }) + }) + + describe('x()', function() { + it('returns the value of x without an argument', function() { + expect(polyline.x()).toBe(0) + }) + it('sets the value of x with the first argument', function() { + polyline.x(123) + var box = polyline.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(polyline.y()).toBe(0) + }) + it('sets the value of y with the first argument', function() { + polyline.y(345) + var box = polyline.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + expect(polyline.cx()).toBe(50) + }) + it('sets the value of cx with the first argument', function() { + polyline.cx(123) + var box = polyline.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + expect(polyline.cy()).toBe(50) + }) + it('sets the value of cy with the first argument', function() { + polyline.cy(345) + var box = polyline.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + polyline.move(123,456) + var box = polyline.bbox() + expect(box.x).toBe(123) + expect(box.y).toBe(456) + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + polyline.move(50,60) + polyline.dx(100) + var box = polyline.bbox() + expect(box.x).toBe(150) + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + polyline.move(50, 60) + polyline.dy(120) + var box = polyline.bbox() + expect(box.y).toBe(180) + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + polyline.move(50,60) + polyline.dmove(80, 25) + var box = polyline.bbox() + expect(box.x).toBe(130) + expect(box.y).toBe(85) + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + polyline.center(321,567) + var box = polyline.bbox() + expect(box.x).toBe(271) + expect(box.y).toBe(517) + }) + }) + + describe('width()', function() { + it('sets the width and height of the element', function() { + polyline.width(987) + var box = polyline.bbox() + expect(box.width).toBeCloseTo(987, 1) + }) + it('gets the width and height of the element without an argument', function() { + polyline.width(789) + expect(polyline.width()).toBeCloseTo(789) + }) + }) + + describe('height()', function() { + it('sets the height and height of the element', function() { + polyline.height(987) + var box = polyline.bbox() + expect(box.height).toBeCloseTo(987) + }) + it('gets the height and height of the element without an argument', function() { + polyline.height(789) + expect(polyline.height()).toBeCloseTo(789) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + polyline.size(987,654) + var box = polyline.bbox() + expect(box.width).toBeCloseTo(987) + expect(box.height).toBeCloseTo(654) + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = polyline.bbox() + polyline.size(500) + expect(polyline.width()).toBe(500) + expect(polyline.width() / polyline.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = polyline.bbox() + polyline.size(null, 525) + expect(polyline.height()).toBe(525) + expect(polyline.width() / polyline.height()).toBe(box.width / box.height) + }) + }) + + describe('scale()', function() { + it('should scale the element universally with one argument', function() { + var box1 = polyline.tbox() + , box2 = polyline.scale(2).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 2) + }) + it('should scale the element over individual x and y axes with two arguments', function() { + var box1 = polyline.tbox() + , box2 = polyline.scale(2, 3.5).tbox() + + expect(box2.width).toBe(box1.width * 2) + expect(box2.height).toBe(box1.height * 3.5) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + polyline.transform({ x: 12, y: 12 }) + expect(polyline.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/rect.js b/node_modules/svgjs/spec/spec/rect.js new file mode 100644 index 0000000..cd82d39 --- /dev/null +++ b/node_modules/svgjs/spec/spec/rect.js @@ -0,0 +1,181 @@ +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) + }) + it('should set the value of x with the first argument', function() { + rect.x(123) + var box = rect.bbox() + expect(box.x).toBe(123) + }) + }) + + describe('y()', function() { + it('should return the value of y without an argument', function() { + expect(rect.y()).toBe(0) + }) + it('should set the value of y with the first argument', function() { + rect.y(345) + var box = rect.bbox() + expect(box.y).toBe(345) + }) + }) + + describe('cx()', function() { + it('should return the value of cx without an argument', function() { + expect(rect.cx()).toBe(110) + }) + it('should set the value of cx with the first argument', function() { + rect.cx(123) + var box = rect.bbox() + expect(box.cx).toBe(123) + }) + }) + + describe('cy()', function() { + it('should return the value of cy without an argument', function() { + expect(rect.cy()).toBe(50) + }) + it('should set the value of cy with the first argument', function() { + rect.cy(345) + var box = rect.bbox() + expect(box.cy).toBe(345) + }) + }) + + describe('radius()', function() { + it('should set the rx and ry', function() { + rect.radius(10,20) + expect(rect.node.getAttribute('rx')).toBe('10') + expect(rect.node.getAttribute('ry')).toBe('20') + }) + it('should set the rx and ry if only rx given', function() { + rect.radius(30) + expect(rect.node.getAttribute('rx')).toBe('30') + expect(rect.node.getAttribute('ry')).toBe('30') + }) + }) + + describe('move()', function() { + it('should set the x and y position', function() { + rect.move(123,456) + expect(rect.node.getAttribute('x')).toBe('123') + expect(rect.node.getAttribute('y')).toBe('456') + }) + }) + + describe('dx()', function() { + it('moves the x positon of the element relative to the current position', function() { + rect.move(50,60) + rect.dx(100) + expect(rect.node.getAttribute('x')).toBe('150') + }) + }) + + describe('dy()', function() { + it('moves the y positon of the element relative to the current position', function() { + rect.move(50,60) + rect.dy(120) + expect(rect.node.getAttribute('y')).toBe('180') + }) + }) + + describe('dmove()', function() { + it('moves the x and y positon of the element relative to the current position', function() { + rect.move(50,60) + rect.dmove(80, 25) + expect(rect.node.getAttribute('x')).toBe('130') + expect(rect.node.getAttribute('y')).toBe('85') + }) + }) + + describe('center()', function() { + it('should set the cx and cy position', function() { + rect.center(321,567) + var box = rect.bbox() + expect(box.cx).toBe(321) + expect(box.cy).toBe(567) + }) + }) + + describe('width()', function() { + it('sets the width of the element', function() { + rect.width(789) + expect(rect.node.getAttribute('width')).toBe('789') + }) + it('gets the width of the element if the argument is null', function() { + expect(rect.width().toString()).toBe(rect.node.getAttribute('width')) + }) + }) + + describe('height()', function() { + it('sets the height of the element', function() { + rect.height(1236) + expect(rect.node.getAttribute('height')).toBe('1236') + }) + it('gets the height of the element if the argument is null', function() { + expect(rect.height().toString()).toBe(rect.node.getAttribute('height')) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + rect.size(987,654) + expect(rect.node.getAttribute('width')).toBe('987') + expect(rect.node.getAttribute('height')).toBe('654') + }) + it('defines the width and height proportionally with only the width value given', function() { + var box = rect.bbox() + rect.size(500) + expect(rect.width()).toBe(500) + expect(rect.width() / rect.height()).toBe(box.width / box.height) + }) + it('defines the width and height proportionally with only the height value given', function() { + var box = rect.bbox() + rect.size(null, 525) + expect(rect.height()).toBe(525) + 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).tbox() + + 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).tbox() + + expect(box.width).toBe(rect.attr('width') * 2) + expect(box.height).toBe(rect.attr('height') * 3.5) + }) + }) + + describe('translate()', function() { + it('should set the translation of an element', function() { + rect.transform({ x: 12, y: 12 }) + expect(rect.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/regex.js b/node_modules/svgjs/spec/spec/regex.js new file mode 100644 index 0000000..67b03ef --- /dev/null +++ b/node_modules/svgjs/spec/spec/regex.js @@ -0,0 +1,67 @@ +describe('Regex', function() { + + describe('matchers', function() { + describe('unit', function() { + var match + + it('is true with a positive unit value', function() { + match = ('10%').match(SVG.regex.unit) + expect(match[1]).toBe('10') + expect(match[2]).toBe('%') + }) + it('is true with a negative unit value', function() { + match = ('-11%').match(SVG.regex.unit) + expect(match[1]).toBe('-11') + expect(match[2]).toBe('%') + }) + it('is false with a positive unit value', function() { + match = ('NotAUnit').match(SVG.regex.unit) + expect(match).toBeNull() + }) + }) + }) + + describe('testers', function() { + + describe('isHex', function() { + it('is true with a three based hex', function() { + expect(SVG.regex.isHex.test('#f09')).toBeTruthy() + }) + it('is true with a six based hex', function() { + expect(SVG.regex.isHex.test('#fe0198')).toBeTruthy() + }) + it('is false with a faulty hex', function() { + expect(SVG.regex.isHex.test('###')).toBeFalsy() + expect(SVG.regex.isHex.test('#0')).toBeFalsy() + expect(SVG.regex.isHex.test('f06')).toBeFalsy() + }) + }) + + describe('isRgb', function() { + it('is true with an rgb value', function() { + expect(SVG.regex.isRgb.test('rgb(255,66,100)')).toBeTruthy() + }) + it('is false with a non-rgb value', function() { + expect(SVG.regex.isRgb.test('hsb(255, 100, 100)')).toBeFalsy() + }) + }) + + describe('isNumber', function() { + + it('is true with a number', function() { + ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"].forEach(function(s) { + expect(SVG.regex.isNumber.test(s)).toBeTruthy() + }) + }) + + it('is false with a faulty number', function() { + ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(function(s) { + expect(SVG.regex.isNumber.test(s)).toBeFalsy() + }) + }) + + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/selector.js b/node_modules/svgjs/spec/spec/selector.js new file mode 100644 index 0000000..b28213d --- /dev/null +++ b/node_modules/svgjs/spec/spec/selector.js @@ -0,0 +1,57 @@ +describe('Selector', function() { + + describe('get()', function() { + it('gets an element\'s instance by id', function() { + var rect = draw.rect(111, 333) + + expect(SVG.get(rect.attr('id'))).toBe(rect) + }) + it('makes all the element\'s methods available', function() { + var element = draw.group() + , got = SVG.get(element.attr('id')) + + expect(got.attr()).toEqual(element.attr()) + }) + it('gets a referenced element by attribute value', function() { + var rect = draw.defs().rect(100, 100) + , use = draw.use(rect) + , mark = draw.marker(10, 10) + , path = draw.path(svgPath).marker('end', mark) + + expect(SVG.get(use.attr('href'))).toBe(rect) + expect(SVG.get(path.attr('marker-end'))).toBe(mark) + }) + }) + + describe('select()', function() { + var e1, e2, e3, e4 ,e5 + + beforeEach(function() { + e1 = draw.rect(100, 100).addClass('selectable-element') + e2 = draw.rect(100, 100).addClass('unselectable-element') + e3 = draw.rect(100, 100).addClass('selectable-element') + e4 = draw.rect(100, 100).addClass('unselectable-element') + e5 = draw.rect(100, 100).addClass('selectable-element') + }) + it('gets all elements with a given class name', function() { + expect(SVG.select('rect.selectable-element').valueOf()).toEqual([e1, e3, e5]) + }) + it('returns an instance of SVG.Set', function() { + expect(SVG.select('rect.selectable-element') instanceof SVG.Set).toBe(true) + }) + }) + + describe('Parent#select()', function() { + it('gets all elements with a given class name inside a given element', function() { + var group = draw.group() + , e1 = draw.rect(100, 100).addClass('selectable-element') + , e2 = draw.rect(100, 100).addClass('unselectable-element') + , e3 = group.rect(100, 100).addClass('selectable-element') + , e4 = draw.rect(100, 100).addClass('unselectable-element') + , e5 = group.rect(100, 100).addClass('selectable-element') + + expect(group.select('rect.selectable-element').valueOf()).toEqual([e3, e5]) + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/set.js b/node_modules/svgjs/spec/spec/set.js new file mode 100644 index 0000000..a2abfb5 --- /dev/null +++ b/node_modules/svgjs/spec/spec/set.js @@ -0,0 +1,215 @@ +describe('Set', function() { + var set, e1, e2, e3, e4, e5 + + beforeEach(function() { + draw.attr('viewBox', null) + set = draw.set() + e1 = draw.rect(100,100).attr('id', 'e1').move(200,250) + e2 = draw.ellipse(100,100).attr('id', 'e2') + e3 = draw.line(0,0,100,100).attr('id', 'e3') + e4 = draw.circle(50).attr('id', 'e4') + e5 = draw.polyline('0,0 10,20 30,50 80,100').attr('id', 'e5') + }) + + afterEach(function() { + draw.clear() + }) + + it('creates the set method on SVG.Container instances', function() { + expect(draw.set() instanceof SVG.Set).toBeTruthy() + }) + + it('creates a set with initial value', function() { + var members = [1, 2, 4] + + expect(draw.set(members).valueOf()).toBe(members) + }) + + describe('add()', function() { + it('returns the set instance', function() { + expect(set.add(e1)).toBe(set) + }) + it('stores given element', function() { + set.add(e1).add(e2).add(e3) + expect(set.valueOf()).toEqual([e1,e2,e3]) + expect(set.members.length).toBe(3) + }) + it('accepts multiple elements at once', function() { + set.add(e1, e2, e3, e4, e5) + expect(set.valueOf()).toEqual([e1, e2, e3, e4, e5]) + expect(set.members.length).toBe(5) + }) + }) + + describe('remove()', function() { + it('returns the set instance', function() { + set.add(e1) + expect(set.remove(e1)).toBe(set) + }) + it('removes given element', function() { + set.add(e1).add(e2).add(e3).remove(e2) + expect(set.valueOf()).toEqual([e1,e3]) + expect(set.members.length).toBe(2) + }) + }) + + describe('each()', function() { + it('returns the set instance', function() { + expect(set.each(function(){})).toBe(set) + }) + it('iterates over all members of the set', function() { + var ids = [] + set.add(e1).add(e2).add(e3) + + set.each(function() { + ids.push(this.attr('id')) + }) + + expect(ids.length).toBe(3) + expect(ids).toEqual(['e1','e2','e3']) + }) + }) + + describe('clear()', function() { + it('returns the set instance', function() { + expect(set.clear()).toBe(set) + }) + it('removes all members from set', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5).clear() + expect(set.members.length).toBe(0) + }) + }) + + describe('get()', function() { + it('returns member at given index', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + expect(set.get(2)).toBe(e3) + }) + }) + + describe('first()', function() { + it('returns first member', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + expect(set.first()).toBe(e1) + }) + }) + + describe('last()', function() { + it('returns last member', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + expect(set.last()).toBe(e5) + }) + }) + + describe('has()', function() { + it('checks if a given element is present in set', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + expect(set.has(e4)).toBeTruthy() + }) + }) + + describe('length()', function() { + it('gets the length of the set', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + expect(set.length()).toBe(5) + }) + }) + + describe('index()', function() { + it('returns the index of a given element within the set', function() { + set.add(e1).add(e2).add(e3).add(e5) + expect(set.index(e1)).toBe(0) + expect(set.index(e2)).toBe(1) + expect(set.index(e3)).toBe(2) + expect(set.index(e4)).toBe(-1) + expect(set.index(e5)).toBe(3) + }) + }) + + describe('valueOf()', function() { + it('returns the members array', function() { + set.add(e1) + expect(set.valueOf()).toBe(set.members) + }) + }) + + describe('bbox()', function() { + it('returns the bounding box of all elements', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + + var box = set.bbox() + + expect(box.x).toBeCloseTo(0) + expect(box.y).toBeCloseTo(0) + expect(box.width).toBeCloseTo(300) + expect(box.height).toBeCloseTo(350) + }) + it('returns an instance of SVG.BBox', function() { + set.add(e1).add(e2).add(e3).add(e4).add(e5) + + expect(set.bbox() instanceof SVG.BBox).toBeTruthy() + }) + it('returns an empty bounding box wiht no members', function() { + var box = set.bbox() + + expect(box.x).toBe(0) + expect(box.y).toBe(0) + expect(box.width).toBe(0) + expect(box.height).toBe(0) + }) + }) + + describe('method alias', function() { + + describe('attr()', function() { + it('is applied to every member of the set', function() { + var fills = [] + + set.add(e1).add(e2).add(e3).add(e4).add(e5).attr('fill', '#ff0099') + set.each(function() { + fills.push(this.attr('fill')) + }) + + expect(fills).toEqual(['#ff0099','#ff0099','#ff0099','#ff0099','#ff0099']) + }) + }) + + }) + + describe('method inheritance', function() { + + beforeEach(function() { + SVG.extend(SVG.Element, { + orange: function() { + this.fill('#ff6600') + } + }) + }) + + it('inherits newly added element methods after initialisation', function() { + expect(typeof set.orange).toBe('function') + }) + + it('applies newly inherited methods properly to members', function() { + var fills = [] + + set.add(e1).add(e2).add(e3).add(e4).add(e5).orange() + set.each(function() { + fills.push(this.attr('fill')) + }) + + expect(fills).toEqual(['#ff6600','#ff6600','#ff6600','#ff6600','#ff6600']) + }) + + }) + +}) + + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/svg.js b/node_modules/svgjs/spec/spec/svg.js new file mode 100644 index 0000000..cc9f7be --- /dev/null +++ b/node_modules/svgjs/spec/spec/svg.js @@ -0,0 +1,82 @@ +describe('SVG', function() { + + describe('()', function() { + var drawing, wrapper + + beforeEach(function() { + wrapper = document.createElement('div') + document.getElementsByTagName('body')[0].appendChild(wrapper) + drawing = SVG(wrapper) + }) + + afterEach(function() { + wrapper.parentNode.removeChild(wrapper) + }) + + it('creates a new svg drawing', function() { + expect(drawing.type).toBe('svg') + }) + it('creates an instance of SVG.Doc', function() { + expect(drawing instanceof SVG.Doc).toBe(true) + }) + }) + + describe('create()', function() { + it('creates an element with given node name and return it', function() { + var element = SVG.create('rect') + + expect(element.nodeName).toBe('rect') + }) + it('increases the global id sequence', function() { + var did = SVG.did + , element = SVG.create('rect') + + expect(did + 1).toBe(SVG.did) + }) + it('adds a unique id containing the node name', function() { + var did = SVG.did + , element = SVG.create('rect') + + expect(element.getAttribute('id')).toBe('SvgjsRect' + did) + }) + }) + + describe('extend()', function() { + it('adds all functions in the given object to the target object', function() { + SVG.extend(SVG.Rect, { + soft: function() { + return this.opacity(0.2) + } + }) + + expect(typeof SVG.Rect.prototype.soft).toBe('function') + expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.2) + }) + it('accepts and extend multiple modules at once', function() { + SVG.extend(SVG.Rect, SVG.Ellipse, SVG.Path, { + soft: function() { + return this.opacity(0.5) + } + }) + + expect(typeof SVG.Rect.prototype.soft).toBe('function') + expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.5) + expect(typeof SVG.Ellipse.prototype.soft).toBe('function') + expect(draw.ellipse(100,100).soft().attr('opacity')).toBe(0.5) + expect(typeof SVG.Path.prototype.soft).toBe('function') + expect(draw.path().soft().attr('opacity')).toBe(0.5) + }) + it('ignones non existant objects', function() { + SVG.extend(SVG.Rect, SVG.Bogus, { + soft: function() { + return this.opacity(0.3) + } + }) + + expect(typeof SVG.Rect.prototype.soft).toBe('function') + expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.3) + expect(typeof SVG.Bogus).toBe('undefined') + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/text.js b/node_modules/svgjs/spec/spec/text.js new file mode 100644 index 0000000..b60a97d --- /dev/null +++ b/node_modules/svgjs/spec/spec/text.js @@ -0,0 +1,268 @@ +// IMPORTANT!!! +// The native getBBox() on text elements isn't always accurate in the decimals. +// Therefore sometimes some rounding is used to make test work as expected. + +describe('Text', function() { + var text + + beforeEach(function() { + text = draw.text(loremIpsum).size(5) + }) + + afterEach(function() { + draw.clear() + }) + + describe('x()', function() { + it('returns the value of x without an argument', function() { + expect(text.x()).toBe(0) + }) + it('sets the value of x with the first argument', function() { + text.x(123) + var box = text.bbox() + expect(box.x).toBeCloseTo(123) + }) + it('sets the value of x based on the anchor with the first argument', function() { + text.x(123, true) + var box = text.bbox() + expect(box.x).toBeCloseTo(123) + }) + }) + + describe('y()', function() { + it('returns the value of y without an argument', function() { + expect(text.y(0).y()).toBe(0) + }) + it('returns the value of y when y is a percentual value', function() { + expect(text.y('45%').y()).toBe('45%') + }) + it('sets the value of y with the first argument', function() { + text.y(345) + var box = text.bbox() + expect(box.y).toBe(345) + }) + it('sets the value of y with a percent value', function() { + text.y('40%') + expect(text.node.getAttribute('y')).toBe('40%') + }) + }) + + describe('cx()', function() { + it('returns the value of cx without an argument', function() { + var box = text.bbox() + expect(text.cx()).toBeCloseTo(box.width / 2) + }) + it('sets the value of cx with the first argument', function() { + text.cx(123) + var box = text.bbox() + expect(box.cx).toBeCloseTo(123) + }) + it('sets the value of cx based on the anchor with the first argument', function() { + text.cx(123, true) + var box = text.bbox() + expect(box.cx).toBeCloseTo(123) + }) + }) + + describe('cy()', function() { + it('returns the value of cy without an argument', function() { + var box = text.bbox() + expect(text.cy()).toBe(box.cy) + }) + it('sets the value of cy with the first argument', function() { + text.cy(345) + var box = text.bbox() + expect(Math.round(box.cy * 10) / 10).toBe(345) + }) + }) + + describe('move()', function() { + it('sets the x and y position', function() { + text.move(123,456) + var box = text.bbox() + expect(box.x).toBeCloseTo(123) + expect(box.y).toBeCloseTo(456) + }) + }) + + describe('center()', function() { + it('sets the cx and cy position', function() { + text.center(321, 567) + var box = text.bbox() + expect(box.cx).toBeCloseTo(321) + expect(box.cy).toBeCloseTo(567, 1) + }) + }) + + describe('size()', function() { + it('should define the width and height of the element', function() { + text.size(50) + expect(text.attr('font-size').valueOf()).toBe(50) + }) + }) + + describe('translate()', function() { + it('sets the translation of an element', function() { + text.transform({ x: 12, y: 12 }) + expect(text.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)') + }) + }) + + describe('text()', function() { + it('adds content in a nested tspan', function() { + text.text('It is a bear!') + expect(text.node.childNodes[0].nodeType).toBe(1) + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('It is a bear!') + }) + it('adds content in a nested tspan even with an empty string', function() { + text.text('') + expect(text.node.childNodes[0].nodeType).toBe(1) + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('') + }) + it('creates multiple lines with a newline separated string', function() { + text.text('It is\nJUST\na bear!') + expect(text.node.childNodes.length).toBe(3) + }) + it('restores the content from the dom', function() { + text.text('It is\nJUST\na bear!') + expect(text.text()).toBe('It is\nJUST\na bear!') + }) + it('gets the given content of a text element without an argument', function() { + text.text('It is another bear!') + expect(text.node.childNodes[0].nodeType).toBe(1) + expect(text.text()).toMatch('It is another bear!') + }) + it('accepts a block as first arguments', function() { + text.text(function(add) { + add.tspan('mastaba') + add.plain('hut') + }) + expect(text.node.childNodes[0].nodeType).toBe(1) + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('mastaba') + expect(text.node.childNodes[1].nodeType).toBe(3) + expect(text.node.childNodes[1].nodeValue).toBe('hut') + }) + }) + + describe('plain()', function() { + it('adds content without a tspan', function() { + text.plain('It is a bear!') + expect(text.node.childNodes[0].nodeType).toBe(3) + expect(text.node.childNodes[0].nodeValue).toBe('It is a bear!') + }) + it('clears content before adding new content', function() { + text.plain('It is not a bear!') + expect(text.node.childNodes.length).toBe(1) + expect(text.node.childNodes[0].nodeValue).toBe('It is not a bear!') + }) + it('restores the content from the dom', function() { + text.plain('Just plain text!') + expect(text.text()).toBe('Just plain text!') + }) + }) + + describe('tspan()', function() { + it('adds content in a tspan', function() { + text.tspan('It is a bear!') + expect(text.node.childNodes[0].nodeType).toBe(1) + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('It is a bear!') + }) + it('clears content before adding new content', function() { + text.tspan('It is not a bear!') + expect(text.node.childNodes.length).toBe(1) + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('It is not a bear!') + }) + }) + + describe('clear()', function() { + it('removes all content', function() { + text.text(function(add) { + add.tspan('The first.') + add.tspan('The second.') + add.tspan('The third.') + }) + expect(text.node.childNodes.length).toBe(3) + text.clear() + expect(text.node.childNodes.length).toBe(0) + }) + }) + + describe('lines()', function() { + it('gets an array of individual lines as an instance of SVG.Set', function() { + var l1, l2, l3 + text.text(function(add) { + l1 = add.tspan('The first.') + l2 = add.tspan('The second.') + l3 = add.tspan('The third.') + }) + expect(text.lines().length()).toBe(3) + expect(text.lines().get(0)).toBe(l1) + expect(text.lines().get(1)).toBe(l2) + expect(text.lines().get(2)).toBe(l3) + }) + }) + + describe('length()', function() { + it('gets total length of text', function() { + text.text(function(add) { + add.tspan('The first.') + add.tspan('The second.') + add.tspan('The third.') + }) + expect(text.length()).toBeCloseTo(text.lines().get(0).length() + text.lines().get(1).length() + text.lines().get(2).length(), 3) + }) + }) + + describe('build()', function() { + it('enables adding multiple plain text nodes when given true', function() { + text.clear().build(true) + text.plain('A great piece!') + text.plain('Another great piece!') + expect(text.node.childNodes[0].nodeValue).toBe('A great piece!') + expect(text.node.childNodes[1].nodeValue).toBe('Another great piece!') + }) + it('enables adding multiple tspan nodes when given true', function() { + text.clear().build(true) + text.tspan('A great piece!') + text.tspan('Another great piece!') + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('A great piece!') + expect(text.node.childNodes[1].childNodes[0].nodeValue).toBe('Another great piece!') + }) + it('disables adding multiple plain text nodes when given false', function() { + text.clear().build(true) + text.plain('A great piece!') + text.build(false).plain('Another great piece!') + expect(text.node.childNodes[0].nodeValue).toBe('Another great piece!') + expect(text.node.childNodes[1]).toBe(undefined) + }) + it('disables adding multiple tspan nodes when given false', function() { + text.clear().build(true) + text.tspan('A great piece!') + text.build(false).tspan('Another great piece!') + expect(text.node.childNodes[0].childNodes[0].nodeValue).toBe('Another great piece!') + expect(text.node.childNodes[1]).toBe(undefined) + }) + }) + + describe('setData()', function() { + it('read all data from the svgjs:data attribute and assign it to el.dom', function(){ + + text.attr('svgjs:data', '{"foo":"bar","leading":"3px"}') + text.setData(JSON.parse(text.attr('svgjs:data'))) + + expect(text.dom.foo).toBe('bar') + expect(text.dom.leading instanceof SVG.Number).toBeTruthy() + expect(text.dom.leading.value).toBe(3) + expect(text.dom.leading.unit).toBe('px') + }) + }) + +}) + + + + + + + + diff --git a/node_modules/svgjs/spec/spec/textpath.js b/node_modules/svgjs/spec/spec/textpath.js new file mode 100644 index 0000000..362a854 --- /dev/null +++ b/node_modules/svgjs/spec/spec/textpath.js @@ -0,0 +1,35 @@ +describe('TextPath', function() { + var text + , data = 'M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100' + + beforeEach(function() { + text = draw.text('We go up, then we go down, then up again') + }) + + afterEach(function() { + draw.clear() + }) + + describe('path()', function() { + it('returns the text element', function() { + expect(text.path(data)).toBe(text) + }) + it('creates a textPath node in the text element', function() { + text.path(data) + expect(text.node.firstChild.nodeName).toBe('textPath') + }) + }) + + describe('textPath()', function() { + it('creates a reference to the textPath', function() { + expect(text.path(data).textPath() instanceof SVG.TextPath).toBe(true) + }) + }) + + describe('track()', function() { + it('creates a reference to the path', function() { + expect(text.path(data).track() instanceof SVG.Path).toBe(true) + }) + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/spec/spec/use.js b/node_modules/svgjs/spec/spec/use.js new file mode 100644 index 0000000..0de5b39 --- /dev/null +++ b/node_modules/svgjs/spec/spec/use.js @@ -0,0 +1,43 @@ +describe('Use', function() { + var use + + describe('on a container element', function() { + var rect + + beforeEach(function() { + rect = draw.rect(100,100) + use = draw.use(rect) + }) + + it('creates an instance of SVG.Use', function() { + expect(use instanceof SVG.Use).toBe(true) + }) + + it('sets the target element id to its href attribute', function() { + expect(use.node.getAttributeNS(SVG.xlink, 'href')).toBe('#' + rect) + }) + + it('adopts the geometry of the target element', function() { + expect(use.bbox()).toEqual(rect.bbox()) + }) + }) + + describe('on an external path', function() { + var file = 'http://upload.wikimedia.org/wikipedia/commons/8/84/Example.svg' + , id = 'flowRoot1882' + + beforeEach(function() { + use = draw.use(id, file) + }) + + it('creates an instance of SVG.Use', function() { + expect(use instanceof SVG.Use).toBe(true) + }) + + it('sets the target element id and file path to its href attribute', function() { + expect(use.node.getAttributeNS(SVG.xlink, 'href')).toBe(file + '#' + id) + }) + + }) + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/arrange.js b/node_modules/svgjs/src/arrange.js new file mode 100644 index 0000000..904381f --- /dev/null +++ b/node_modules/svgjs/src/arrange.js @@ -0,0 +1,85 @@ +// ### 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) +, previous: function() { + return this.siblings()[this.position() - 1] + } + // Send given element one step forward +, forward: function() { + var i = this.position() + 1 + , 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 + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/array.js b/node_modules/svgjs/src/array.js new file mode 100644 index 0000000..8f47774 --- /dev/null +++ b/node_modules/svgjs/src/array.js @@ -0,0 +1,80 @@ +// 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] + , 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 + return this.value = 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 this.split(array) + } + // Strip unnecessary whitespace +, split: function(string) { + return string.trim().split(/\s+/) + } + // Reverse array +, reverse: function() { + this.value.reverse() + + return this + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/attr.js b/node_modules/svgjs/src/attr.js new file mode 100644 index 0000000..9340981 --- /dev/null +++ b/node_modules/svgjs/src/attr.js @@ -0,0 +1,83 @@ +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 { + // BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0 + if (a == 'stroke-width') + this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null) + else if (a == 'stroke') + this._stroke = v + + // convert image fill and stroke to patterns + if (a == 'fill' || a == 'stroke') { + if (SVG.regex.isImage.test(v)) + v = this.doc().defs().image(v, 0, 0) + + 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) + + // ensure full hex color + else if (SVG.Color.isColor(v)) + v = new SVG.Color(v) + + // parse array values + else if (Array.isArray(v)) + v = new SVG.Array(v) + + // store parametric transformation values locally + else if (v instanceof SVG.Matrix && v.param) + this.param = v.param + + // 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 + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/bare.js b/node_modules/svgjs/src/bare.js new file mode 100644 index 0000000..a045165 --- /dev/null +++ b/node_modules/svgjs/src/bare.js @@ -0,0 +1,45 @@ + +SVG.Bare = SVG.invent({ + // Initialize + create: function(element, inherit) { + // construct element + this.constructor.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(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)) + } + // Add symbol element +, symbol: function() { + return this.defs().element('symbol', SVG.Container) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/boxes.js b/node_modules/svgjs/src/boxes.js new file mode 100644 index 0000000..3066be2 --- /dev/null +++ b/node_modules/svgjs/src/boxes.js @@ -0,0 +1,164 @@ +SVG.BBox = SVG.invent({ + // Initialize + create: function(element) { + // get values if element is given + if (element) { + var box + + // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered + try { + // find native bbox + box = element.node.getBBox() + } catch(e) { + if(element instanceof SVG.Shape){ + var clone = element.clone().addTo(SVG.parser.draw) + box = clone.bbox() + clone.remove() + }else{ + box = { + x: element.node.clientLeft + , y: element.node.clientTop + , width: element.node.clientWidth + , height: element.node.clientHeight + } + } + } + + // plain x and y + this.x = box.x + this.y = box.y + + // plain width and height + this.width = box.width + this.height = box.height + } + + // add center, right and bottom + fullBox(this) + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get bounding box + bbox: function() { + return new SVG.BBox(this) + } + } + +}) + +SVG.TBox = SVG.invent({ + // Initialize + create: function(element) { + // get values if element is given + if (element) { + var t = element.ctm().extract() + , box = element.bbox() + + // width and height including transformations + this.width = box.width * t.scaleX + this.height = box.height * t.scaleY + + // x and y including transformations + this.x = box.x + t.x + this.y = box.y + t.y + } + + // add center, right and bottom + fullBox(this) + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get transformed bounding box + tbox: function() { + return new SVG.TBox(this) + } + } + +}) + + +SVG.RBox = SVG.invent({ + // Initialize + create: function(element) { + if (element) { + var e = element.doc().parent() + , box = element.node.getBoundingClientRect() + , zoom = 1 + + // get screen offset + this.x = box.left + this.y = box.top + + // subtract parent offset + this.x -= e.offsetLeft + this.y -= e.offsetTop + + while (e = e.offsetParent) { + this.x -= e.offsetLeft + this.y -= e.offsetTop + } + + // calculate cumulative zoom from svg documents + e = element + while (e.parent && (e = e.parent())) { + if (e.viewbox) { + zoom *= e.viewbox().zoom + this.x -= e.x() || 0 + this.y -= e.y() || 0 + } + } + + // recalculate viewbox distortion + this.width = box.width /= zoom + this.height = box.height /= zoom + } + + // add center, right and bottom + fullBox(this) + + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + this.y += window.pageYOffset + } + + // define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get rect box + rbox: function() { + return new SVG.RBox(this) + } + } + +}) + +// Add universal merge method +;[SVG.BBox, SVG.TBox, SVG.RBox].forEach(function(c) { + + SVG.extend(c, { + // Merge rect box with another, return a new instance + merge: function(box) { + var b = new c() + + // merge boxes + b.x = Math.min(this.x, box.x) + b.y = Math.min(this.y, box.y) + b.width = Math.max(this.x + this.width, box.x + box.width) - b.x + b.height = Math.max(this.y + this.height, box.y + box.height) - b.y + + return fullBox(b) + } + + }) + +}) diff --git a/node_modules/svgjs/src/clip.js b/node_modules/svgjs/src/clip.js new file mode 100644 index 0000000..2a92e44 --- /dev/null +++ b/node_modules/svgjs/src/clip.js @@ -0,0 +1,58 @@ +SVG.ClipPath = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('clipPath')) + + // keep references to clipped elements + this.targets = [] + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Unclip all clipped elements and remove itself + remove: function() { + // unclip all targets + for (var i = this.targets.length - 1; i >= 0; i--) + if (this.targets[i]) + this.targets[i].unclip() + this.targets = [] + + // remove clipPath from parent + this.parent().removeElement(this) + + return this + } + } + + // 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 + this.clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element) + + // store reverence on self in mask + this.clipper.targets.push(this) + + // apply mask + return this.attr('clip-path', 'url("#' + this.clipper.attr('id') + '")') + } + // Unclip element +, unclip: function() { + delete this.clipper + return this.attr('clip-path', null) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/color.js b/node_modules/svgjs/src/color.js new file mode 100644 index 0000000..1564bba --- /dev/null +++ b/node_modules/svgjs/src/color.js @@ -0,0 +1,106 @@ +// Module for color convertions +SVG.Color = function(color) { + var match + + // initialize defaults + this.r = 0 + this.g = 0 + this.b = 0 + + // parse color + if (typeof color === 'string') { + if (SVG.regex.isRgb.test(color)) { + // get rgb values + match = SVG.regex.rgb.exec(color.replace(/\s/g,'')) + + // 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) +} \ No newline at end of file diff --git a/node_modules/svgjs/src/container.js b/node_modules/svgjs/src/container.js new file mode 100644 index 0000000..33427c6 --- /dev/null +++ b/node_modules/svgjs/src/container.js @@ -0,0 +1,27 @@ +SVG.Container = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Parent + + // Add class methods +, extend: { + // Get the viewBox and calculate the zoom value + viewbox: function(v) { + if (arguments.length == 0) + // act as a getter if there are no arguments + return new SVG.ViewBox(this) + + // otherwise act as a setter + v = arguments.length == 1 ? + [v.x, v.y, v.width, v.height] : + [].slice.call(arguments) + + return this.attr('viewBox', v) + } + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/data.js b/node_modules/svgjs/src/data.js new file mode 100644 index 0000000..cefa21c --- /dev/null +++ b/node_modules/svgjs/src/data.js @@ -0,0 +1,29 @@ + +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 + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/default.js b/node_modules/svgjs/src/default.js new file mode 100644 index 0000000..d371ca0 --- /dev/null +++ b/node_modules/svgjs/src/default.js @@ -0,0 +1,36 @@ + +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' + } + +} \ No newline at end of file diff --git a/node_modules/svgjs/src/defs.js b/node_modules/svgjs/src/defs.js new file mode 100644 index 0000000..ad66cc5 --- /dev/null +++ b/node_modules/svgjs/src/defs.js @@ -0,0 +1,9 @@ + +SVG.Defs = SVG.invent({ + // Initialize node + create: 'defs' + + // Inherit from +, inherit: SVG.Container + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/doc.js b/node_modules/svgjs/src/doc.js new file mode 100644 index 0000000..ef1a58b --- /dev/null +++ b/node_modules/svgjs/src/doc.js @@ -0,0 +1,80 @@ +SVG.Doc = SVG.invent({ + // Initialize node + create: function(element) { + if (element) { + // ensure the presence of a dom element + element = typeof element == 'string' ? + document.getElementById(element) : + element + + // If the target is an svg element, use that element as the main wrapper. + // This allows svg.js to work with svg documents as well. + if (element.nodeName == 'svg') { + this.constructor.call(this, element) + } else { + this.constructor.call(this, SVG.create('svg')) + element.appendChild(this.node) + } + + // set svg element attributes and ensure defs node + this.namespace().size('100%', '100%').defs() + } + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Add namespaces + namespace: function() { + 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._defs) { + var defs + + // Find or create a defs element in this instance + if (defs = this.node.getElementsByTagName('defs')[0]) + this._defs = SVG.adopt(defs) + else + this._defs = new SVG.Defs + + // Make sure the defs node is at the end of the stack + this.node.appendChild(this._defs.node) + } + + return this._defs + } + // custom parent method + , parent: function() { + return this.node.parentNode.nodeName == '#document' ? null : this.node.parentNode + } + // Fix for possible sub-pixel offset. See: + // https://bugzilla.mozilla.org/show_bug.cgi?id=608812 + , spof: function(spof) { + var pos = this.node.getScreenCTM() + + if (pos) + this + .style('left', (-pos.e % 1) + 'px') + .style('top', (-pos.f % 1) + 'px') + + return this + } + + // Removes the doc from the DOM + , remove: function() { + if(this.parent()) { + this.parent().removeChild(this.node); + } + + return this; + } + } + +}) diff --git a/node_modules/svgjs/src/element.js b/node_modules/svgjs/src/element.js new file mode 100644 index 0000000..090459f --- /dev/null +++ b/node_modules/svgjs/src/element.js @@ -0,0 +1,260 @@ + +SVG.Element = SVG.invent({ + // Initialize node + create: function(node) { + // make stroke value accessible dynamically + this._stroke = SVG.defaults.attrs.stroke + + // initialize data object + this.dom = {} + + // create circular reference + if (this.node = node) { + this.type = node.nodeName + this.node.instance = this + + // store current attribute value + this._stroke = node.getAttribute('stroke') || this._stroke + } + } + + // 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.bbox(), width, height) + + return this + .width(new SVG.Number(p.width)) + .height(new SVG.Number(p.height)) + } + // Clone element + , clone: function() { + // clone element and assign new id + var clone = assignNewId(this.node.cloneNode(true)) + + // insert the clone after myself + 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 parent.put(this) + } + // Add element to given container and return container + , putIn: function(parent) { + return parent.add(this) + } + // Get / set id + , id: function(id) { + 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.style('display', '') + } + // Hide element + , hide: function() { + return this.style('display', 'none') + } + // Is element visible? + , visible: function() { + return this.style('display') != 'none' + } + // Return id on string conversion + , toString: function() { + return this.attr('id') + } + // Return array of classes on the node + , classes: function() { + var attr = this.attr('class') + + return attr == null ? [] : attr.trim().split(/\s+/) + } + // 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.node instanceof SVGElement){ + if(typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = SVG.adopt(parent.node.parentNode) + } + } + // Get parent document + , doc: function() { + return this instanceof SVG.Doc ? this : this.parent(SVG.Doc) + } + // return array of all ancestors of given type up to the root svg + , parents: function(type) { + var parents = [], 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) { + // create temporary holder + var well = document.createElement('svg') + + // act as a setter if svg is given + if (svg && this instanceof SVG.Parent) { + // dump raw svg + well.innerHTML = '' + svg.replace(/\n/, '').replace(/<(\w+)([^<]+?)\/>/g, '<$1$2>') + '' + + // transplant nodes + for (var i = 0, il = well.firstChild.childNodes.length; i < il; i++) + this.node.appendChild(well.firstChild.firstChild) + + // otherwise act as a getter + } else { + // create a wrapping svg element in case of partial content + well.appendChild(svg = document.createElement('svg')) + + // write svgjs data to the dom + this.writeDataToDom() + + // insert a copy of this node + svg.appendChild(this.node.cloneNode(true)) + + // return target element + return well.innerHTML.replace(/^/, '').replace(/<\/svg>$/, '') + } + + return this + } + // write svgjs data to the dom + , writeDataToDom: function() { + + // dump variables recursively + if(this.each || this.lines){ + var fn = this.each ? this : this.lines(); + fn.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 + } + } +}) diff --git a/node_modules/svgjs/src/ellipse.js b/node_modules/svgjs/src/ellipse.js new file mode 100644 index 0000000..b1ae4fc --- /dev/null +++ b/node_modules/svgjs/src/ellipse.js @@ -0,0 +1,89 @@ +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.bbox(), width, height) + + return this + .rx(new SVG.Number(p.width).divide(2)) + .ry(new SVG.Number(p.height).divide(2)) + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/event.js b/node_modules/svgjs/src/event.js new file mode 100644 index 0000000..66cf6c3 --- /dev/null +++ b/node_modules/svgjs/src/event.js @@ -0,0 +1,136 @@ +// Add events to elements +;[ 'click' + , 'dblclick' + , 'mousedown' + , 'mouseup' + , 'mouseover' + , 'mouseout' + , 'mousemove' + // , 'mouseenter' -> not supported by IE + // , 'mouseleave' -> not supported by IE + , 'touchstart' + , 'touchmove' + , 'touchleave' + , 'touchend' + , 'touchcancel' ].forEach(function(event) { + + // add event to SVG.Element + SVG.Element.prototype[event] = function(f) { + var self = this + + // bind event to element rather than element node + this.node['on' + event] = typeof f == 'function' ? + function() { return f.apply(self, arguments) } : null + + return this + } + +}) + +// Initialize listeners stack +SVG.listeners = [] +SVG.handlerMap = [] + +// Add event binder in the SVG namespace +SVG.on = function(node, event, listener, binding) { + // create listener, get object-index + var l = listener.bind(binding || node.instance || node) + , index = (SVG.handlerMap.indexOf(node) + 1 || SVG.handlerMap.push(node)) - 1 + , ev = event.split('.')[0] + , ns = event.split('.')[1] || '*' + + + // ensure valid object + SVG.listeners[index] = SVG.listeners[index] || {} + SVG.listeners[index][ev] = SVG.listeners[index][ev] || {} + SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {} + + // reference listener + SVG.listeners[index][ev][ns][listener] = l + + // add listener + node.addEventListener(ev, l, false) +} + +// Add event unbinder in the SVG namespace +SVG.off = function(node, event, listener) { + var index = SVG.handlerMap.indexOf(node) + , ev = event && event.split('.')[0] + , ns = event && event.split('.')[1] + + if(index == -1) return + + if (listener) { + // remove listener reference + if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) { + // remove listener + node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false) + + delete SVG.listeners[index][ev][ns || '*'][listener] + } + + } else if (ns && ev) { + // remove all listeners for a namespaced event + if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) { + for (listener in SVG.listeners[index][ev][ns]) + SVG.off(node, [ev, ns].join('.'), listener) + + delete SVG.listeners[index][ev][ns] + } + + } else if (ns){ + // remove all listeners for a specific namespace + for(event in SVG.listeners[index]){ + for(namespace in SVG.listeners[index][event]){ + if(ns === namespace){ + SVG.off(node, [event, ns].join('.')) + } + } + } + + } else if (ev) { + // remove all listeners for the event + if (SVG.listeners[index][ev]) { + for (namespace in SVG.listeners[index][ev]) + SVG.off(node, [ev, namespace].join('.')) + + delete SVG.listeners[index][ev] + } + + } else { + // remove all listeners on a given node + for (event in SVG.listeners[index]) + SVG.off(node, event) + + delete SVG.listeners[index] + + } +} + +// +SVG.extend(SVG.Element, { + // Bind given event to listener + on: function(event, listener, binding) { + SVG.on(this.node, event, listener, binding) + + return this + } + // Unbind event from listener +, off: function(event, listener) { + SVG.off(this.node, event, listener) + + return this + } + // Fire given event +, fire: function(event, data) { + + // Dispatch event + if(event instanceof Event){ + this.node.dispatchEvent(event) + }else{ + this.node.dispatchEvent(new CustomEvent(event, {detail:data})) + } + + return this + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/fx.js b/node_modules/svgjs/src/fx.js new file mode 100644 index 0000000..4ed85a2 --- /dev/null +++ b/node_modules/svgjs/src/fx.js @@ -0,0 +1,460 @@ +SVG.FX = SVG.invent({ + // Initialize FX object + create: function(element) { + // store target element + this.target = element + } + + // Add class methods +, extend: { + // Add animation parameters and start animation + animate: function(d, ease, delay) { + var akeys, skeys, key + , element = this.target + , fx = this + + // dissect object if one is passed + if (typeof d == 'object') { + delay = d.delay + ease = d.ease + d = d.duration + } + + // ensure default duration and easing + d = d == '=' ? d : d == null ? 1000 : new SVG.Number(d).valueOf() + ease = ease || '<>' + + // process values + fx.at = function(pos) { + var i + + // normalise pos + pos = pos < 0 ? 0 : pos > 1 ? 1 : pos + + // collect attribute keys + if (akeys == null) { + akeys = [] + for (key in fx.attrs) + akeys.push(key) + + // make sure morphable elements are scaled, translated and morphed all together + if (element.morphArray && (fx.destination.plot || akeys.indexOf('points') > -1)) { + // get destination + var box + , p = new element.morphArray(fx.destination.plot || fx.attrs.points || element.array()) + + // add size + if (fx.destination.size) + p.size(fx.destination.size.width.to, fx.destination.size.height.to) + + // add movement + box = p.bbox() + if (fx.destination.x) + p.move(fx.destination.x.to, box.y) + else if (fx.destination.cx) + p.move(fx.destination.cx.to - box.width / 2, box.y) + + box = p.bbox() + if (fx.destination.y) + p.move(box.x, fx.destination.y.to) + else if (fx.destination.cy) + p.move(box.x, fx.destination.cy.to - box.height / 2) + + // reset destination values + fx.destination = { + plot: element.array().morph(p) + } + } + } + + // collect style keys + if (skeys == null) { + skeys = [] + for (key in fx.styles) + skeys.push(key) + } + + // apply easing + pos = ease == '<>' ? + (-Math.cos(pos * Math.PI) / 2) + 0.5 : + ease == '>' ? + Math.sin(pos * Math.PI / 2) : + ease == '<' ? + -Math.cos(pos * Math.PI / 2) + 1 : + ease == '-' ? + pos : + typeof ease == 'function' ? + ease(pos) : + pos + + // run plot function + if (fx.destination.plot) { + element.plot(fx.destination.plot.at(pos)) + + } else { + // run all x-position properties + if (fx.destination.x) + element.x(fx.destination.x.at(pos)) + else if (fx.destination.cx) + element.cx(fx.destination.cx.at(pos)) + + // run all y-position properties + if (fx.destination.y) + element.y(fx.destination.y.at(pos)) + else if (fx.destination.cy) + element.cy(fx.destination.cy.at(pos)) + + // run all size properties + if (fx.destination.size) + element.size(fx.destination.size.width.at(pos), fx.destination.size.height.at(pos)) + } + + // run all viewbox properties + if (fx.destination.viewbox) + element.viewbox( + fx.destination.viewbox.x.at(pos) + , fx.destination.viewbox.y.at(pos) + , fx.destination.viewbox.width.at(pos) + , fx.destination.viewbox.height.at(pos) + ) + + // run leading property + if (fx.destination.leading) + element.leading(fx.destination.leading.at(pos)) + + // animate attributes + for (i = akeys.length - 1; i >= 0; i--) + element.attr(akeys[i], at(fx.attrs[akeys[i]], pos)) + + // animate styles + for (i = skeys.length - 1; i >= 0; i--) + element.style(skeys[i], at(fx.styles[skeys[i]], pos)) + + // callback for each keyframe + if (fx.situation.during) + fx.situation.during.call(element, pos, function(from, to) { + return at({ from: from, to: to }, pos) + }) + } + + if (typeof d === 'number') { + // delay animation + this.timeout = setTimeout(function() { + var start = new Date().getTime() + + // initialize situation object + fx.situation.start = start + fx.situation.play = true + fx.situation.finish = start + d + fx.situation.duration = d + fx.situation.ease = ease + + // render function + fx.render = function() { + + if (fx.situation.play === true) { + // calculate pos + var time = new Date().getTime() + , pos = time > fx.situation.finish ? 1 : (time - fx.situation.start) / d + + // reverse pos if animation is reversed + if (fx.situation.reversing) + pos = -pos + 1 + + // process values + fx.at(pos) + + // finish off animation + if (time > fx.situation.finish) { + if (fx.destination.plot) + element.plot(new SVG.PointArray(fx.destination.plot.destination).settle()) + + if (fx.situation.loop === true || (typeof fx.situation.loop == 'number' && fx.situation.loop > 0)) { + // register reverse + if (fx.situation.reverse) + fx.situation.reversing = !fx.situation.reversing + + if (typeof fx.situation.loop == 'number') { + // reduce loop count + if (!fx.situation.reverse || fx.situation.reversing) + --fx.situation.loop + + // remove last loop if reverse is disabled + if (!fx.situation.reverse && fx.situation.loop == 1) + --fx.situation.loop + } + + fx.animate(d, ease, delay) + } else { + fx.situation.after ? fx.situation.after.apply(element, [fx]) : fx.stop() + } + + } else { + fx.animationFrame = requestAnimationFrame(fx.render) + } + } else { + fx.animationFrame = requestAnimationFrame(fx.render) + } + + } + + // start animation + fx.render() + + }, new SVG.Number(delay).valueOf()) + } + + return this + } + // Get bounding box of target element + , bbox: function() { + return this.target.bbox() + } + // Add animatable attributes + , attr: function(a, v) { + // apply attributes individually + if (typeof a == 'object') { + for (var key in a) + this.attr(key, a[key]) + + } else { + // get the current state + var from = this.target.attr(a) + + // detect format + if (a == 'transform') { + // merge given transformation with an existing one + if (this.attrs[a]) + v = this.attrs[a].destination.multiply(v) + + // prepare matrix for morphing + this.attrs[a] = (new SVG.Matrix(this.target)).morph(v) + + // add parametric rotation values + if (this.param) { + // get initial rotation + v = this.target.transform('rotation') + + // add param + this.attrs[a].param = { + from: this.target.param || { rotation: v, cx: this.param.cx, cy: this.param.cy } + , to: this.param + } + } + + } else { + this.attrs[a] = SVG.Color.isColor(v) ? + // prepare color for morphing + new SVG.Color(from).morph(v) : + SVG.regex.unit.test(v) ? + // prepare number for morphing + new SVG.Number(from).morph(v) : + // prepare for plain morphing + { from: from, to: v } + } + } + + return this + } + // Add animatable styles + , style: function(s, v) { + if (typeof s == 'object') + for (var key in s) + this.style(key, s[key]) + + else + this.styles[s] = { from: this.target.style(s), to: v } + + return this + } + // Animatable x-axis + , x: function(x) { + this.destination.x = new SVG.Number(this.target.x()).morph(x) + + return this + } + // Animatable y-axis + , y: function(y) { + this.destination.y = new SVG.Number(this.target.y()).morph(y) + + return this + } + // Animatable center x-axis + , cx: function(x) { + this.destination.cx = new SVG.Number(this.target.cx()).morph(x) + + return this + } + // Animatable center y-axis + , cy: function(y) { + this.destination.cy = new SVG.Number(this.target.cy()).morph(y) + + return this + } + // 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 = this.target.bbox() + + this.destination.size = { + width: new SVG.Number(box.width).morph(width) + , height: new SVG.Number(box.height).morph(height) + } + } + + return this + } + // Add animatable plot + , plot: function(p) { + this.destination.plot = p + + return this + } + // Add leading method + , leading: function(value) { + if (this.target.destination.leading) + this.destination.leading = new SVG.Number(this.target.destination.leading).morph(value) + + return this + } + // Add animatable viewbox + , viewbox: function(x, y, width, height) { + if (this.target instanceof SVG.Container) { + var box = this.target.viewbox() + + this.destination.viewbox = { + x: new SVG.Number(box.x).morph(x) + , y: new SVG.Number(box.y).morph(y) + , width: new SVG.Number(box.width).morph(width) + , height: new SVG.Number(box.height).morph(height) + } + } + + return this + } + // Add animateable gradient update + , update: function(o) { + if (this.target instanceof SVG.Stop) { + 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 + } + // Add callback for each keyframe + , during: function(during) { + this.situation.during = during + + return this + } + // Callback after animation + , after: function(after) { + this.situation.after = after + + return this + } + // Make loopable + , loop: function(times, reverse) { + // store current loop and total loops + this.situation.loop = this.situation.loops = times || true + + // make reversable + this.situation.reverse = !!reverse + + return this + } + // Stop running animation + , stop: function(fulfill) { + // fulfill animation + if (fulfill === true) { + + this.animate(0) + + if (this.situation.after) + this.situation.after.apply(this.target, [this]) + + } else { + // stop current animation + clearTimeout(this.timeout) + cancelAnimationFrame(this.animationFrame); + + // reset storage for properties + this.attrs = {} + this.styles = {} + this.situation = {} + this.destination = {} + } + + return this + } + // Pause running animation + , pause: function() { + if (this.situation.play === true) { + this.situation.play = false + this.situation.pause = new Date().getTime() + } + + return this + } + // Play running animation + , play: function() { + if (this.situation.play === false) { + var pause = new Date().getTime() - this.situation.pause + + this.situation.finish += pause + this.situation.start += pause + this.situation.play = true + } + + return this + } + + } + + // Define parent class +, 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(d, ease, delay) { + return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(d, ease, delay) + } + // Stop current animation; this is an alias to the fx instance + , stop: function(fulfill) { + if (this.fx) + this.fx.stop(fulfill) + + 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 + } + + } +}) diff --git a/node_modules/svgjs/src/gradient.js b/node_modules/svgjs/src/gradient.js new file mode 100644 index 0000000..9478747 --- /dev/null +++ b/node_modules/svgjs/src/gradient.js @@ -0,0 +1,107 @@ +SVG.Gradient = SVG.invent({ + // Initialize node + create: function(type) { + this.constructor.call(this, SVG.create(type + 'Gradient')) + + // store type + this.type = type + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Add a color stop + at: 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 + , fill: function() { + return 'url(#' + this.id() + ')' + } + // Alias string convertion to fill + , toString: function() { + return this.fill() + } + // 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 == 'radial' ? + 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 == 'radial' ? + 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 + } + } + +}) diff --git a/node_modules/svgjs/src/group.js b/node_modules/svgjs/src/group.js new file mode 100644 index 0000000..05d144c --- /dev/null +++ b/node_modules/svgjs/src/group.js @@ -0,0 +1,50 @@ +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.tbox().cx : this.x(x - this.tbox().width / 2) + } + // Move by center over y-axis + , cy: function(y) { + return y == null ? this.tbox().cy : this.y(y - this.tbox().height / 2) + } + , gbox: function() { + + var bbox = this.bbox() + , 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) + } + } +}) diff --git a/node_modules/svgjs/src/helpers.js b/node_modules/svgjs/src/helpers.js new file mode 100644 index 0000000..ee86dc7 --- /dev/null +++ b/node_modules/svgjs/src/helpers.js @@ -0,0 +1,177 @@ +// 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(box, width, height) { + if (height == null) + height = box.height / box.width * width + else if (width == null) + width = box.width / box.height * height + + 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 +} + +// Convert string to matrix +function stringToMatrix(source) { + // remove matrix wrapper and split to individual numbers + source = source + .replace(SVG.regex.whitespace, '') + .replace(SVG.regex.matrix, '') + .split(SVG.regex.matrixElements) + + // convert string values to floats and convert to a matrix-formatted object + return arrayToMatrix( + SVG.utils.map(source, function(n) { + return parseFloat(n) + }) + ) +} + +// Calculate position according to from and to +function at(o, pos) { + // number recalculation (don't bother converting to SVG.Number for performance reasons) + return typeof o.from == 'number' ? + o.from + (o.to - o.from) * pos : + + // instance recalculation + o instanceof SVG.Color || o instanceof SVG.Number || o instanceof SVG.Matrix ? o.at(pos) : + + // for all other values wait until pos has reached 1 to return the final value + pos < 1 ? o.from : o.to +} + +// 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.childNodes.length - 1; i >= 0; i--) + if (node.childNodes[i] instanceof SVGElement) + assignNewId(node.childNodes[i]) + + return SVG.adopt(node).id(SVG.eid(node.nodeName)) +} + +// 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('') \ No newline at end of file diff --git a/node_modules/svgjs/src/hyperlink.js b/node_modules/svgjs/src/hyperlink.js new file mode 100644 index 0000000..a967707 --- /dev/null +++ b/node_modules/svgjs/src/hyperlink.js @@ -0,0 +1,46 @@ +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 show attribute + , show: function(target) { + return this.attr('show', target, 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) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/image.js b/node_modules/svgjs/src/image.js new file mode 100644 index 0000000..a0adf31 --- /dev/null +++ b/node_modules/svgjs/src/image.js @@ -0,0 +1,58 @@ +SVG.Image = SVG.invent({ + // Initialize node + create: 'image' + + // Inherit from +, inherit: SVG.Shape + + // Add class methods +, extend: { + // (re)load image + load: function(url) { + if (!url) return this + + var self = this + , img = document.createElement('img') + + // preload image + img.onload = function() { + var p = self.parent(SVG.Pattern) + + if(p === null) return + + // ensure image size + if (self.width() == 0 && self.height() == 0) + self.size(img.width, img.height) + + // ensure pattern size if not set + if (p && p.width() == 0 && p.height() == 0) + p.size(self.width(), self.height()) + + // callback + if (typeof self._loaded === 'function') + self._loaded.call(self, { + width: img.width + , height: img.height + , ratio: img.width / img.height + , url: url + }) + } + + return this.attr('href', (img.src = this.src = url), SVG.xlink) + } + // Add loaded callback + , loaded: function(loaded) { + this._loaded = loaded + return this + } + } + + // Add parent method +, construct: { + // create image element, load image and set its size + image: function(source, width, height) { + return this.put(new SVG.Image).load(source).size(width || 0, height || width || 0) + } + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/line.js b/node_modules/svgjs/src/line.js new file mode 100644 index 0000000..0fcf63f --- /dev/null +++ b/node_modules/svgjs/src/line.js @@ -0,0 +1,45 @@ +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 (arguments.length == 4) + 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.bbox(), 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) { + return this.put(new SVG.Line).plot(x1, y1, x2, y2) + } + } +}) diff --git a/node_modules/svgjs/src/marker.js b/node_modules/svgjs/src/marker.js new file mode 100644 index 0000000..cdde0ff --- /dev/null +++ b/node_modules/svgjs/src/marker.js @@ -0,0 +1,80 @@ +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) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/mask.js b/node_modules/svgjs/src/mask.js new file mode 100644 index 0000000..51e61e9 --- /dev/null +++ b/node_modules/svgjs/src/mask.js @@ -0,0 +1,58 @@ +SVG.Mask = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('mask')) + + // keep references to masked elements + this.targets = [] + } + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Unmask all masked elements and remove itself + remove: function() { + // unmask all targets + for (var i = this.targets.length - 1; i >= 0; i--) + if (this.targets[i]) + this.targets[i].unmask() + this.targets = [] + + // remove mask from parent + this.parent().removeElement(this) + + return this + } + } + + // 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 + this.masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element) + + // store reverence on self in mask + this.masker.targets.push(this) + + // apply mask + return this.attr('mask', 'url("#' + this.masker.attr('id') + '")') + } + // Unmask element +, unmask: function() { + delete this.masker + return this.attr('mask', null) + } + +}) diff --git a/node_modules/svgjs/src/matrix.js b/node_modules/svgjs/src/matrix.js new file mode 100644 index 0000000..9b3c28e --- /dev/null +++ b/node_modules/svgjs/src/matrix.js @@ -0,0 +1,186 @@ +SVG.Matrix = SVG.invent({ + // Initialize + create: function(source) { + var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0]) + + // ensure source as object + source = source instanceof SVG.Element ? + source.matrixify() : + typeof source === 'string' ? + stringToMatrix(source) : + arguments.length == 6 ? + arrayToMatrix([].slice.call(arguments)) : + typeof source === 'object' ? + source : base + + // merge source + for (i = abcdef.length - 1; i >= 0; i--) + this[abcdef[i]] = source && typeof source[abcdef[i]] === 'number' ? + source[abcdef[i]] : base[abcdef[i]] + } + + // Add methods +, extend: { + // Extract individual transformations + extract: function() { + // find delta transform points + var px = deltaTransformPoint(this, 0, 1) + , py = deltaTransformPoint(this, 1, 0) + , skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90 + + return { + // translation + x: this.e + , y: this.f + // 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 + } + } + // 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 + }) + + // process parametric rotation if present + if (this.param && this.param.to) { + // calculate current parametric position + var param = { + rotation: this.param.from.rotation + (this.param.to.rotation - this.param.from.rotation) * pos + , cx: this.param.from.cx + , cy: this.param.from.cy + } + + // rotate matrix + matrix = matrix.rotate( + (this.param.to.rotation - this.param.from.rotation * 2) * pos + , param.cx + , param.cy + ) + + // store current parametric values + matrix.param = param + } + + 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 universal scale + if (arguments.length == 1 || arguments.length == 3) + y = x + if (arguments.length == 3) { + cy = cx + cx = y + } + + 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) : this.scale(1, -1, 0, o) + } + // Skew + , skew: function(x, y, cx, cy) { + return this.around(cx, cy, this.native().skewX(x || 0).skewY(y || 0)) + } + // SkewX + , skewX: function(x, cx, cy) { + return this.around(cx, cy, this.native().skewX(x || 0)) + } + // SkewY + , skewY: function(y, cx, cy) { + return this.around(cx, cy, this.native().skewY(y || 0)) + } + // 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.draw.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() { + return new SVG.Matrix(this.node.getScreenCTM()) + } + + } + +}) diff --git a/node_modules/svgjs/src/memory.js b/node_modules/svgjs/src/memory.js new file mode 100644 index 0000000..1a30faa --- /dev/null +++ b/node_modules/svgjs/src/memory.js @@ -0,0 +1,36 @@ +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 v in k) + this.remember(v, k[v]) + + // retrieve memory + else if (arguments.length == 1) + return this.memory()[k] + + // store memory + else + 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 = {}) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/nested.js b/node_modules/svgjs/src/nested.js new file mode 100644 index 0000000..f856e52 --- /dev/null +++ b/node_modules/svgjs/src/nested.js @@ -0,0 +1,19 @@ +SVG.Nested = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, SVG.create('svg')) + + this.style('overflow', 'visible') + } + + // Inherit from +, inherit: SVG.Container + + // Add parent method +, construct: { + // Create nested svg document + nested: function() { + return this.put(new SVG.Nested) + } + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/number.js b/node_modules/svgjs/src/number.js new file mode 100644 index 0000000..f0c53e0 --- /dev/null +++ b/node_modules/svgjs/src/number.js @@ -0,0 +1,102 @@ +// 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.unit) + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]) + + // normalize + if (unit[2] == '%') + this.value /= 100 + else if (unit[2] == 's') + this.value *= 1000 + + // store unit + this.unit = unit[2] + } + + } 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) { + return new SVG.Number(this + new SVG.Number(number), this.unit) + } + // Subtract number + , minus: function(number) { + return this.plus(-new SVG.Number(number)) + } + // Multiply number + , times: function(number) { + return new SVG.Number(this * new SVG.Number(number), this.unit) + } + // Divide number + , divide: function(number) { + return new SVG.Number(this / new SVG.Number(number), this.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) + + 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) + } + + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/parent.js b/node_modules/svgjs/src/parent.js new file mode 100644 index 0000000..86c7db8 --- /dev/null +++ b/node_modules/svgjs/src/parent.js @@ -0,0 +1,93 @@ +SVG.Parent = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Element + + // Add class methods +, extend: { + // Returns all child elements + children: function() { + return SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(node) { + return SVG.adopt(node) + }) + } + // Add given element at a position + , add: function(element, i) { + if (!this.has(element)) { + // define insertion index if none given + i = i == null ? this.children().length : i + + // add element references + this.node.insertBefore(element.node, this.node.childNodes[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 + } + // 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 this.children().indexOf(element) + } + // Get a element at the given index + , get: function(i) { + return this.children()[i] + } + // Get first child, skipping the defs node + , first: function() { + return this.children()[0] + } + // Get the last child + , last: function() { + return this.children()[this.children().length - 1] + } + // Iterates over all children and invokes a given block + , each: function(block, deep) { + var i, il + , children = this.children() + + 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.Container)) + 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 + } + , // Get defs + defs: function() { + return this.doc().defs() + } + } + +}) diff --git a/node_modules/svgjs/src/path.js b/node_modules/svgjs/src/path.js new file mode 100644 index 0000000..8282ce7 --- /dev/null +++ b/node_modules/svgjs/src/path.js @@ -0,0 +1,56 @@ +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 poly points + , plot: function(p) { + return this.attr('d', (this._array = new SVG.PathArray(p))) + } + // 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.bbox(), 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) { + return this.put(new SVG.Path).plot(d) + } + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/patharray.js b/node_modules/svgjs/src/patharray.js new file mode 100644 index 0000000..03a9b7f --- /dev/null +++ b/node_modules/svgjs/src/patharray.js @@ -0,0 +1,243 @@ +// Path points array +SVG.PathArray = function(array, fallback) { + this.constructor.call(this, array, fallback || [['M', 0, 0]]) +} + +// Inherit from SVG.Array +SVG.PathArray.prototype = new SVG.Array + +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 i, l, box = this.bbox() + + // 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 + } + // 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 i, x0, y0, s, seg, arr + , x = 0 + , y = 0 + , paramCnt = { 'M':2, 'L':2, 'H':1, 'V':1, 'C':6, 'S':4, 'Q':4, 'T':2, 'A':7 } + + if(typeof array == 'string'){ + + array = array + .replace(SVG.regex.negExp, 'X') // replace all negative exponents with certain char + .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers + .replace(SVG.regex.hyphen, ' -') // add space before hyphen + .replace(SVG.regex.comma, ' ') // unify all spaces + .replace(SVG.regex.X, 'e-') // add back the expoent + .trim() // trim + .split(SVG.regex.whitespaces) // split into array + + // at this place there could be parts like ['3.124.854.32'] because we could not determine the point as seperator till now + // we fix this elements in the next loop + for(i = array.length; --i;){ + if(array[i].indexOf('.') != array[i].lastIndexOf('.')){ + var split = array[i].split('.') // split at the point + var first = [split.shift(), split.shift()].join('.') // join the first number together + array.splice.apply(array, [i, 1].concat(first, split.map(function(el){ return '.'+el }))) // add first and all other entries back to array + } + } + + }else{ + array = array.reduce(function(prev, curr){ + return [].concat.apply(prev, curr) + }, []) + } + + // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + + var arr = [] + + do{ + + // Test if we have a path letter + if(SVG.regex.isPathLetter.test(array[0])){ + s = array[0] + array.shift() + // 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' + } + + // add path letter as first element + seg = [s.toUpperCase()] + + // push all necessary parameters to segment + for(i = 0; i < paramCnt[seg[0]]; ++i){ + seg.push(parseFloat(array.shift())) + } + + // upper case + if(s == seg[0]){ + + if(s == 'M' || s == 'L' || s == 'C' || s == 'Q'){ + x = seg[paramCnt[seg[0]]-1] + y = seg[paramCnt[seg[0]]] + }else if(s == 'V'){ + y = seg[1] + }else if(s == 'H'){ + x = seg[1] + }else if(s == 'A'){ + x = seg[6] + y = seg[7] + } + + // lower case + }else{ + + // convert relative to absolute values + if(s == 'm' || s == 'l' || s == 'c' || s == 's' || s == 'q' || s == 't'){ + + seg[1] += x + seg[2] += y + + if(seg[3] != null){ + seg[3] += x + seg[4] += y + } + + if(seg[5] != null){ + seg[5] += x + seg[6] += y + } + + // move pointer + x = seg[paramCnt[seg[0]]-1] + y = seg[paramCnt[seg[0]]] + + }else if(s == 'v'){ + seg[1] += y + y = seg[1] + }else if(s == 'h'){ + seg[1] += x + x = seg[1] + }else if(s == 'a'){ + seg[6] += x + seg[7] += y + x = seg[6] + y = seg[7] + } + + } + + if(seg[0] == 'M'){ + x0 = x + y0 = y + } + + if(seg[0] == 'Z'){ + x = x0 + y = y0 + } + + arr.push(seg) + + }while(array.length) + + return arr + + } + // Get bounding box of path +, bbox: function() { + SVG.parser.path.setAttribute('d', this.toString()) + + return SVG.parser.path.getBBox() + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/pattern.js b/node_modules/svgjs/src/pattern.js new file mode 100644 index 0000000..fed33c8 --- /dev/null +++ b/node_modules/svgjs/src/pattern.js @@ -0,0 +1,58 @@ +SVG.Pattern = SVG.invent({ + // Initialize node + create: 'pattern' + + // Inherit from +, inherit: SVG.Container + + // Add class methods +, extend: { + // Return the fill id + fill: 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.fill() + } + // 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' + }) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/point.js b/node_modules/svgjs/src/point.js new file mode 100644 index 0000000..ba7bd8f --- /dev/null +++ b/node_modules/svgjs/src/point.js @@ -0,0 +1,72 @@ +SVG.Point = SVG.invent({ + // Initialize + create: function(x,y) { + var i, source, 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} : + y != null ? + {x:x, y:y} : base + + // 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(point) { + // store new destination + this.destination = new SVG.Point(point) + + 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.draw.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()); + } + +}) diff --git a/node_modules/svgjs/src/pointarray.js b/node_modules/svgjs/src/pointarray.js new file mode 100644 index 0000000..d5c632c --- /dev/null +++ b/node_modules/svgjs/src/pointarray.js @@ -0,0 +1,93 @@ +// Poly points array +SVG.PointArray = function(array, fallback) { + this.constructor.call(this, array, fallback || [[0,0]]) +} + +// Inherit from SVG.Array +SVG.PointArray.prototype = new SVG.Array + +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 +, parse: function(array) { + array = array.valueOf() + + // if already is an array, no need to parse it + if (Array.isArray(array)) return array + + // split points + array = this.split(array) + + // parse points + for (var i = 0, il = array.length, p, points = []; i < il; i++) { + p = array[i].split(',') + points.push([parseFloat(p[0]), parseFloat(p[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, box = this.bbox() + + // recalculate position of all points according to new size + for (i = this.value.length - 1; i >= 0; i--) { + this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x + this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y + } + + return this + } + // Get bounding box of points +, bbox: function() { + SVG.parser.poly.setAttribute('points', this.toString()) + + return SVG.parser.poly.getBBox() + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/pointed.js b/node_modules/svgjs/src/pointed.js new file mode 100644 index 0000000..02ff44e --- /dev/null +++ b/node_modules/svgjs/src/pointed.js @@ -0,0 +1,25 @@ +// 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) + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/poly.js b/node_modules/svgjs/src/poly.js new file mode 100644 index 0000000..0f3b1e6 --- /dev/null +++ b/node_modules/svgjs/src/poly.js @@ -0,0 +1,54 @@ +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) { + return this.put(new SVG.Polyline).plot(p) + } + } +}) + +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) { + return this.put(new SVG.Polygon).plot(p) + } + } +}) + +// 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 this.attr('points', (this._array = new SVG.PointArray(p))) + } + // 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.bbox(), width, height) + + return this.attr('points', this.array().size(p.width, p.height)) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/polyfill.js b/node_modules/svgjs/src/polyfill.js new file mode 100644 index 0000000..06ae0fd --- /dev/null +++ b/node_modules/svgjs/src/polyfill.js @@ -0,0 +1,42 @@ +// Add CustomEvent to IE9 and IE10 +if (typeof CustomEvent !== 'function') { + // Code from: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent + var CustomEvent = function(event, options) { + options = options || { bubbles: false, cancelable: false, detail: undefined } + var e = document.createEvent('CustomEvent') + e.initCustomEvent(event, options.bubbles, options.cancelable, options.detail) + return e + } + + CustomEvent.prototype = window.Event.prototype + + window.CustomEvent = CustomEvent +} + +// requestAnimationFrame / cancelAnimationFrame Polyfill with fallback based on Paul Irish +(function(w) { + var lastTime = 0 + var vendors = ['moz', 'webkit'] + + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame'] + w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame'] || + w[vendors[x] + 'CancelRequestAnimationFrame'] + } + + w.requestAnimationFrame = w.requestAnimationFrame || + function(callback) { + var currTime = new Date().getTime() + var timeToCall = Math.max(0, 16 - (currTime - lastTime)) + + var id = w.setTimeout(function() { + callback(currTime + timeToCall) + }, timeToCall) + + lastTime = currTime + timeToCall + return id + } + + w.cancelAnimationFrame = w.cancelAnimationFrame || w.clearTimeout; + +}(window)) \ No newline at end of file diff --git a/node_modules/svgjs/src/rect.js b/node_modules/svgjs/src/rect.js new file mode 100644 index 0000000..6c639fe --- /dev/null +++ b/node_modules/svgjs/src/rect.js @@ -0,0 +1,15 @@ +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) + } + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/regex.js b/node_modules/svgjs/src/regex.js new file mode 100644 index 0000000..d2e6c78 --- /dev/null +++ b/node_modules/svgjs/src/regex.js @@ -0,0 +1,67 @@ +// Storage for regular expressions +SVG.regex = { + // Parse unit value + unit: /^(-?[\d\.]+)([a-z%]{0,2})$/ + + // 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 + + // Parse matrix wrapper +, matrix: /matrix\(|\)/g + + // Elements of a matrix +, matrixElements: /,*\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 + + // The following regex are used to parse the d attribute of a path + + // Replaces all negative exponents +, negExp: /e\-/gi + + // Replaces all comma +, comma: /,/g + + // Replaces all hyphens +, hyphen: /\-/g + + // Replaces and tests for all path letters +, pathLetters: /[MLHVCSQTAZ]/gi + + // yes we need this one, too +, isPathLetter: /[MLHVCSQTAZ]/i + + // split at whitespaces +, whitespaces: /\s+/ + + // matches X +, X: /X/g +} diff --git a/node_modules/svgjs/src/selector.js b/node_modules/svgjs/src/selector.js new file mode 100644 index 0000000..fe87e4e --- /dev/null +++ b/node_modules/svgjs/src/selector.js @@ -0,0 +1,22 @@ +// 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 new SVG.Set( + SVG.utils.map((parent || document).querySelectorAll(query), function(node) { + return SVG.adopt(node) + }) + ) +} + +SVG.extend(SVG.Parent, { + // Scoped select method + select: function(query) { + return SVG.select(query, this.node) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/set.js b/node_modules/svgjs/src/set.js new file mode 100644 index 0000000..41289dd --- /dev/null +++ b/node_modules/svgjs/src/set.js @@ -0,0 +1,153 @@ +SVG.Set = SVG.invent({ + // Initialize + create: function(members) { + // Set initial state + Array.isArray(members) ? this.members = members : this.clear() + } + + // Add class methods +, extend: { + // Add element to set + add: function() { + var i, il, elements = [].slice.call(arguments) + + for (i = 0, il = elements.length; i < il; i++) + this.members.push(elements[i]) + + return this + } + // Remove element from set + , remove: function(element) { + var i = this.index(element) + + // remove given child + if (i > -1) + this.members.splice(i, 1) + + return this + } + // Iterate over all members + , each: function(block) { + for (var i = 0, il = this.members.length; i < il; i++) + block.apply(this.members[i], [i, this.members]) + + return this + } + // Restore to defaults + , clear: function() { + // initialize store + this.members = [] + + return this + } + // Get the length of a set + , length: function() { + return this.members.length + } + // Checks if a given element is present in set + , has: function(element) { + return this.index(element) >= 0 + } + // retuns index of given element in set + , index: function(element) { + return this.members.indexOf(element) + } + // Get member at given index + , get: function(i) { + return this.members[i] + } + // Get first member + , first: function() { + return this.get(0) + } + // Get last member + , last: function() { + return this.get(this.members.length - 1) + } + // Default value + , valueOf: function() { + return this.members + } + // Get the bounding box of all members included or empty box if set has no items + , bbox: function(){ + var box = new SVG.BBox() + + // return an empty box of there are no members + if (this.members.length == 0) + return box + + // get the first rbox and update the target bbox + var rbox = this.members[0].rbox() + box.x = rbox.x + box.y = rbox.y + box.width = rbox.width + box.height = rbox.height + + this.each(function() { + // user rbox for correct position and visual representation + box = box.merge(this.rbox()) + }) + + return box + } + } + + // Add parent method +, construct: { + // Create a new set + set: function(members) { + return new SVG.Set(members) + } + } +}) + +SVG.FX.Set = SVG.invent({ + // Initialize node + create: function(set) { + // store reference to set + this.set = set + } + +}) + +// Alias methods +SVG.Set.inherit = function() { + var m + , methods = [] + + // gather shape methods + for(var m in SVG.Shape.prototype) + if (typeof SVG.Shape.prototype[m] == 'function' && typeof SVG.Set.prototype[m] != 'function') + methods.push(m) + + // apply shape aliasses + methods.forEach(function(method) { + SVG.Set.prototype[method] = function() { + for (var i = 0, il = this.members.length; i < il; i++) + if (this.members[i] && typeof this.members[i][method] == 'function') + this.members[i][method].apply(this.members[i], arguments) + + return method == 'animate' ? (this.fx || (this.fx = new SVG.FX.Set(this))) : this + } + }) + + // clear methods for the next round + methods = [] + + // gather fx methods + for(var m in SVG.FX.prototype) + if (typeof SVG.FX.prototype[m] == 'function' && typeof SVG.FX.Set.prototype[m] != 'function') + methods.push(m) + + // apply fx aliasses + methods.forEach(function(method) { + SVG.FX.Set.prototype[method] = function() { + for (var i = 0, il = this.set.members.length; i < il; i++) + this.set.members[i].fx[method].apply(this.set.members[i].fx, arguments) + + return this + } + }) +} + + diff --git a/node_modules/svgjs/src/shape.js b/node_modules/svgjs/src/shape.js new file mode 100644 index 0000000..3bfc210 --- /dev/null +++ b/node_modules/svgjs/src/shape.js @@ -0,0 +1,10 @@ +SVG.Shape = SVG.invent({ + // Initialize node + create: function(element) { + this.constructor.call(this, element) + } + + // Inherit from +, inherit: SVG.Element + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/style.js b/node_modules/svgjs/src/style.js new file mode 100644 index 0000000..14cf863 --- /dev/null +++ b/node_modules/svgjs/src/style.js @@ -0,0 +1,33 @@ +SVG.extend(SVG.Element, { + // Dynamic style generator + style: function(s, v) { + if (arguments.length == 0) { + // get full style + return this.node.style.cssText || '' + + } else if (arguments.length < 2) { + // apply every style individually if an object is passed + if (typeof s == 'object') { + for (v in s) this.style(v, s[v]) + + } else if (SVG.regex.isCss.test(s)) { + // parse css string + s = s.split(';') + + // apply every definition individually + for (var i = 0; i < s.length; i++) { + v = s[i].split(':') + this.style(v[0].replace(/\s+/g, ''), v[1]) + } + } else { + // act as a getter if the first and only argument is not an object + return this.node.style[camelCase(s)] + } + + } else { + this.node.style[camelCase(s)] = v === null || SVG.regex.isBlank.test(v) ? '' : v + } + + return this + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/sugar.js b/node_modules/svgjs/src/sugar.js new file mode 100644 index 0000000..2a0404c --- /dev/null +++ b/node_modules/svgjs/src/sugar.js @@ -0,0 +1,112 @@ +// 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 i, extension = {} + + extension[m] = function(o) { + 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 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) { + return this.transform({ flip: a, offset: o }) + } + // Map matrix to transform +, matrix: function(m) { + return this.attr('transform', new SVG.Matrix(m)) + } + // Opacity +, opacity: function(value) { + return this.attr('opacity', value) + } + // Relative move over x axis +, dx: function(x) { + return this.x((this.target || this).x() + x) + } + // Relative move over y axis +, dy: function(y) { + return this.y((this.target || this).y() + y) + } + // 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 == 'radial' || type == 'circle' ? + 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 this.node.getPointAtLength(length) + } +}) + +SVG.extend(SVG.Parent, SVG.Text, SVG.FX, { + // Set font + font: function(o) { + for (var k in o) + k == 'leading' ? + this.leading(o[k]) : + k == 'anchor' ? + this.attr('text-anchor', o[k]) : + k == 'size' || k == 'family' || k == 'weight' || k == 'stretch' || k == 'variant' || k == 'style' ? + this.attr('font-'+ k, o[k]) : + this.attr(k, o[k]) + + return this + } +}) + diff --git a/node_modules/svgjs/src/svg.js b/node_modules/svgjs/src/svg.js new file mode 100644 index 0000000..c69aebc --- /dev/null +++ b/node_modules/svgjs/src/svg.js @@ -0,0 +1,146 @@ +// The main wrapping element +var SVG = this.SVG = function(element) { + if (SVG.supported) { + element = new SVG.Doc(element) + + if (!SVG.parser) + SVG.prepare(element) + + return element + } +} + +// 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' + +// Svg support test +SVG.supported = (function() { + return !! document.createElementNS && + !! document.createElementNS(SVG.ns,'svg').createSVGRect +})() + +// Don't bother to continue if SVG is not supported +if (!SVG.supported) return false + +// 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 + var element = document.createElementNS(this.ns, name) + + // apply unique id + element.setAttribute('id', this.eid(name)) + + return element +} + +// Method for extending objects +SVG.extend = function() { + var modules, methods, key, i + + // Get list of modules + modules = [].slice.call(arguments) + + // Get object with extensions + methods = modules.pop() + + for (i = modules.length - 1; i >= 0; i--) + if (modules[i]) + for (key in methods) + modules[i].prototype[key] = methods[key] + + // Make sure SVG.Set inherits any newly added methods + if (SVG.Set && SVG.Set.inherit) + SVG.Set.inherit() +} + +// Invent new element +SVG.invent = function(config) { + // Create element initializer + var initializer = typeof config.create == 'function' ? + config.create : + function() { + this.constructor.call(this, 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) return node.instance + + // initialize variables + var element + + // adopt with element-specific settings + if (node.nodeName == 'svg') + element = node.parentNode instanceof SVGElement ? new SVG.Nested : new SVG.Doc + else if (node.nodeName == 'linearGradient') + element = new SVG.Gradient('linear') + else if (node.nodeName == 'radialGradient') + element = new SVG.Gradient('radial') + else if (SVG[capitalize(node.nodeName)]) + element = new SVG[capitalize(node.nodeName)] + else + element = new SVG.Element(node) + + // ensure references + element.type = node.nodeName + element.node = node + node.instance = element + + // SVG.Class specific preparations + if (element instanceof SVG.Doc) + element.namespace().defs() + + // pull svgjs data from the dom (getAttributeNS doesn't work in html5) + element.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}) + + return element +} + +// Initialize parsing element +SVG.prepare = function(element) { + // Select document body and create invisible svg element + var body = document.getElementsByTagName('body')[0] + , draw = (body ? new SVG.Doc(body) : element.nested()).size(2, 0) + , path = SVG.create('path') + + // Insert parsers + draw.node.appendChild(path) + + // Create parser object + SVG.parser = { + body: body || element.parent() + , draw: draw.style('opacity:0;position:fixed;left:100%;top:100%;overflow:hidden') + , poly: draw.polyline().node + , path: path + } +} diff --git a/node_modules/svgjs/src/text.js b/node_modules/svgjs/src/text.js new file mode 100644 index 0000000..debc1fb --- /dev/null +++ b/node_modules/svgjs/src/text.js @@ -0,0 +1,261 @@ +SVG.Text = SVG.invent({ + // Initialize node + create: function() { + this.constructor.call(this, 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.Shape + + // Add class methods +, extend: { + clone: function(){ + // clone element and assign new id + var clone = assignNewId(this.node.cloneNode(true)) + + // insert the clone after myself + this.after(clone) + + return clone + } + // Move over x-axis + , x: function(x) { + // act as getter + if (x == null) + return this.attr('x') + + // move lines as well if no textPath is present + if (!this.textPath) + this.lines().each(function() { if (this.dom.newLined) this.x(x) }) + + return this.attr('x', x) + } + // Move over y-axis + , y: function(y) { + var oy = this.attr('y') + , 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 (typeof text === 'undefined'){ + var text = '' + var children = this.node.childNodes + for(var i = 0, len = children.length; i < len; ++i){ + + // add newline if its not the first child and newLined is set to true + if(i != 0 && 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 i = 0, il = text.length; i < il; i++) + this.tspan(text[i]).newLine() + } + + // disable build mode and rebuild lines + return this.build(false).rebuild() + } + // Set font size + , size: function(size) { + return this.attr('font-size', size).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() + } + // Get all the first level lines + , lines: function() { + // filter tspans and map them to SVG.js instances + var lines = SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(el){ + return SVG.adopt(el) + }) + + // return an instance of SVG.set + return new SVG.Set(lines) + } + // 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 + , blankLineOffset = 0 + , dy = this.dom.leading * new SVG.Number(this.attr('font-size')) + + this.lines().each(function() { + if (this.dom.newLined) { + if (!this.textPath) + 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.Shape + + // 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 hy¡n + 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 node = (this.textPath && this.textPath() || this).node + , tspan = new SVG.Tspan + + // clear if build mode is disabled + if (this._build === false) + this.clear() + + // add new tspan + node.appendChild(tspan.node) + + return tspan.text(text) + } + // Clear all lines +, clear: function() { + var node = (this.textPath && this.textPath() || this).node + + // remove existing child nodes + while (node.hasChildNodes()) + node.removeChild(node.lastChild) + + return this + } + // Get length of text element +, length: function() { + return this.node.getComputedTextLength() + } +}) diff --git a/node_modules/svgjs/src/textpath.js b/node_modules/svgjs/src/textpath.js new file mode 100644 index 0000000..03dfbee --- /dev/null +++ b/node_modules/svgjs/src/textpath.js @@ -0,0 +1,53 @@ +SVG.TextPath = SVG.invent({ + // Initialize node + create: 'textPath' + + // Inherit from +, inherit: SVG.Element + + // Define parent class +, parent: SVG.Text + + // Add parent method +, construct: { + // Create path for text to run on + path: function(d) { + // create textPath element + var path = new SVG.TextPath + , track = this.doc().defs().path(d) + + // move lines to textpath + while (this.node.hasChildNodes()) + path.node.appendChild(this.node.firstChild) + + // add textPath element as child node + this.node.appendChild(path.node) + + // link textPath to path and add content + path.attr('href', '#' + track, SVG.xlink) + + return this + } + // Plot path if any + , plot: function(d) { + var track = this.track() + + if (track) + track.plot(d) + + return this + } + // Get the path track element + , track: function() { + var path = this.textPath() + + if (path) + return path.reference('href') + } + // Get the textPath child + , textPath: function() { + if (this.node.firstChild && this.node.firstChild.nodeName == 'textPath') + return SVG.adopt(this.node.firstChild) + } + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/transform.js b/node_modules/svgjs/src/transform.js new file mode 100644 index 0000000..0e7a5a0 --- /dev/null +++ b/node_modules/svgjs/src/transform.js @@ -0,0 +1,163 @@ +SVG.extend(SVG.Element, SVG.FX, { + // Add transformations + transform: function(o, relative) { + // get target in case of the fx module, otherwise reference this + var target = this.target || this + , matrix + + // act as a getter + if (typeof o !== 'object') { + // get current matrix + matrix = new SVG.Matrix(target).extract() + + // add parametric rotation + if (typeof this.param === 'object') { + matrix.rotation = this.param.rotation + matrix.cx = this.param.cx + matrix.cy = this.param.cy + } + + return typeof o === 'string' ? matrix[o] : matrix + } + + // get current matrix + matrix = this instanceof SVG.FX && this.attrs.transform ? + this.attrs.transform : + new SVG.Matrix(target) + + // ensure relative flag + relative = !!relative || !!o.relative + + // act on matrix + if (o.a != null) { + matrix = relative ? + // relative + matrix.multiply(new SVG.Matrix(o)) : + // absolute + new SVG.Matrix(o) + + // act on rotation + } else if (o.rotation != null) { + // ensure centre point + ensureCentre(o, target) + + // relativize rotation value + if (relative) { + o.rotation += this.param && this.param.rotation != null ? + this.param.rotation : + matrix.extract().rotation + } + + // store parametric values + this.param = o + + // apply transformation + if (this instanceof SVG.Element) { + matrix = relative ? + // relative + matrix.rotate(o.rotation, o.cx, o.cy) : + // absolute + 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.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 + + if (!relative) { + // absolute; reset skew values + var e = matrix.extract() + matrix = matrix.multiply(new SVG.Matrix().skew(e.skewX, e.skewY, o.cx, o.cy).inverse()) + } + + matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy) + + // act on flip + } else if (o.flip) { + matrix = matrix.flip( + o.flip + , o.offset == null ? target.bbox()['c' + 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(this instanceof SVG.Pattern ? 'patternTransform' : this instanceof SVG.Gradient ? 'gradientTransform' : 'transform', matrix) + } +}) + +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(/\)\s*/).slice(0,-1).map(function(str){ + // generate key => value pairs + var kv = str.trim().split('(') + return [kv[0], kv[1].split(SVG.regex.matrixElements).map(function(str){ return parseFloat(str) })] + }) + // calculate 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 temp = parent.rect(1,1) + var pCtm = temp.screenCTM().inverse() + temp.remove() + + 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()) + } + +}) diff --git a/node_modules/svgjs/src/umd.js b/node_modules/svgjs/src/umd.js new file mode 100644 index 0000000..3ef3ab9 --- /dev/null +++ b/node_modules/svgjs/src/umd.js @@ -0,0 +1,17 @@ +(function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(function(){ + return factory(root, root.document) + }) + } else if (typeof exports === 'object') { + module.exports = root.document ? factory(root, root.document) : function(w){ return factory(w, w.document) } + } else { + root.SVG = factory(root, root.document) + } +}(typeof window !== "undefined" ? window : this, function(window, document) { + +<%= contents %> + +return SVG + +})); \ No newline at end of file diff --git a/node_modules/svgjs/src/ungroup.js b/node_modules/svgjs/src/ungroup.js new file mode 100644 index 0000000..7f26915 --- /dev/null +++ b/node_modules/svgjs/src/ungroup.js @@ -0,0 +1,24 @@ +SVG.extend(SVG.Parent, { + + ungroup: function(parent, depth) { + if(depth === 0 || this instanceof SVG.Defs) return this + + parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent)) + depth = depth || Infinity + + this.each(function(){ + if(this instanceof SVG.Defs) return this + if(this instanceof SVG.Parent) return this.ungroup(parent, depth-1) + return this.toParent(parent) + }) + + this.node.firstChild || this.remove() + + return this + }, + + flatten: function(parent, depth) { + return this.ungroup(parent, depth) + } + +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/use.js b/node_modules/svgjs/src/use.js new file mode 100644 index 0000000..d3150f7 --- /dev/null +++ b/node_modules/svgjs/src/use.js @@ -0,0 +1,24 @@ +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) + } + } +}) \ No newline at end of file diff --git a/node_modules/svgjs/src/utilities.js b/node_modules/svgjs/src/utilities.js new file mode 100644 index 0000000..70495cd --- /dev/null +++ b/node_modules/svgjs/src/utilities.js @@ -0,0 +1,26 @@ +SVG.utils = { + // Map function + map: function(array, block) { + var i + , il = array.length + , result = [] + + for (i = 0; i < il; i++) + result.push(block(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(p) { + return [].filter.call(p, function(el){ return el instanceof SVGElement }) + } + +} \ No newline at end of file diff --git a/node_modules/svgjs/src/viewbox.js b/node_modules/svgjs/src/viewbox.js new file mode 100644 index 0000000..ce9c902 --- /dev/null +++ b/node_modules/svgjs/src/viewbox.js @@ -0,0 +1,63 @@ + +SVG.ViewBox = function(element) { + var x, y, width, height + , wm = 1 // width multiplier + , hm = 1 // height multiplier + , box = element.bbox() + , view = (element.attr('viewBox') || '').match(/-?[\d\.]+/g) + , we = element + , he = element + + // get dimensions of current node + width = new SVG.Number(element.width()) + height = new SVG.Number(element.height()) + + // find nearest non-percentual dimensions + while (width.unit == '%') { + wm *= width.value + width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width()) + we = we.parent() + } + while (height.unit == '%') { + hm *= height.value + height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height()) + he = he.parent() + } + + // ensure defaults + this.x = box.x + this.y = box.y + this.width = width * wm + this.height = height * hm + this.zoom = 1 + + if (view) { + // get width and height from viewbox + x = parseFloat(view[0]) + y = parseFloat(view[1]) + width = parseFloat(view[2]) + height = parseFloat(view[3]) + + // calculate zoom accoring to viewbox + this.zoom = ((this.width / this.height) > (width / height)) ? + this.height / height : + this.width / width + + // calculate real pixel dimensions on parent SVG.Doc element + this.x = x + this.y = y + this.width = width + this.height = height + + } + +} + +// +SVG.extend(SVG.ViewBox, { + // Parse viewbox to string + toString: function() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height + } + +}) \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/.npmignore b/node_modules/synyi-annotation-tool/.npmignore new file mode 100644 index 0000000..869f436 --- /dev/null +++ b/node_modules/synyi-annotation-tool/.npmignore @@ -0,0 +1,10 @@ +*.ts +!*.d.ts +*.js.map +node_modules +src/typings +src/test +typings.json +tslint.json +tsconfig.json +.idea diff --git a/node_modules/synyi-annotation-tool/LICENSE b/node_modules/synyi-annotation-tool/LICENSE new file mode 100644 index 0000000..7ccae3d --- /dev/null +++ b/node_modules/synyi-annotation-tool/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Synyi + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/README.md b/node_modules/synyi-annotation-tool/README.md new file mode 100644 index 0000000..e976f9c --- /dev/null +++ b/node_modules/synyi-annotation-tool/README.md @@ -0,0 +1,7 @@ +# Synyi annotation tool + +Inspired by [brat rapid annotation tool](http://brat.nlplab.org/) + +Powered by Svg.js + TypeScript + System.js + +![screenshot](http://i.v2ex.co/t690JyZS.png) diff --git a/node_modules/synyi-annotation-tool/demo.html b/node_modules/synyi-annotation-tool/demo.html new file mode 100644 index 0000000..cb4843a --- /dev/null +++ b/node_modules/synyi-annotation-tool/demo.html @@ -0,0 +1,18 @@ + + + + + Synyi annotation tool + + +
+
+ + + + + \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/gulpfile.js b/node_modules/synyi-annotation-tool/gulpfile.js new file mode 100644 index 0000000..7b285f7 --- /dev/null +++ b/node_modules/synyi-annotation-tool/gulpfile.js @@ -0,0 +1,16 @@ +var gulp = require('gulp'); +var browserSync = require('browser-sync'); +var reload = browserSync.reload; + +gulp.task('reload', function(){ + reload(); +}); + +gulp.task('serve', function() { + browserSync({ + server: { + baseDir: '.' + } + }); + gulp.watch(['demo.html', 'src/**/*.js'], ['reload']); +}); diff --git a/node_modules/synyi-annotation-tool/package.json b/node_modules/synyi-annotation-tool/package.json new file mode 100644 index 0000000..3d6a18e --- /dev/null +++ b/node_modules/synyi-annotation-tool/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + { + "raw": "synyi-annotation-tool", + "scope": null, + "escapedName": "synyi-annotation-tool", + "name": "synyi-annotation-tool", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "/Users/yjh/web/annotation_viewer" + ] + ], + "_from": "synyi-annotation-tool@latest", + "_id": "synyi-annotation-tool@0.4.14", + "_inCache": true, + "_installable": true, + "_location": "/synyi-annotation-tool", + "_nodeVersion": "5.6.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/synyi-annotation-tool-0.4.14.tgz_1474915324114_0.39467127714306116" + }, + "_npmUser": { + "name": "synyi", + "email": "shen.yanghua@synyi.com" + }, + "_npmVersion": "3.6.0", + "_phantomChildren": {}, + "_requested": { + "raw": "synyi-annotation-tool", + "scope": null, + "escapedName": "synyi-annotation-tool", + "name": "synyi-annotation-tool", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "#USER" + ], + "_resolved": "https://registry.npmjs.org/synyi-annotation-tool/-/synyi-annotation-tool-0.4.14.tgz", + "_shasum": "78db54d05bab156e4a5f442b288da8fc58257686", + "_shrinkwrap": null, + "_spec": "synyi-annotation-tool", + "_where": "/Users/yjh/web/annotation_viewer", + "author": { + "name": "synyi" + }, + "bugs": { + "url": "https://github.com/synyi/annotation-tool/issues" + }, + "dependencies": { + "svgjs": "^2.2.5", + "systemjs": "^0.19.31" + }, + "description": "A svg library for medical history annotation (NLP)", + "devDependencies": { + "browser-sync": "^2.12.4", + "gulp": "^3.9.1", + "gulp-cssnano": "^2.1.1", + "gulp-htmlbuild": "^0.4.1", + "gulp-htmlmin": "^1.3.0", + "gulp-minify-css": "^1.2.3", + "gulp-minify-html": "^1.0.5", + "gulp-rev": "^6.0.1", + "gulp-shell": "^0.5.2", + "gulp-uglify": "^1.5.1", + "gulp-usemin": "^0.3.20", + "typescript": "^1.8.0" + }, + "directories": {}, + "dist": { + "shasum": "78db54d05bab156e4a5f442b288da8fc58257686", + "tarball": "https://registry.npmjs.org/synyi-annotation-tool/-/synyi-annotation-tool-0.4.14.tgz" + }, + "gitHead": "d931a95afd2ce7fb41749ba18de8ab86c81dd904", + "homepage": "https://github.com/synyi/annotation-tool", + "license": "Apache-2.0", + "maintainers": [ + { + "name": "synyi", + "email": "shen.yanghua@synyi.com" + } + ], + "name": "synyi-annotation-tool", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/synyi/annotation-tool.git" + }, + "scripts": { + "build": "gulp", + "tsc:w": "tsc -w" + }, + "version": "0.4.14" +} diff --git a/node_modules/synyi-annotation-tool/src/Annotator.d.ts b/node_modules/synyi-annotation-tool/src/Annotator.d.ts new file mode 100644 index 0000000..c28c541 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/Annotator.d.ts @@ -0,0 +1,106 @@ +/// +import { EventBase } from './lib/util/EventBase'; +export declare enum Categories { + 'sign&symptom' = 1, + 'diagnosis' = 2, + 'assessment' = 3, + 'treatment' = 4, + "index" = 5, + "drug" = 6, + "body location" = 7, + "frequency" = 8, + "value" = 9, + "change" = 10, + "modifier" = 11, + "time" = 12, + "instrument" = 13, + "location" = 14, + "unit" = 15, + "degree" = 16, + "bool" = 17, + "privacy" = 18, + "probability" = 19, +} +export declare class Annotator extends EventBase { + svg: any; + group: {}; + lines: {}; + category: any[]; + labelsSVG: any[]; + linkable: boolean; + underscorable: boolean; + progress: number; + private config; + private draw; + private raw; + private labelLineMap; + private relationLineMap; + private labels; + private background; + private baseTop; + private baseLeft; + private maxWidth; + private labelSelected; + private selectedLabel; + private trackLine; + private _state; + private state; + constructor(container: any, config?: {}); + private init(); + private clear(); + private render(startAt); + loadConfig(config: any): void; + import(raw: String, categories?: any[], labels?: any[], relations?: any[]): void; + dump(): { + labels: any; + relations: any; + }; + refresh(): void; + getConfig(): any; + setVisiblity(component: string, visible: boolean): void; + setStyle(attribute: any, value: any): void; + setConfig(key: string, value: number): void; + exportPNG(scale?: number, filename?: string): void; + resize(width: any, height: any): void; + getLabelById(id: any): { + id: any; + rect: Element; + text: Element; + group: HTMLElement; + highlight: Element; + svg: { + rect: svgjs.Element; + group: svgjs.Element; + highlight: svgjs.Element; + text: svgjs.Element; + }; + }; + getSelectedTextByLabelId(id: any): any; + getRelationById(id: any): { + path: any; + group: Element; + rect: any; + id: any; + svg: { + group: svgjs.Element; + path: svgjs.Element; + rect: svgjs.Element; + }; + }; + addLabel(category: any, selection: any): void; + removeLabel(id: any): void; + setLabelCategoryById(id: any, category: any): void; + addRelation(src: any, dst: any, text: any): void; + removeRelation(id: any): void; + removeRelationsByLabel(labelId: any): void; + clearLabelSelection(): void; + private clickLabelEventHandler(event); + private clickRelationEventHandler(event); + private selectionParagraphEventHandler(); + private mousemoveEventHandler(event); + private moveoverEventHandler(event); + private moveoutEventHandler(event); + private posInLine(x, y); + private requestAnimeFrame(callback); + private transformRelationMeta(); +} diff --git a/node_modules/synyi-annotation-tool/src/Annotator.js b/node_modules/synyi-annotation-tool/src/Annotator.js new file mode 100644 index 0000000..6500e7a --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/Annotator.js @@ -0,0 +1,868 @@ +System.register(['./lib/util/TextSelector', './lib/util/EventBase', './lib/Draw', './lib/components/Paragraph', './lib/components/Label', './lib/util/Util'], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + var TextSelector_1, EventBase_1, Draw_1, Paragraph_1, Label_1, Util_1; + var Categories, States, Annotator, InvalidLabelError; + return { + setters:[ + function (TextSelector_1_1) { + TextSelector_1 = TextSelector_1_1; + }, + function (EventBase_1_1) { + EventBase_1 = EventBase_1_1; + }, + function (Draw_1_1) { + Draw_1 = Draw_1_1; + }, + function (Paragraph_1_1) { + Paragraph_1 = Paragraph_1_1; + }, + function (Label_1_1) { + Label_1 = Label_1_1; + }, + function (Util_1_1) { + Util_1 = Util_1_1; + }], + execute: function() { + (function (Categories) { + Categories[Categories['sign&symptom'] = 1] = 'sign&symptom'; + Categories[Categories['diagnosis'] = 2] = 'diagnosis'; + Categories[Categories['assessment'] = 3] = 'assessment'; + Categories[Categories['treatment'] = 4] = 'treatment'; + Categories[Categories["index"] = 5] = "index"; + Categories[Categories["drug"] = 6] = "drug"; + Categories[Categories["body location"] = 7] = "body location"; + Categories[Categories["frequency"] = 8] = "frequency"; + Categories[Categories["value"] = 9] = "value"; + Categories[Categories["change"] = 10] = "change"; + Categories[Categories["modifier"] = 11] = "modifier"; + Categories[Categories["time"] = 12] = "time"; + Categories[Categories["instrument"] = 13] = "instrument"; + Categories[Categories["location"] = 14] = "location"; + Categories[Categories["unit"] = 15] = "unit"; + Categories[Categories["degree"] = 16] = "degree"; + Categories[Categories["bool"] = 17] = "bool"; + Categories[Categories["privacy"] = 18] = "privacy"; + Categories[Categories["probability"] = 19] = "probability"; + })(Categories || (Categories = {})); + exports_1("Categories", Categories); + (function (States) { + States[States["Init"] = 0] = "Init"; + States[States["Rendering"] = 1] = "Rendering"; + States[States["Interrupted"] = 2] = "Interrupted"; + States[States["Finished"] = 3] = "Finished"; + })(States || (States = {})); + Annotator = (function (_super) { + __extends(Annotator, _super); + function Annotator(container, config) { + var _this = this; + if (config === void 0) { config = {}; } + _super.call(this); + this.group = {}; + this.lines = {}; + this.category = []; + this.labelsSVG = []; + this.linkable = false; + this.underscorable = false; + this.progress = 0; + this.config = { + visible: { + 'relation': true, + 'highlight': true, + 'label': true + }, + style: { + padding: 10, + baseLeft: 30, + rectColor: '', + bgColor: 'white', + width: 0, + height: 0 + }, + puncLen: 80, + linesPerRender: 15, + selectable: false + }; + this.labelLineMap = {}; + this.relationLineMap = {}; + this.background = undefined; + this.baseTop = 0; + this.baseLeft = 0; + this.maxWidth = 0; + this.labelSelected = false; + this.selectedLabel = {}; + this.trackLine = null; + this._state = States.Init; + this.svg = SVG(container); + this.init(); + this.draw = new Draw_1.Draw(this); + this.svg.node.addEventListener('mouseup', function (event) { + if (event.detail >= 2) { + TextSelector_1.TextSelector.clear(); + return; + } + _this.selectionParagraphEventHandler(); + }); + this.svg.node.addEventListener('click', function (event) { + _this.clickLabelEventHandler(event); + _this.clickRelationEventHandler(event); + }); + this.svg.node.addEventListener('mousemove', function (event) { + _this.mousemoveEventHandler(event); + }); + this.svg.node.addEventListener('mouseover', function (event) { + _this.moveoverEventHandler(event); + }); + this.svg.node.addEventListener('mouseout', function (event) { + _this.moveoutEventHandler(event); + }); + this.loadConfig(config); + this.svg.size(this.config.style.width, this.config.style.height); + window['a'] = this; + } + Object.defineProperty(Annotator.prototype, "state", { + get: function () { + return this._state; + }, + set: function (value) { + var name = States[value]; + this.emit('state changed', name); + this.emit("state " + name.toLowerCase()); + this._state = value; + }, + enumerable: true, + configurable: true + }); + Annotator.prototype.init = function () { + this.group = { + shadow: this.svg.group(), + background: this.svg.group(), + relation: this.svg.group(), + highlight: this.svg.group(), + text: this.svg.group(), + annotation: [] + }; + this.lines = { + text: [], + highlight: [], + annotation: this.group['annotation'], + raw: [], + label: [], + relation: [], + relation_meta: [], + top: 0 + }; + this.labelLineMap = {}; + this.relationLineMap = {}; + this.labels = new Label_1.LabelContainer(); + this.progress = 0; + this.raw = ''; + this.state = States.Init; + this.background = this.group['background'].rect(0, 0, this.config.style.width, this.config.style.height).fill('white'); + }; + Annotator.prototype.clear = function () { + this.svg.clear(); + this.init(); + }; + Annotator.prototype.render = function (startAt) { + var _this = this; + this.requestAnimeFrame(function () { + var linesPerRender = _this.config.linesPerRender; + try { + var lines = _this.lines['raw']; + if (_this.state !== States.Rendering || !_this.svg || _this.svg.node.getClientRects().length < 1) { + _this.state = States.Interrupted; + throw new Error('Render is interrupted, maybe svg root element is invisible now.'); + } + var endAt_1 = startAt + linesPerRender > lines.length ? lines.length : startAt + linesPerRender; + if (startAt >= lines.length) { + _this.transformRelationMeta(); + _this.draw.reRelations(); + _this.state = States.Finished; + return; + } + var style = _this.config.style; + for (var i = startAt; i < endAt_1; i++) { + _this.baseTop = style.height; + var text = _this.draw.textline(i + 1, lines[i], _this.baseLeft, _this.baseTop); + var width = Util_1.Util.width(text.node) + _this.baseLeft; + if (width > _this.maxWidth) + _this.maxWidth = width; + _this.lines['text'].push(text); + _this.lines['annotation'].push([]); + _this.lines['highlight'].push([]); + _this.lines['relation'].push([]); + _this.baseTop += style.padding + Util_1.Util.height(text.node); + style.height = _this.baseTop; + if (_this.lines['label'][i]) { + for (var _i = 0, _a = _this.lines['label'][i]; _i < _a.length; _i++) { + var label = _a[_i]; + var raw = _this.lines['raw'][i]; + var j = 0; + var x = label.x, y = label.y; + while (raw[j] == ' ') { + j += 1; + x -= 1; + y -= 1; + } + if (x < 0 || y < 0) + continue; + try { + var startAt_1 = _this.lines['text'][i].node.getExtentOfChar(x); + var endAt_2 = _this.lines['text'][i].node.getExtentOfChar(y); + var selector = { + lineNo: i + 1, + width: endAt_2.x - startAt_1.x + endAt_2.width, + height: startAt_1.height, + left: startAt_1.x, + top: startAt_1.y + }; + _this.draw.label(label.id, label.category, selector); + } + catch (e) { + if (e.name === 'IndexSizeError') { + console.error('Error occured while indexing text line(最可能是标签匹配错位,请联系yjh)'); + if (e.stack) + console.error(e.stack); + } + else { + throw e; + } + } + } + } + if (_this.lines['relation_meta'][i]) { + for (var _b = 0, _c = _this.lines['relation_meta'][i]; _b < _c.length; _b++) { + var relation = _c[_b]; + if (relation.invalid) + continue; + var id = relation.id, src = relation.src, dst = relation.dst, text_1 = relation.text; + try { + _this.draw.relation(id, src, dst, text_1); + } + catch (e) { + console.error(e.message); + if (e.stack) + console.error(e.stack); + } + } + } + } + _this.config.style.width = _this.maxWidth + 100; + _this.resize(_this.maxWidth + 100, _this.config.style.height); + _this.progress = endAt_1 / lines.length; + _this.emit('progress', _this.progress); + setTimeout(function () { + _this.render(endAt_1); + }, 10); + } + catch (e) { + console.error(e.message); + if (e.stack) + console.error(e.stack); + _this.state = States.Interrupted; + } + }); + }; + Annotator.prototype.loadConfig = function (config) { + for (var _i = 0, _a = Object.keys(this.config.style); _i < _a.length; _i++) { + var key = _a[_i]; + if (config[key]) + this.config.style[key] = config[key]; + } + if (config.visible) { + for (var _b = 0, _c = Object.keys(this.config.visible); _b < _c.length; _b++) { + var key = _c[_b]; + if (config.visible[key] !== undefined) + this.config.visible[key] = config.visible[key]; + } + } + if (config.linesPerRender) + this.config.linesPerRender = config.linesPerRender; + if (config.puncLen) + this.config.puncLen = config.puncLen; + if (config.selectable) + this.config.selectable = config.selectable; + }; + Annotator.prototype.import = function (raw, categories, labels, relations) { + if (categories === void 0) { categories = []; } + if (labels === void 0) { labels = []; } + if (relations === void 0) { relations = []; } + if (this.state == States.Rendering) + throw new Error('Can not import data while svg is rendering...'); + this.clear(); + this.category = categories; + this.raw = raw; + var slices = raw.split(/(.*?[\n\r])/g) + .filter(function (value) { return value.length > 0; }) + .map(function (value) { return value.replace('\n', ' '); }); + var lines = []; + for (var _i = 0, labels_1 = labels; _i < labels_1.length; _i++) { + var label = labels_1[_i]; + this.labels.create(label.id, label.category, label.pos); + } + var lineNo = 0; + var basePos = 0; + var loopLimit = 0; + var labelSentinel = 0; + var puncLen = this.config.puncLen; + while (slices.length > 0) { + loopLimit += 1; + if (loopLimit > 100000) { + throw new Error('dead loop!'); + } + var slice = slices.shift(); + if (slice.length < 1) + continue; + if (slice.length > puncLen) { + if (slices.length < 1 && slice.slice(puncLen).length > 0) + slices[0] = slice.slice(puncLen); + else if (slices.length > 0) + slices[0] = slice.slice(puncLen) + slices[0]; + slice = slice.slice(0, puncLen); + } + var truncPos = basePos + slice.length - 1; + while (true) { + if (this.labels.length <= labelSentinel) + break; + var i = labelSentinel; + var truncFlag = false; + while (true) { + var label = this.labels.get(i); + if (label.pos[0] > truncPos) + break; + if (label.isTruncate(truncPos)) { + truncFlag = true; + truncPos = label.pos[0] - 1; + } + i += 1; + if (this.labels.length <= i) + break; + } + if (!truncFlag) { + labelSentinel = i; + break; + } + } + if (slice.length < 1 || truncPos < basePos) + continue; + var truncOffset = truncPos - basePos + 1; + if (slices.length > 0) + slices[0] = slice.slice(truncOffset) + slices[0]; + else if (slice.slice(truncOffset).length > 0) + slices[0] = slice.slice(truncOffset); + slice = slice.slice(0, truncOffset); + lineNo += 1; + basePos += slice.length; + lines.push(slice); + this.lines['raw'].push(slice); + } + this.baseTop = this.config.style.height = 10; + this.baseLeft = this.config.style.baseLeft; + this.maxWidth = 0; + for (var _a = 0, lines_1 = lines; _a < lines_1.length; _a++) { + var line = lines_1[_a]; + this.lines['label'].push([]); + } + for (var _b = 0, labels_2 = labels; _b < labels_2.length; _b++) { + var label = labels_2[_b]; + try { + var _c = this.posInLine(label['pos'][0], label['pos'][1]), x = _c.x, y = _c.y, no = _c.no; + this.lines['label'][no - 1].push({ x: x, y: y, category: label['category'], id: label['id'], pos: label['pos'] }); + this.labelLineMap[label['id']] = no; + } + catch (e) { + if (e instanceof InvalidLabelError) { + console.error(e.message); + this.lines['label'][0].push({ + x: -1, + y: -1, + id: label['id'], + category: label['category'], + pos: label['pos'] + }); + continue; + } + throw e; + } + } + for (var _d = 0, lines_2 = lines; _d < lines_2.length; _d++) { + var line = lines_2[_d]; + this.lines['relation_meta'].push([]); + } + for (var _e = 0, relations_1 = relations; _e < relations_1.length; _e++) { + var relation = relations_1[_e]; + var srcLineNo = this.labelLineMap[relation['src']]; + var dstLineNo = this.labelLineMap[relation['dst']]; + if (typeof srcLineNo == 'number' && typeof dstLineNo == 'number') { + var lineNo_1 = Math.max(srcLineNo, dstLineNo); + var id = relation.id, src = relation.src, dst = relation.dst, text = relation.text; + this.lines['relation_meta'][lineNo_1 - 1].push({ id: id, src: src, dst: dst, text: text }); + } + else { + var id = relation.id, src = relation.src, dst = relation.dst, text = relation.text; + this.lines['relation_mata'][0].push({ + id: id, + src: src, + dst: dst, + text: text, + invalid: false + }); + } + } + this.state = States.Rendering; + this.render(0); + }; + Annotator.prototype.dump = function () { + var labels = this.lines['label'].reduce(function (labels, line) { + for (var _i = 0, line_1 = line; _i < line_1.length; _i++) { + var label = line_1[_i]; + labels.push({ + 'id': label.id, + 'category': label.category, + 'pos': label.pos + }); + } + return labels; + }, []); + var relations = this.lines['relation_meta'].reduce(function (relations, line) { + for (var _i = 0, line_2 = line; _i < line_2.length; _i++) { + var relation = line_2[_i]; + relations.push({ + 'id': relation.id, + 'src': relation.src, + 'dst': relation.dst, + 'text': relation.text + }); + } + return relations; + }, []); + return { labels: labels, relations: relations }; + }; + Annotator.prototype.refresh = function () { + var _a = this.dump(), labels = _a.labels, relations = _a.relations; + if (this.state == States.Rendering) + throw new Error('Refreshing is not allowed in current state'); + this.state = States.Init; + this.import(this.raw, this.category, labels, relations); + }; + Annotator.prototype.getConfig = function () { + return JSON.parse(JSON.stringify(this.config)); + }; + Annotator.prototype.setVisiblity = function (component, visible) { + if (this.config.visible[component] === undefined) + throw new Error("\"" + component + "\" is not a componenet of annotation-tool"); + if (typeof visible !== 'boolean') + throw new Error("\"" + visible + "\" is not boolean"); + this.config.visible[component] = visible; + }; + Annotator.prototype.setStyle = function (attribute, value) { + if (this.config.style[attribute]) + this.config.style[attribute] = value; + else + throw new Error("\"attr " + attribute + "\" is not found."); + }; + Annotator.prototype.setConfig = function (key, value) { + if (this.config[key] && key !== 'style' && key !== 'visibility') + this.config[key] = value; + }; + Annotator.prototype.exportPNG = function (scale, filename) { + if (scale === void 0) { scale = 1; } + if (filename === void 0) { filename = 'export.png'; } + var el = this.svg.node; + var dataUrl = 'data:image/svg+xml;utf-8,' + el.outerHTML; + var img = document.createElement('img'); + var a = document.createElement('a'); + document.body.appendChild(a); + a.setAttribute('style', 'display: none'); + img.onload = function () { + var canvas = document.createElement('canvas'); + canvas.width = scale * img.width; + canvas.height = scale * img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, img.width * scale, img.height * scale); + if (canvas.toBlob) { + canvas.toBlob(function (b) { + var url = URL.createObjectURL(b); + a.setAttribute('href', url); + a.setAttribute('download', filename); + a.click(); + URL.revokeObjectURL(url); + }); + } + else { + var url = canvas.toDataURL(); + window.open(url, '_blank'); + } + }; + img.src = dataUrl; + }; + Annotator.prototype.resize = function (width, height) { + this.svg.size(width, height); + this.background.size(width, height); + }; + Annotator.prototype.getLabelById = function (id) { + var rect = document.querySelector("[data-id=\"label-" + id + "\"]"); + var text = rect.nextElementSibling; + var group = rect.parentElement; + var highlight = document.querySelector("[data-id=\"label-highlight-" + id + "\"]"); + return { + id: id, rect: rect, text: text, group: group, highlight: highlight, + svg: { + rect: SVG.get(rect.id), + group: SVG.get(group.id), + highlight: SVG.get(highlight.id), + text: SVG.get(text.id) + } + }; + }; + Annotator.prototype.getSelectedTextByLabelId = function (id) { + for (var _i = 0, _a = this.lines['label']; _i < _a.length; _i++) { + var line = _a[_i]; + for (var _b = 0, line_3 = line; _b < line_3.length; _b++) { + var label = line_3[_b]; + if (label.id == id) { + return this.raw.slice(label.pos[0], label.pos[1] + 1); + } + } + } + }; + Annotator.prototype.getRelationById = function (id) { + var group = document.querySelector("[data-id=\"relation-" + id + "\"]"); + var path = group.childNodes[0]; + var rect = group.childNodes[1]; + return { + path: path, group: group, rect: rect, id: id, + svg: { + group: SVG.get(group.id), + path: SVG.get(path.id), + rect: SVG.get(rect.id) + } + }; + }; + Annotator.prototype.addLabel = function (category, selection) { + if (!this.config.visible['label']) + return; + var id = this.lines['label'].reduce(function (id, line) { + for (var _i = 0, line_4 = line; _i < line_4.length; _i++) { + var label = line_4[_i]; + id = Math.max(label.id, id); + } + return id; + }, -1) + 1; + var line = selection.line.start; + this.draw.label(id, category, { + lineNo: line, + width: selection.rect.width, + height: selection.rect.height, + top: selection.rect.top, + left: selection.rect.left + }); + this.lines['label'][line - 1].push({ + x: selection.offset.start, + y: selection.offset.end, + pos: [selection.pos.start, selection.pos.end], + category: category, id: id + }); + this.labelLineMap[id] = line; + this.draw.reRelations(line); + }; + Annotator.prototype.removeLabel = function (id) { + var _this = this; + var dom = this.svg.node.querySelector("[data-id=\"label-" + id + "\"]").parentElement; + var highlight = this.svg.node.querySelector("[data-id=\"label-highlight-" + id + "\"]"); + var remove = function (lines, id) { + for (var _i = 0, lines_3 = lines; _i < lines_3.length; _i++) { + var line = lines_3[_i]; + for (var i = 0; i < line.length; i++) { + var tid = -1; + if (line[i] instanceof _this.svg.constructor) + tid = line[i].attr('id'); + else + tid = line[i].id; + if (tid == id) { + line.splice(i, 1); + return; + } + } + } + }; + remove(this.lines['label'], id); + remove(this.lines['highlight'], highlight.id); + remove(this.lines['annotation'], dom.id); + var lineNo = this.labelLineMap[id]; + var _a = this.getLabelById(id).svg, group = _a.group, rect = _a.rect; + var top = group.transform()['y'] + rect.y(); + this.draw.tryMoveLineUp(lineNo); + SVG.get(highlight.id).remove(); + SVG.get(dom.id).remove(); + }; + Annotator.prototype.setLabelCategoryById = function (id, category) { + var lineNo = this.labelLineMap[id]; + if (!lineNo) + throw new Error('Invalid label id'); + var labels = this.lines['label'][lineNo - 1]; + for (var _i = 0, labels_3 = labels; _i < labels_3.length; _i++) { + var label = labels_3[_i]; + if (label.id == id) { + label.category = category; + } + } + this.refresh(); + }; + Annotator.prototype.addRelation = function (src, dst, text) { + if (!this.config.visible['relation']) + return; + var id = Util_1.Util.autoIncrementId(this.lines['relation_meta'], 'id'); + var srcLineNo = this.labelLineMap[src]; + var dstLineNo = this.labelLineMap[dst]; + if (typeof srcLineNo == 'number' && typeof dstLineNo == 'number') { + var lineNo = Math.min(srcLineNo, dstLineNo); + this.relationLineMap[id] = lineNo; + this.lines['relation_meta'][lineNo - 1].push({ id: id, src: src, dst: dst, text: text }); + } + else { + throw new Error("Invalid label number: " + src + ", " + dst + " "); + } + this.draw.relation(id, src, dst, text); + this.draw.reRelations(Math.min(srcLineNo, dstLineNo)); + }; + Annotator.prototype.removeRelation = function (id) { + Util_1.Util.removeInLines(this.lines['relation_meta'], function (item) { + return item.id == id; + }); + Util_1.Util.removeInLines(this.lines['relation'], function (item) { + return item.attr('data-id') == "relation-" + id; + }); + var _a = this.getRelationById(id).svg, group = _a.group, rect = _a.rect; + var top = rect.y() + group.transform()['y']; + var lineNo = this.relationLineMap[id]; + this.draw.tryMoveLineUp(lineNo); + this.getRelationById(id).svg.group.remove(); + }; + Annotator.prototype.removeRelationsByLabel = function (labelId) { + var will_remove = []; + for (var _i = 0, _a = this.lines['relation_meta']; _i < _a.length; _i++) { + var line = _a[_i]; + for (var i = line.length - 1; i >= 0; i--) { + var _b = line[i], id = _b.id, src = _b.src, dst = _b.dst; + if (src == labelId || dst == labelId) { + will_remove.push(id); + line.splice(i, 1); + } + } + } + for (var _c = 0, _d = this.lines['relation']; _c < _d.length; _c++) { + var line = _d[_c]; + for (var i = line.length - 1; i >= 0; i--) { + var id = line[i].attr('data-id').match(/^relation-(\d+)$/)[1]; + if (will_remove.indexOf(+id) >= 0) { + line.splice(i, 1); + } + } + } + for (var _e = 0, will_remove_1 = will_remove; _e < will_remove_1.length; _e++) { + var id = will_remove_1[_e]; + var _f = this.getRelationById(id).svg, group = _f.group, rect = _f.rect; + var top_1 = rect.y() + group.transform()['y']; + var lineNo = this.relationLineMap[id]; + this.draw.tryMoveLineUp(lineNo); + this.getRelationById(id).svg.group.remove(); + } + }; + Annotator.prototype.clearLabelSelection = function () { + this.labelSelected = false; + this.trackLine.remove(); + this.selectedLabel = {}; + }; + Annotator.prototype.clickLabelEventHandler = function (event) { + var target = event.target; + if (!target.parentElement) + return; + var previousElement = target.parentElement.previousElementSibling; + if (target.nodeName == 'tspan' && previousElement && previousElement.nodeName == 'rect') { + var dataId = previousElement.getAttribute('data-id'); + if (dataId) { + var labelId = dataId.match(/^label-(\d+)$/)[1]; + this.labelSelected = !this.labelSelected; + if (!this.labelSelected && this.selectedLabel !== null && this.trackLine) + this.trackLine.remove(); + this.selectedLabel = this.getLabelById(+labelId); + this.emit('selected label', +labelId); + } + } + }; + Annotator.prototype.clickRelationEventHandler = function (event) { + var target = event.target; + if (!target.parentElement) + return; + var grandparentElement = target.parentElement.parentElement; + if (target.nodeName == 'tspan' && grandparentElement && grandparentElement.nodeName == 'g') { + var dataId = grandparentElement.getAttribute('data-id'); + if (dataId) { + var relationId = dataId.match(/^relation-(\d+)$/)[1]; + this.emit('selected relation', +relationId); + } + } + }; + Annotator.prototype.selectionParagraphEventHandler = function () { + try { + var _a = TextSelector_1.TextSelector.paragraph(), startOffset = _a.startOffset, endOffset = _a.endOffset, startLineNo = _a.startLineNo, endLineNo = _a.endLineNo; + endOffset -= 1; + var paragraph = new Paragraph_1.Paragraph(this, startLineNo, startOffset, endLineNo, endOffset); + this.emit('selected', { + pos: { start: paragraph.startPos, end: paragraph.endPos }, + offset: { start: paragraph.startOffset, end: paragraph.endOffset }, + line: { start: startLineNo, end: endLineNo }, + text: paragraph.text, + rect: TextSelector_1.TextSelector.rect() + }); + if (this.underscorable) { + this.draw.underscore(paragraph); + } + } + catch (e) { + if (e instanceof TextSelector_1.SelectorDummyException) + return; + throw e; + } + }; + Annotator.prototype.mousemoveEventHandler = function (event) { + if (this.labelSelected && this.config.selectable) { + var label = this.getLabelById(this.selectedLabel['id']); + var root = this.svg.node.getClientRects()[0]; + var left = event.clientX, top_2 = event.clientY; + this.draw.trackLine(label, left - root.left, top_2 - root.top - 3); + } + }; + Annotator.prototype.moveoverEventHandler = function (event) { + var target = event.target; + if (!target.parentElement) + return; + var previousElement = target.parentElement.previousElementSibling; + var grandparentElement = target.parentElement.parentElement; + if (target.nodeName == 'tspan' && grandparentElement && grandparentElement.nodeName == 'g') { + var dataId = grandparentElement.getAttribute('data-id'); + if (dataId) { + var relationId = dataId.match(/^relation-(\d+)$/)[1]; + var svg = this.getRelationById(relationId).svg; + svg.path.stroke({ width: 2 }); + } + } + if (target.nodeName == 'tspan' && previousElement && previousElement.nodeName == 'rect') { + var dataId = previousElement.getAttribute('data-id'); + if (dataId) { + var labelId = dataId.match(/^label-(\d+)$/)[1]; + for (var _i = 0, _a = this.lines['relation_meta']; _i < _a.length; _i++) { + var line = _a[_i]; + for (var _b = 0, line_5 = line; _b < line_5.length; _b++) { + var relation = line_5[_b]; + var id = relation.id, src = relation.src, dst = relation.dst; + if (src == labelId || dst == labelId) { + var svg = this.getRelationById(id).svg; + svg.path.stroke({ width: 2 }); + } + } + } + } + } + }; + Annotator.prototype.moveoutEventHandler = function (event) { + var target = event.target; + if (!target.parentElement) + return; + var previousElement = target.parentElement.previousElementSibling; + var grandparentElement = target.parentElement.parentElement; + if (target.nodeName == 'tspan' && grandparentElement && grandparentElement.nodeName == 'g') { + var dataId = grandparentElement.getAttribute('data-id'); + if (dataId) { + var relationId = dataId.match(/^relation-(\d+)$/)[1]; + var svg = this.getRelationById(relationId).svg; + svg.path.stroke({ width: 1 }); + } + } + if (target.nodeName == 'tspan' && previousElement && previousElement.nodeName == 'rect') { + var dataId = previousElement.getAttribute('data-id'); + if (dataId) { + var labelId = dataId.match(/^label-(\d+)$/)[1]; + for (var _i = 0, _a = this.lines['relation_meta']; _i < _a.length; _i++) { + var line = _a[_i]; + for (var _b = 0, line_6 = line; _b < line_6.length; _b++) { + var relation = line_6[_b]; + var id = relation.id, src = relation.src, dst = relation.dst; + if (src == labelId || dst == labelId) { + var svg = this.getRelationById(id).svg; + svg.path.stroke({ width: 1 }); + } + } + } + } + } + }; + Annotator.prototype.posInLine = function (x, y) { + var lineNo = 0; + for (var _i = 0, _a = this.lines['raw']; _i < _a.length; _i++) { + var raw = _a[_i]; + lineNo += 1; + if (x - raw.length < 0) + break; + x -= raw.length; + } + for (var _b = 0, _c = this.lines['raw']; _b < _c.length; _b++) { + var raw = _c[_b]; + if (y - raw.length < 0) + break; + y -= raw.length; + } + if (x > y) + throw new InvalidLabelError("Invalid selection, x:" + x + ", y:" + y + ", line no: " + lineNo); + return { x: x, y: y, no: lineNo }; + }; + Annotator.prototype.requestAnimeFrame = function (callback) { + if (window.requestAnimationFrame) + window.requestAnimationFrame(callback); + else + setTimeout(callback, 16); + }; + Annotator.prototype.transformRelationMeta = function () { + var transformedRelationMeta = []; + for (var _i = 0, _a = this.lines['relation_meta']; _i < _a.length; _i++) { + var line = _a[_i]; + transformedRelationMeta.push([]); + for (var _b = 0, line_7 = line; _b < line_7.length; _b++) { + var relation = line_7[_b]; + var id = relation.id, src = relation.src, dst = relation.dst; + var srcLineNo = this.labelLineMap[src]; + var dstLineNo = this.labelLineMap[dst]; + if (typeof srcLineNo == 'number' && typeof dstLineNo == 'number') { + var lineNo = Math.min(srcLineNo, dstLineNo); + transformedRelationMeta[lineNo - 1].push(relation); + this.relationLineMap[id] = lineNo; + } + else { + transformedRelationMeta[0].push(relation); + } + } + } + this.lines['relation_meta'] = transformedRelationMeta; + }; + return Annotator; + }(EventBase_1.EventBase)); + exports_1("Annotator", Annotator); + InvalidLabelError = (function (_super) { + __extends(InvalidLabelError, _super); + function InvalidLabelError(message) { + _super.call(this, message); + this.message = message; + } + return InvalidLabelError; + }(Error)); + } + } +}); +//# sourceMappingURL=Annotator.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/Draw.d.ts b/node_modules/synyi-annotation-tool/src/lib/Draw.d.ts new file mode 100644 index 0000000..ff91054 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/Draw.d.ts @@ -0,0 +1,28 @@ +/// +export declare class Draw { + private board; + private margin; + private lineHeight; + private shoulder; + private needExtend; + private style_user_select_none; + constructor(board: any); + highlight(selector: any, color?: string): any; + textline(lineNo: any, content: any, left: any, top: any): any; + annotation(id: any, cid: any, selector: any): void; + label(id: any, cid: any, selector: any): void; + relation(id: any, srcId: any, dstId: any, text?: string): void; + underscore(paragraph: any): void; + bracket(cid: any, x1: any, y1: any, x2: any, y2: any, width: any, q?: number): any; + trackLine(label: any, left: any, top: any): void; + tryMoveLineUp(lineNo: any): void; + reRelations(lineNo?: number): void; + private moveLineRight(lineNo, padding); + private moveLineVertically(lineNo, type, delta?); + private underscoreLine(lineNo, start, end); + private calcAnnotationTop(text, selector); + private calcRelationTop(lineNo, width, height, top, left); + private isCollisionInLine(lineNo, width, height, left, top); + private isCollision(x1, y1, w1, h1, x2, y2, w2, h2); + private redrawRelations(lineNo); +} diff --git a/node_modules/synyi-annotation-tool/src/lib/Draw.js b/node_modules/synyi-annotation-tool/src/lib/Draw.js new file mode 100644 index 0000000..ecf75bc --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/Draw.js @@ -0,0 +1,412 @@ +System.register(['./util/Util'], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var Util_1; + var Draw; + return { + setters:[ + function (Util_1_1) { + Util_1 = Util_1_1; + }], + execute: function() { + Draw = (function () { + function Draw(board) { + this.margin = 10; + this.lineHeight = 25; + this.shoulder = 20; + this.needExtend = false; + this.style_user_select_none = { + 'style': '-webkit-user-select: none; user-select:none; -khtml-user-select:none;-ms-user-select:none;-moz-user-select:none; cursor: default;' + }; + this.board = board; + } + Draw.prototype.highlight = function (selector, color) { + if (color === void 0) { color = '#e8fbe8'; } + var width = selector.width, height = selector.height, left = selector.left, top = selector.top; + return this.board.group['highlight'].rect(width, height).move(left, top).attr({ fill: color }); + }; + Draw.prototype.textline = function (lineNo, content, left, top) { + return this.board.group['text'].text(content).attr({ 'data-id': "text-line-" + lineNo }).move(left, top).font({ size: 14 }); + }; + Draw.prototype.annotation = function (id, cid, selector) { + this.needExtend = false; + var margin = this.margin; + var lineNo = selector.lineNo; + var content = this.board.category[cid - 1]['text']; + var textDef = this.board.group['shadow'].text(content).size(12); + var width = Util_1.Util.width(textDef.node); + var height = Util_1.Util.height(textDef.node); + var left = selector.left + selector.width / 2 - width / 2 + 2; + var top = this.calcAnnotationTop(textDef, selector); + var text = this.board.svg.text(content).size(12).move(left, top).attr(this.style_user_select_none); + textDef.remove(); + var fillColor = this.board.category[cid - 1]['fill']; + var strokeColor = this.board.category[cid - 1]['boader']; + var rect = this.board.svg.rect(width + 4, height + 4).move(left - 2, top - 2).fill(fillColor).stroke(strokeColor).radius(2).attr({ 'data-id': "label-" + id }); + var annotateGroup = this.board.svg.group(); + var bHeight = margin - 2; + var bTop = top + rect.height() - 2; + var bracket = this.bracket(cid, selector.left, bTop, selector.left + selector.width, bTop, bHeight); + annotateGroup.add(rect); + annotateGroup.add(text); + annotateGroup.add(bracket); + this.board.labelsSVG[id] = { rect: rect, lineNo: lineNo }; + this.board.lines['annotation'][lineNo - 1].push(annotateGroup); + if (this.needExtend || this.board.lines['annotation'][lineNo - 1].length < 2) { + this.tryMoveLineUp(lineNo); + } + if (left < 2) + this.moveLineRight(lineNo, -left + 2); + }; + Draw.prototype.label = function (id, cid, selector) { + if (!this.board.config.visible['label']) + return; + var extendHeight = 0; + var lineNo = selector.lineNo; + var width = selector.width, height = selector.height, left = selector.left, top = selector.top; + if (this.board.config.visible['highlight']) { + var highlight = this.highlight(selector, this.board.category[cid - 1]['highlight']).attr('data-id', "label-highlight-" + id); + this.board.lines['highlight'][lineNo - 1].push(highlight); + } + if (this.board.config.visible['label']) + this.annotation(id, cid, selector); + }; + Draw.prototype.relation = function (id, srcId, dstId, text) { + if (text === void 0) { text = 'body location of'; } + if (!this.board.config.visible['relation']) + return; + this.needExtend = false; + var content = text; + var textDef = this.board.group['shadow'].text(content).size(12); + var width = Util_1.Util.width(textDef.node); + var height = Util_1.Util.height(textDef.node); + var src = this.board.labelsSVG[srcId].rect; + var dst = this.board.labelsSVG[dstId].rect; + var srcLineNo = Math.min(this.board.labelsSVG[dstId].lineNo, this.board.labelsSVG[srcId].lineNo); + var dstLineNo = Math.max(this.board.labelsSVG[dstId].lineNo, this.board.labelsSVG[srcId].lineNo); + var srcX = src.x() + src.parent().transform()['x']; + var srcY = src.y() + src.parent().transform()['y']; + var dstX = dst.x() + dst.parent().transform()['x']; + var dstY = dst.y() + dst.parent().transform()['y']; + var distance = srcX < dstX ? dstX + dst.width() - srcX : srcX + src.width() - dstX; + var left = srcX < dstX ? (srcX + dstX + dst.width() - width) / 2 : (dstX + srcX + src.width() - width) / 2; + var deltaY = srcY < dstY ? 0 : srcY - dstY; + var x0 = srcX < dstX ? srcX : srcX + src.width(); + var y0 = srcY + src.height() / 2; + var shoulder = this.shoulder; + var cx1 = srcX < dstX ? x0 - shoulder : x0 + shoulder; + var top = this.calcRelationTop(srcLineNo, width, height, y0 - (this.margin + height + deltaY), left); + var cy1 = top + height / 2; + var x1 = x0; + var y1 = cy1; + var x2 = srcX < dstX ? dstX + dst.width() + shoulder / 2 : dstX - shoulder / 2; + var cx2 = srcX < dstX ? x2 + shoulder / 2 : x2 - shoulder / 2; + var cy2 = y1; + var x3 = srcX < dstX ? dstX + dst.width() : dstX; + var y3 = dstY - 2; + if (distance < width) { + cx1 = srcX < dstX ? left - shoulder : left + width + shoulder; + x1 = srcX < dstX ? left - shoulder / 2 : left + width + shoulder / 2; + x2 = srcX < dstX ? left + width + shoulder / 2 : left - shoulder / 2; + cx2 = srcX < dstX ? x2 + shoulder / 2 : x2 - shoulder / 2; + } + var group = this.board.group['relation'].group().attr('data-id', "relation-" + id); + var path = group.path("M" + x0 + " " + y0 + "Q" + cx1 + " " + cy1 + " " + x1 + " " + y1 + " H" + x2 + " Q" + cx2 + " " + cy2 + " " + x3 + " " + y3) + .fill('none').stroke({ color: '#000' }); + path.marker('end', 5, 5, function (add) { + add.polyline('0,0 5,2.5 0,5 0.2,2.5'); + }); + group.rect(width + 4, height).move(left - 2, top).fill('#fff'); + group.text(content).size(12).move(left, top).attr(this.style_user_select_none); + textDef.remove(); + this.board.lines['relation'][srcLineNo - 1].push(group); + if (this.needExtend) { + this.tryMoveLineUp(srcLineNo); + this.redrawRelations(srcLineNo); + } + var leftEdge = Math.min(srcX, dstX, x0, x1, x2, x3, cx1, cx2, left); + if (leftEdge < 0) { + var lineNo = Math.min(this.board.labelsSVG[dstId].lineNo, this.board.labelsSVG[srcId].lineNo); + this.moveLineRight(lineNo, -leftEdge); + } + }; + Draw.prototype.underscore = function (paragraph) { + var startLine = paragraph.startLine; + var startOffset = paragraph.startOffset; + var endLine = paragraph.endLine; + var endOffset = paragraph.endOffset; + if (startLine == endOffset) { + this.underscoreLine(startLine, startOffset, -1); + for (var i = startLine + 1; i = endLine - 1; i++) { + this.underscoreLine(i, 0, -1); + } + this.underscoreLine(endLine, 0, endOffset); + } + else { + this.underscoreLine(startLine, startOffset, endOffset); + } + }; + Draw.prototype.bracket = function (cid, x1, y1, x2, y2, width, q) { + if (q === void 0) { q = 0.6; } + var dx = x1 - x2; + var dy = y1 - y2; + var len = Math.sqrt(dx * dx + dy * dy); + dx = dx / len; + dy = dy / len; + var qx1 = x1 + q * width * dy; + var qy1 = y1 - q * width * dx; + var qx2 = (x1 - .25 * len * dx) + (1 - q) * width * dy; + var qy2 = (y1 - .25 * len * dy) - (1 - q) * width * dx; + var tx1 = (x1 - .5 * len * dx) + width * dy; + var ty1 = (y1 - .5 * len * dy) - width * dx; + var qx3 = x2 + q * width * dy; + var qy3 = y2 - q * width * dx; + var qx4 = (x1 - .75 * len * dx) + (1 - q) * width * dy; + var qy4 = (y1 - .75 * len * dy) - (1 - q) * width * dx; + return this.board.svg.path("M" + x1 + "," + y1 + "Q" + qx1 + "," + qy1 + "," + qx2 + "," + qy2 + "T" + tx1 + "," + ty1 + "M" + x2 + "," + y2 + "Q" + qx3 + "," + qy3 + "," + qx4 + "," + qy4 + "T" + tx1 + "," + ty1) + .fill('none').stroke({ color: this.board.category[cid - 1]['boader'], width: 1 }).transform({ rotation: 180 }); + }; + Draw.prototype.trackLine = function (label, left, top) { + var _a = label.svg, group = _a.group, rect = _a.rect; + var src = { + x: group.transform()['x'] + rect.x() + rect.width() / 2, y: group.transform()['y'] + rect.y() + }; + var dst = { x: left, y: top }; + if (this.board.trackLine !== null) + this.board.trackLine.remove(); + var dx = (src.x - dst.x) / 4; + var y2 = Math.min(src.y, dst.y) - rect.height(); + this.board.trackLine = this.board.svg.path("M" + src.x + "," + src.y + "C" + (src.x - dx) + "," + y2 + "," + (dst.x + dx) + "," + y2 + "," + dst.x + "," + dst.y) + .fill('none').stroke({ color: 'black', width: 1 }); + this.board.trackLine.marker('end', 5, 5, function (add) { + add.polyline('0,0 5,2.5 0,5 0.2,2.5'); + }); + }; + Draw.prototype.tryMoveLineUp = function (lineNo) { + var textline = this.board.lines['text'][lineNo - 1]; + var annotations = this.board.lines['annotation'][lineNo - 1]; + var relations = this.board.lines['relation'][lineNo - 1]; + var padding = this.board.config.style.padding; + var top = lineNo - 2 >= 0 ? this.board.lines['text'][lineNo - 2].y() + + Util_1.Util.height(this.board.lines['text'][lineNo - 2].node) + padding : padding; + var upper = Math.min(10000000, textline.y()); + var loop = function (groups) { + if (!groups) + return; + for (var _i = 0, groups_1 = groups; _i < groups_1.length; _i++) { + var group = groups_1[_i]; + for (var _a = 0, _b = group.children(); _a < _b.length; _a++) { + var element = _b[_a]; + upper = Math.min(element.y() + group.transform()['y'], upper); + } + } + }; + loop(annotations); + loop(relations); + var delta = upper - top; + this.moveLineVertically(lineNo, 'up', -delta); + }; + Draw.prototype.reRelations = function (lineNo) { + if (lineNo === void 0) { lineNo = -1; } + for (var _i = 0, _a = this.board.lines['relation_meta']; _i < _a.length; _i++) { + var relations = _a[_i]; + for (var _b = 0, relations_1 = relations; _b < relations_1.length; _b++) { + var relation = relations_1[_b]; + var id = relation.id, src = relation.src, dst = relation.dst; + var srcLineNo = this.board.labelLineMap[relation['src']]; + var dstLineNo = this.board.labelLineMap[relation['dst']]; + if (srcLineNo < 0 || dstLineNo < 0 || srcLineNo == dstLineNo) + continue; + if (lineNo == -1 || (lineNo > Math.min(srcLineNo, dstLineNo) && lineNo <= Math.max(srcLineNo, dstLineNo))) { + var relationGroup = this.board.getRelationById(id).svg.group; + var _c = this.board.getLabelById(src).svg, srcLabelGroup = _c.group, srcLabelRect = _c.rect; + var _d = this.board.getLabelById(dst).svg, dstLabelGroup = _d.group, dstLabelRect = _d.rect; + var path = relationGroup.first(); + var pointArr = path.array(); + if (dstLineNo > srcLineNo) { + pointArr.value[3][4] = dstLabelRect.y() + dstLabelGroup.transform()['y'] - relationGroup.transform()['y']; + } + else if (srcLineNo > dstLineNo) { + pointArr.value[0][2] = srcLabelRect.y() + srcLabelRect.height() / 2 + srcLabelGroup.transform()['y'] + - relationGroup.transform()['y']; + } + path.plot(pointArr.toString()); + } + } + } + }; + Draw.prototype.moveLineRight = function (lineNo, padding) { + var textline = this.board.lines['text'][lineNo - 1]; + var highlights = this.board.lines['highlight'][lineNo - 1]; + var annotations = this.board.lines['annotation'][lineNo - 1]; + var relations = this.board.lines['relation'][lineNo - 1]; + textline.dx(padding); + var maxWidth = textline.x(); + if (highlights) { + for (var _i = 0, highlights_1 = highlights; _i < highlights_1.length; _i++) { + var highlight = highlights_1[_i]; + highlight.dx(padding); + if (maxWidth < highlight.x()) + maxWidth = highlight.x(); + } + } + if (annotations) { + for (var _a = 0, annotations_1 = annotations; _a < annotations_1.length; _a++) { + var annotation = annotations_1[_a]; + var x = annotation.transform().x; + annotation.transform({ x: x + padding }); + maxWidth = Math.max(annotation.x() + annotation.transform()['x'], maxWidth); + } + } + if (relations) { + for (var _b = 0, relations_2 = relations; _b < relations_2.length; _b++) { + var relation = relations_2[_b]; + var x = relation.transform().x; + relation.transform({ x: x + padding }); + maxWidth = Math.max(relation.x() + relation.transform()['x'], maxWidth); + } + } + if (maxWidth > this.board.config.style.width) { + this.board.config.style.width = maxWidth; + this.board.svg.size(this.board.config.style.width, this.board.config.style.height); + } + }; + Draw.prototype.moveLineVertically = function (lineNo, type, delta) { + if (delta === void 0) { delta = 0; } + var s = lineNo - 1; + var textlines = this.board.lines['text']; + var highlights = this.board.lines['highlight']; + var annotations = this.board.lines['annotation']; + var relations = this.board.lines['relation']; + var lineHeight = type.indexOf('label') >= 0 ? this.lineHeight : this.lineHeight * 2 / 3; + if (delta !== 0) + lineHeight = delta; + for (var i = s; i < textlines.length; i++) { + textlines[i].dy(lineHeight); + if (highlights[i]) { + for (var _i = 0, _a = highlights[i]; _i < _a.length; _i++) { + var highlight = _a[_i]; + highlight.dy(lineHeight); + } + } + if (annotations[i]) { + for (var _b = 0, _c = annotations[i]; _b < _c.length; _b++) { + var annotation = _c[_b]; + var y = annotation.transform().y; + annotation.transform({ y: y + lineHeight }); + } + } + if (relations[i]) { + for (var _d = 0, _e = relations[i]; _d < _e.length; _d++) { + var relation = _e[_d]; + var y = relation.transform().y; + relation.transform({ y: y + lineHeight }); + } + } + } + this.board.config.style.height += lineHeight; + this.board.resize(this.board.config.style.width, this.board.config.style.height); + return lineHeight; + }; + Draw.prototype.underscoreLine = function (lineNo, start, end) { + if (end == -1) { + end = this.board.lines['raw'][lineNo - 1].length - 1; + } + var textLine = this.board.lines['text'][lineNo - 1]; + }; + Draw.prototype.calcAnnotationTop = function (text, selector) { + var lineNo = selector.lineNo; + var width = Util_1.Util.width(text.node); + var height = Util_1.Util.height(text.node); + var left = selector.left + selector.width / 2 - width / 2; + var top = selector.top - this.margin - height; + while (this.isCollisionInLine(lineNo, width + 4, height + 4, left - 2, top + 2)) { + top -= this.lineHeight; + } + return top; + }; + Draw.prototype.calcRelationTop = function (lineNo, width, height, top, left) { + while (this.isCollisionInLine(lineNo, width + 10, height + 10, left - 5, top)) { + top -= this.lineHeight / 2; + } + return top; + }; + Draw.prototype.isCollisionInLine = function (lineNo, width, height, left, top) { + var _this = this; + var annotations = this.board.lines['annotation'][lineNo - 1]; + var relations = this.board.lines['relation'][lineNo - 1]; + if (annotations.length < 1 && relations.length < 1) { + return false; + } + var minY = 100000000; + var testCollision = function (elements) { + for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) { + var element = elements_1[_i]; + var y = element.y() + element.parent().transform()['y']; + if (element.type == 'rect') { + if (minY > y) { + minY = y; + } + if (_this.isCollision(left, top, width, height, element.x(), y, element.width(), element.height())) { + return true; + } + } + } + return false; + }; + for (var _i = 0, annotations_2 = annotations; _i < annotations_2.length; _i++) { + var annotaion = annotations_2[_i]; + var elements = annotaion.children(); + if (testCollision(elements)) + return true; + } + for (var _a = 0, relations_3 = relations; _a < relations_3.length; _a++) { + var relation = relations_3[_a]; + var elements = relation.children(); + if (testCollision(elements)) + return true; + } + if (top < minY - 2) { + this.needExtend = true; + } + return false; + }; + Draw.prototype.isCollision = function (x1, y1, w1, h1, x2, y2, w2, h2) { + if (x1 >= x2 && x1 >= x2 + w2) { + return false; + } + else if (x1 <= x2 && x1 + w1 <= x2) { + return false; + } + else if (y1 >= y2 && y1 >= y2 + h2) { + return false; + } + else if (y1 <= y2 && y1 + h1 <= y2) { + return false; + } + return true; + }; + Draw.prototype.redrawRelations = function (lineNo) { + for (var i = 0; i < lineNo - 1; i++) { + for (var _i = 0, _a = this.board.lines['relation_meta'][i]; _i < _a.length; _i++) { + var relation = _a[_i]; + var id = relation.id, src = relation.src, dst = relation.dst; + var srcLineNo = this.board.labelLineMap[relation['src']]; + var dstLineNo = this.board.labelLineMap[relation['dst']]; + if (Math.max(srcLineNo, dstLineNo) >= lineNo) { + var group = this.board.getRelationById(id).svg.group; + var path = group.first(); + var pointArr = path.array(); + pointArr.value[3][4] += this.lineHeight * 2 / 3; + path.plot(pointArr.toString()); + } + } + } + }; + return Draw; + }()); + exports_1("Draw", Draw); + } + } +}); +//# sourceMappingURL=Draw.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Label.d.ts b/node_modules/synyi-annotation-tool/src/lib/components/Label.d.ts new file mode 100644 index 0000000..335d534 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Label.d.ts @@ -0,0 +1,18 @@ +export declare class Label { + id: any; + category: any; + pos: number[]; + lineNo: any; + constructor(id: any, category: any, pos: any); + isTruncate(pos: any): boolean; +} +export declare class LabelContainer { + private labels; + private lineMap; + create(id: any, category: any, pos: any): void; + push(label: Label): void; + get(id: any): any; + readonly length: number; + gen(label: any): any[]; + private insert(target); +} diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Label.js b/node_modules/synyi-annotation-tool/src/lib/components/Label.js new file mode 100644 index 0000000..714762f --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Label.js @@ -0,0 +1,61 @@ +System.register([], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var Label, LabelContainer; + return { + setters:[], + execute: function() { + Label = (function () { + function Label(id, category, pos) { + this.pos = [0, 0]; + this.id = id; + this.category = category; + this.pos[0] = pos[0]; + this.pos[1] = pos[1]; + } + Label.prototype.isTruncate = function (pos) { + return (this.pos[0] <= pos && this.pos[1] > pos); + }; + return Label; + }()); + exports_1("Label", Label); + LabelContainer = (function () { + function LabelContainer() { + this.labels = []; + this.lineMap = {}; + } + LabelContainer.prototype.create = function (id, category, pos) { + this.insert(new Label(id, category, pos)); + }; + LabelContainer.prototype.push = function (label) { + this.insert(label); + }; + LabelContainer.prototype.get = function (id) { + return this.labels[id]; + }; + Object.defineProperty(LabelContainer.prototype, "length", { + get: function () { + return this.labels.length; + }, + enumerable: true, + configurable: true + }); + LabelContainer.prototype.gen = function (label) { + return this.labels; + }; + LabelContainer.prototype.insert = function (target) { + var i = 0; + for (var _i = 0, _a = this.labels; _i < _a.length; _i++) { + var label = _a[_i]; + if (label.pos[0] < target.pos[0]) + i += 1; + } + this.labels.splice(i, 0, target); + }; + return LabelContainer; + }()); + exports_1("LabelContainer", LabelContainer); + } + } +}); +//# sourceMappingURL=Label.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Line.d.ts b/node_modules/synyi-annotation-tool/src/lib/components/Line.d.ts new file mode 100644 index 0000000..6be7b8d --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Line.d.ts @@ -0,0 +1,7 @@ +/// +export declare class Line { + svg: any; + constructor(id: any, width: any, height: any); + group(): void; + extend(lineNo: any): void; +} diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Line.js b/node_modules/synyi-annotation-tool/src/lib/components/Line.js new file mode 100644 index 0000000..2a59065 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Line.js @@ -0,0 +1,22 @@ +System.register([], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var Line; + return { + setters:[], + execute: function() { + Line = (function () { + function Line(id, width, height) { + this.svg = SVG(id).size(width, height); + } + Line.prototype.group = function () { + }; + Line.prototype.extend = function (lineNo) { + }; + return Line; + }()); + exports_1("Line", Line); + } + } +}); +//# sourceMappingURL=Line.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.d.ts b/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.d.ts new file mode 100644 index 0000000..d3e974b --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.d.ts @@ -0,0 +1,12 @@ +export declare class Paragraph { + startLine: any; + endLine: any; + startOffset: any; + endOffset: any; + startPos: any; + endPos: any; + text: any; + private context; + constructor(context: any, startLine: any, startOffset: any, endLine: any, endOffset: any); + calcPos(lineNo: any, offset: any): number; +} diff --git a/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.js b/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.js new file mode 100644 index 0000000..2b20015 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/components/Paragraph.js @@ -0,0 +1,33 @@ +System.register([], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var Paragraph; + return { + setters:[], + execute: function() { + Paragraph = (function () { + function Paragraph(context, startLine, startOffset, endLine, endOffset) { + this.context = context; + this.startLine = startLine; + this.endLine = endLine; + this.startOffset = startOffset; + this.endOffset = endOffset; + this.startPos = this.calcPos(startLine, startOffset); + this.endPos = this.calcPos(endLine, endOffset); + this.text = this.context.raw.slice(this.startPos, this.endPos + 1); + } + Paragraph.prototype.calcPos = function (lineNo, offset) { + var pos = 0; + for (var i = 0; i < lineNo - 1; i++) { + pos += this.context.lines['raw'][i].length; + } + pos += offset; + return pos; + }; + return Paragraph; + }()); + exports_1("Paragraph", Paragraph); + } + } +}); +//# sourceMappingURL=Paragraph.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/util/EventBase.d.ts b/node_modules/synyi-annotation-tool/src/lib/util/EventBase.d.ts new file mode 100644 index 0000000..af36f36 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/EventBase.d.ts @@ -0,0 +1,8 @@ +export declare class EventBase { + private listeners; + emit(event: string, args?: any): boolean; + on(event: string, listener: (target: EventBase, args?: any) => any): number; + private off(event); + offById(event: string, id: number): void; + offAll(): void; +} diff --git a/node_modules/synyi-annotation-tool/src/lib/util/EventBase.js b/node_modules/synyi-annotation-tool/src/lib/util/EventBase.js new file mode 100644 index 0000000..fc6abcb --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/EventBase.js @@ -0,0 +1,52 @@ +System.register([], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var EventBase; + return { + setters:[], + execute: function() { + EventBase = (function () { + function EventBase() { + this.listeners = {}; + } + EventBase.prototype.emit = function (event, args) { + if (!this.listeners[event]) { + return false; + } + for (var _i = 0, _a = this.listeners[event]; _i < _a.length; _i++) { + var l = _a[_i]; + l.listener(this, args); + return true; + } + return false; + }; + EventBase.prototype.on = function (event, listener) { + if (!this.listeners[event]) { + this.listeners[event] = []; + } + var id = Math.random(); + this.listeners[event].push({ listener: listener, id: id }); + return id; + }; + EventBase.prototype.off = function (event) { + this.listeners[event] = []; + }; + EventBase.prototype.offById = function (event, id) { + var list = this.listeners[event]; + for (var i = 0; i < list.length; i++) { + if (list[i].id == id) { + list.splice(i, 1); + return; + } + } + }; + EventBase.prototype.offAll = function () { + this.listeners = {}; + }; + return EventBase; + }()); + exports_1("EventBase", EventBase); + } + } +}); +//# sourceMappingURL=EventBase.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.d.ts b/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.d.ts new file mode 100644 index 0000000..a8c1d99 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.d.ts @@ -0,0 +1,27 @@ +/// +export declare class TextSelector { + static rect(): { + width: number; + height: number; + left: number; + top: number; + }; + static lineNo(): number; + static init(): { + startOffset: number; + endOffset: number; + startNode: Node; + endNode: Node; + tspan: SVGTextContentElement; + }; + static paragraph(): { + startOffset: number; + endOffset: number; + startLineNo: number; + endLineNo: number; + }; + static clear(): void; +} +export declare class SelectorDummyException extends Error { + constructor(message: any); +} diff --git a/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.js b/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.js new file mode 100644 index 0000000..6e91d3f --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/TextSelector.js @@ -0,0 +1,134 @@ +System.register([], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + var TextSelector, SelectorDummyException; + return { + setters:[], + execute: function() { + TextSelector = (function () { + function TextSelector() { + } + TextSelector.rect = function () { + var _a = this.init(), startOffset = _a.startOffset, endOffset = _a.endOffset, tspan = _a.tspan; + var text = tspan.textContent; + var i = 0; + while (text[i] == ' ') { + startOffset -= 1; + endOffset -= 1; + i += 1; + } + var startAt = tspan.getExtentOfChar(startOffset); + var endAt = tspan.getExtentOfChar(endOffset - 1); + return { + width: endAt.x - startAt.x + endAt.width, + height: endAt.height, + left: startAt.x, + top: startAt.y + }; + }; + TextSelector.lineNo = function () { + var tspan = this.init().tspan; + var text = tspan.parentElement; + var num = +text.getAttribute('data-id').match(/^text-line-(\d+)$/)[1]; + return num; + }; + TextSelector.init = function () { + var selection = window.getSelection(); + var anchorOffset = selection.anchorOffset; + var focusOffset = selection.focusOffset; + if (anchorOffset == focusOffset || selection.anchorNode !== selection.focusNode) { + throw new SelectorDummyException('Void selection.'); + } + if (anchorOffset > focusOffset) { + _a = [focusOffset, anchorOffset], anchorOffset = _a[0], focusOffset = _a[1]; + } + var tspan = selection.anchorNode.parentElement; + var text = tspan.textContent; + while (text[anchorOffset] == ' ') { + anchorOffset += 1; + } + while (text[focusOffset - 1] == ' ') { + focusOffset -= 1; + } + if (anchorOffset >= text.length || focusOffset <= 0 || anchorOffset >= focusOffset) { + throw new SelectorDummyException('Void selection.'); + } + return { + startOffset: anchorOffset, + endOffset: focusOffset, + startNode: selection.anchorNode, + endNode: selection.focusNode, + tspan: tspan + }; + var _a; + }; + TextSelector.paragraph = function () { + var selection = window.getSelection(); + var startOffset = selection.anchorOffset; + var endOffset = selection.focusOffset; + var startNode = selection.anchorNode; + var endNode = selection.focusNode; + if (!startNode || !startNode.parentElement || !startNode.parentElement.parentElement + || !endNode || !endNode.parentElement || !endNode.parentElement.parentElement) + throw new SelectorDummyException('Invalid target element'); + var startText = startNode.parentElement.parentElement; + var endText = endNode.parentElement.parentElement; + var startDataId = startText.getAttribute('data-id'); + var endDataId = endText.getAttribute('data-id'); + if (endDataId === null || startDataId === null) { + throw new SelectorDummyException('Void selection'); + } + var startLineNo = +startDataId.match(/^text-line-(\d+)$/)[1]; + var endLineNo = +endDataId.match(/^text-line-(\d+)$/)[1]; + if (startLineNo == endLineNo && startOffset == endOffset) + throw new SelectorDummyException('Void selection'); + if (startLineNo > endLineNo || (startLineNo == endLineNo && startOffset >= endOffset)) { + _a = [endNode, startNode], startNode = _a[0], endNode = _a[1]; + _b = [endOffset, startOffset], startOffset = _b[0], endOffset = _b[1]; + _c = [endText, startText], startText = _c[0], endText = _c[1]; + _d = [endLineNo, startLineNo], startLineNo = _d[0], endLineNo = _d[1]; + } + var startTextContent = startNode.parentElement.textContent; + var endTextContent = endNode.parentElement.textContent; + while (startTextContent[startOffset] == ' ') { + startOffset += 1; + } + while (endTextContent[endOffset - 1] == ' ') { + endOffset -= 1; + } + if (startOffset >= startTextContent.length || endOffset <= 0 || startOffset >= endOffset) { + throw new SelectorDummyException('Void selection.'); + } + return { + startOffset: startOffset, + endOffset: endOffset, + startLineNo: startLineNo, + endLineNo: endLineNo + }; + var _a, _b, _c, _d; + }; + TextSelector.clear = function () { + var selection = window.getSelection(); + selection.removeAllRanges(); + }; + return TextSelector; + }()); + exports_1("TextSelector", TextSelector); + SelectorDummyException = (function (_super) { + __extends(SelectorDummyException, _super); + function SelectorDummyException(message) { + _super.call(this, message); + this.message = message; + } + return SelectorDummyException; + }(Error)); + exports_1("SelectorDummyException", SelectorDummyException); + } + } +}); +//# sourceMappingURL=TextSelector.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/src/lib/util/Util.d.ts b/node_modules/synyi-annotation-tool/src/lib/util/Util.d.ts new file mode 100644 index 0000000..cc1aefd --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/Util.d.ts @@ -0,0 +1,8 @@ +export declare class Util { + static height(node: any): any; + static width(node: any): any; + static top(node: any): any; + static left(node: any): any; + static autoIncrementId(lines: any, key: any): number; + static removeInLines(lines: any, callback: any): boolean; +} diff --git a/node_modules/synyi-annotation-tool/src/lib/util/Util.js b/node_modules/synyi-annotation-tool/src/lib/util/Util.js new file mode 100644 index 0000000..7fbc7e7 --- /dev/null +++ b/node_modules/synyi-annotation-tool/src/lib/util/Util.js @@ -0,0 +1,53 @@ +System.register([], function(exports_1, context_1) { + 'use strict'; + var __moduleName = context_1 && context_1.id; + var Util; + return { + setters:[], + execute: function() { + Util = (function () { + function Util() { + } + Util.height = function (node) { + return node.clientHeight || node.getBoundingClientRect().height || node.getBBox().height; + }; + Util.width = function (node) { + return node.clientWidth || node.getBoundingClientRect().width || node.getBBox().width; + }; + Util.top = function (node) { + return node.clientTop || node.getBoundingClientRect().top || node.getBBox().y; + }; + Util.left = function (node) { + return node.clientLeft || node.getBoundingClientRect().left || node.getBBox().x; + }; + Util.autoIncrementId = function (lines, key) { + var max = -1; + for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { + var line = lines_1[_i]; + for (var _a = 0, line_1 = line; _a < line_1.length; _a++) { + var item = line_1[_a]; + if (item[key] > max) + max = item[key]; + } + } + return max + 1; + }; + Util.removeInLines = function (lines, callback) { + for (var _i = 0, lines_2 = lines; _i < lines_2.length; _i++) { + var line = lines_2[_i]; + for (var i = 0; i < line.length; i++) { + if (callback(line[i])) { + line.splice(i, 1); + return true; + } + } + } + return false; + }; + return Util; + }()); + exports_1("Util", Util); + } + } +}); +//# sourceMappingURL=Util.js.map \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/typings/globals/es6-shim/index.d.ts b/node_modules/synyi-annotation-tool/typings/globals/es6-shim/index.d.ts new file mode 100644 index 0000000..1be23ee --- /dev/null +++ b/node_modules/synyi-annotation-tool/typings/globals/es6-shim/index.d.ts @@ -0,0 +1,666 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/9807d9b701f58be068cb07833d2b24235351d052/es6-shim/es6-shim.d.ts +declare type PropertyKey = string | number | symbol; + +interface IteratorResult { + done: boolean; + value?: T; +} + +interface IterableShim { + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): Iterator; +} + +interface Iterator { + next(value?: any): IteratorResult; + return?(value?: any): IteratorResult; + throw?(e?: any): IteratorResult; +} + +interface IterableIteratorShim extends IterableShim, Iterator { + /** + * Shim for an ES6 iterable iterator. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface StringConstructor { + /** + * Return the String value whose elements are, in order, the elements in the List elements. + * If length is 0, the empty string is returned. + */ + fromCodePoint(...codePoints: number[]): string; + + /** + * String.raw is intended for use as a tag function of a Tagged Template String. When called + * as such the first argument will be a well formed template call site object and the rest + * parameter will contain the substitution values. + * @param template A well-formed template string call site representation. + * @param substitutions A set of substitution values. + */ + raw(template: TemplateStringsArray, ...substitutions: any[]): string; +} + +interface String { + /** + * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point + * value of the UTF-16 encoded code point starting at the string element at position pos in + * the String resulting from converting this object to a String. + * If there is no element at that position, the result is undefined. + * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. + */ + codePointAt(pos: number): number; + + /** + * Returns true if searchString appears as a substring of the result of converting this + * object to a String, at one or more positions that are + * greater than or equal to position; otherwise, returns false. + * @param searchString search string + * @param position If position is undefined, 0 is assumed, so as to search all of the String. + */ + includes(searchString: string, position?: number): boolean; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * endPosition – length(this). Otherwise returns false. + */ + endsWith(searchString: string, endPosition?: number): boolean; + + /** + * Returns a String value that is made from count copies appended together. If count is 0, + * T is the empty String is returned. + * @param count number of copies to append + */ + repeat(count: number): string; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * position. Otherwise returns false. + */ + startsWith(searchString: string, position?: number): boolean; + + /** + * Returns an
HTML anchor element and sets the name attribute to the text value + * @param name + */ + anchor(name: string): string; + + /** Returns a HTML element */ + big(): string; + + /** Returns a HTML element */ + blink(): string; + + /** Returns a HTML element */ + bold(): string; + + /** Returns a HTML element */ + fixed(): string + + /** Returns a HTML element and sets the color attribute value */ + fontcolor(color: string): string + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: number): string; + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: string): string; + + /** Returns an HTML element */ + italics(): string; + + /** Returns an HTML element and sets the href attribute value */ + link(url: string): string; + + /** Returns a HTML element */ + small(): string; + + /** Returns a HTML element */ + strike(): string; + + /** Returns a HTML element */ + sub(): string; + + /** Returns a HTML element */ + sup(): string; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface ArrayConstructor { + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(iterable: IterableShim, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + */ + from(arrayLike: ArrayLike): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + */ + from(iterable: IterableShim): Array; + + /** + * Returns a new array from a set of elements. + * @param items A set of elements to include in the new array object. + */ + of(...items: T[]): Array; +} + +interface Array { + /** + * Returns the value of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T; + + /** + * Returns the index of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + + /** + * Returns the this object after filling the section identified by start and end with value + * @param value value to fill array section with + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as + * length+end. + */ + fill(value: T, start?: number, end?: number): T[]; + + /** + * Returns the this object after copying a section of the array identified by start and end + * to the same array starting at position target + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it + * is treated as length+end. + * @param end If not specified, length of the this object is used as its default value. + */ + copyWithin(target: number, start: number, end?: number): T[]; + + /** + * Returns an array of key, value pairs for every entry in the array + */ + entries(): IterableIteratorShim<[number, T]>; + + /** + * Returns an list of keys in the array + */ + keys(): IterableIteratorShim; + + /** + * Returns an list of values in the array + */ + values(): IterableIteratorShim; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface NumberConstructor { + /** + * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 + * that is representable as a Number value, which is approximately: + * 2.2204460492503130808472633361816 x 10‍−‍16. + */ + EPSILON: number; + + /** + * Returns true if passed value is finite. + * Unlike the global isFininte, Number.isFinite doesn't forcibly convert the parameter to a + * number. Only finite values of the type number, result in true. + * @param number A numeric value. + */ + isFinite(number: number): boolean; + + /** + * Returns true if the value passed is an integer, false otherwise. + * @param number A numeric value. + */ + isInteger(number: number): boolean; + + /** + * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a + * number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter + * to a number. Only values of the type number, that are also NaN, result in true. + * @param number A numeric value. + */ + isNaN(number: number): boolean; + + /** + * Returns true if the value passed is a safe integer. + * @param number A numeric value. + */ + isSafeInteger(number: number): boolean; + + /** + * The value of the largest integer n such that n and n + 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 − 1. + */ + MAX_SAFE_INTEGER: number; + + /** + * The value of the smallest integer n such that n and n − 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)). + */ + MIN_SAFE_INTEGER: number; + + /** + * Converts a string to a floating-point number. + * @param string A string that contains a floating-point number. + */ + parseFloat(string: string): number; + + /** + * Converts A string to an integer. + * @param s A string to convert into a number. + * @param radix A value between 2 and 36 that specifies the base of the number in numString. + * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. + * All other strings are considered decimal. + */ + parseInt(string: string, radix?: number): number; +} + +interface ObjectConstructor { + /** + * Copy the values of all of the enumerable own properties from one or more source objects to a + * target object. Returns the target object. + * @param target The target object to copy to. + * @param sources One or more source objects to copy properties from. + */ + assign(target: any, ...sources: any[]): any; + + /** + * Returns true if the values are the same value, false otherwise. + * @param value1 The first value. + * @param value2 The second value. + */ + is(value1: any, value2: any): boolean; + + /** + * Sets the prototype of a specified object o to object proto or null. Returns the object o. + * @param o The object to change its prototype. + * @param proto The value of the new prototype or null. + * @remarks Requires `__proto__` support. + */ + setPrototypeOf(o: any, proto: any): any; +} + +interface RegExp { + /** + * Returns a string indicating the flags of the regular expression in question. This field is read-only. + * The characters in this string are sequenced and concatenated in the following order: + * + * - "g" for global + * - "i" for ignoreCase + * - "m" for multiline + * - "u" for unicode + * - "y" for sticky + * + * If no flags are set, the value is the empty string. + */ + flags: string; +} + +interface Math { + /** + * Returns the number of leading zero bits in the 32-bit binary representation of a number. + * @param x A numeric expression. + */ + clz32(x: number): number; + + /** + * Returns the result of 32-bit multiplication of two numbers. + * @param x First number + * @param y Second number + */ + imul(x: number, y: number): number; + + /** + * Returns the sign of the x, indicating whether x is positive, negative or zero. + * @param x The numeric expression to test + */ + sign(x: number): number; + + /** + * Returns the base 10 logarithm of a number. + * @param x A numeric expression. + */ + log10(x: number): number; + + /** + * Returns the base 2 logarithm of a number. + * @param x A numeric expression. + */ + log2(x: number): number; + + /** + * Returns the natural logarithm of 1 + x. + * @param x A numeric expression. + */ + log1p(x: number): number; + + /** + * Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of + * the natural logarithms). + * @param x A numeric expression. + */ + expm1(x: number): number; + + /** + * Returns the hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + cosh(x: number): number; + + /** + * Returns the hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + sinh(x: number): number; + + /** + * Returns the hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + tanh(x: number): number; + + /** + * Returns the inverse hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + acosh(x: number): number; + + /** + * Returns the inverse hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + asinh(x: number): number; + + /** + * Returns the inverse hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + atanh(x: number): number; + + /** + * Returns the square root of the sum of squares of its arguments. + * @param values Values to compute the square root for. + * If no arguments are passed, the result is +0. + * If there is only one argument, the result is the absolute value. + * If any argument is +Infinity or -Infinity, the result is +Infinity. + * If any argument is NaN, the result is NaN. + * If all arguments are either +0 or −0, the result is +0. + */ + hypot(...values: number[]): number; + + /** + * Returns the integral part of the a numeric expression, x, removing any fractional digits. + * If x is already an integer, the result is x. + * @param x A numeric expression. + */ + trunc(x: number): number; + + /** + * Returns the nearest single precision float representation of a number. + * @param x A numeric expression. + */ + fround(x: number): number; + + /** + * Returns an implementation-dependent approximation to the cube root of number. + * @param x A numeric expression. + */ + cbrt(x: number): number; +} + +interface PromiseLike { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; +} + +/** + * Represents the completion of an asynchronous operation + */ +interface Promise { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; + + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: (reason: any) => T | PromiseLike): Promise; + catch(onrejected?: (reason: any) => void): Promise; +} + +interface PromiseConstructor { + /** + * A reference to the prototype. + */ + prototype: Promise; + + /** + * Creates a new Promise. + * @param executor A callback used to initialize the promise. This callback is passed two arguments: + * a resolve callback used resolve the promise with a value or the result of another promise, + * and a reject callback used to reject the promise with a provided reason or error. + */ + new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + + /** + * Creates a Promise that is resolved with an array of results when all of the provided Promises + * resolve, or rejected when any Promise is rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + all(values: IterableShim>): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: IterableShim>): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new resolved promise for the provided value. + * @param value A promise. + * @returns A promise whose internal state matches the provided promise. + */ + resolve(value: T | PromiseLike): Promise; + + /** + * Creates a new resolved promise . + * @returns A resolved promise. + */ + resolve(): Promise; +} + +declare var Promise: PromiseConstructor; + +interface Map { + clear(): void; + delete(key: K): boolean; + forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): Map; + size: number; + entries(): IterableIteratorShim<[K, V]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; +} + +interface MapConstructor { + new (): Map; + new (iterable: IterableShim<[K, V]>): Map; + prototype: Map; +} + +declare var Map: MapConstructor; + +interface Set { + add(value: T): Set; + clear(): void; + delete(value: T): boolean; + forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + has(value: T): boolean; + size: number; + entries(): IterableIteratorShim<[T, T]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; + '_es6-shim iterator_'(): IterableIteratorShim; +} + +interface SetConstructor { + new (): Set; + new (iterable: IterableShim): Set; + prototype: Set; +} + +declare var Set: SetConstructor; + +interface WeakMap { + delete(key: K): boolean; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): WeakMap; +} + +interface WeakMapConstructor { + new (): WeakMap; + new (iterable: IterableShim<[K, V]>): WeakMap; + prototype: WeakMap; +} + +declare var WeakMap: WeakMapConstructor; + +interface WeakSet { + add(value: T): WeakSet; + delete(value: T): boolean; + has(value: T): boolean; +} + +interface WeakSetConstructor { + new (): WeakSet; + new (iterable: IterableShim): WeakSet; + prototype: WeakSet; +} + +declare var WeakSet: WeakSetConstructor; + +declare namespace Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): IterableIteratorShim; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; +} + +declare module "es6-shim" { + var String: StringConstructor; + var Array: ArrayConstructor; + var Number: NumberConstructor; + var Math: Math; + var Object: ObjectConstructor; + var Map: MapConstructor; + var Set: SetConstructor; + var WeakMap: WeakMapConstructor; + var WeakSet: WeakSetConstructor; + var Promise: PromiseConstructor; + namespace Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): Iterator; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; + } +} \ No newline at end of file diff --git a/node_modules/synyi-annotation-tool/typings/index.d.ts b/node_modules/synyi-annotation-tool/typings/index.d.ts new file mode 100644 index 0000000..841268a --- /dev/null +++ b/node_modules/synyi-annotation-tool/typings/index.d.ts @@ -0,0 +1 @@ +/// diff --git a/node_modules/synyi-annotation-tool/typings/svgjs.d.ts b/node_modules/synyi-annotation-tool/typings/svgjs.d.ts new file mode 100644 index 0000000..513e744 --- /dev/null +++ b/node_modules/synyi-annotation-tool/typings/svgjs.d.ts @@ -0,0 +1,276 @@ +// Type definitions for svg.js +// Project: http://www.svgjs.com/ +// Definitions by: Sean Hess +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// Reference: http://documentup.com/wout/svg.js + +// TODO sets +// TODO gradients + +declare namespace svgjs { + + export interface LinkedHTMLElement extends HTMLElement { + instance: Element; + } + + export interface Library { + (selector:string):Doc; + (domElement:HTMLElement):Doc; + create(name:string):any; + Element:ElementStatic; + supported:boolean; + get(id:string):Element; + extend(parent:Object, obj:Object):void; + } + + export interface Doc extends Element { + svg(data:string):any; + pattern(w:number, h:number, add:(e:Element)=>void):Element; + + defs():Defs; + + clear():void; + + mask():Mask; + + // TODO gradients + } + + + // https://github.com/wout/svg.filter.js + export interface Filter { + gaussianBlur(values:string):Filter; + colorMatrix(name:string, value:number):Filter; + colorMatrix(name:string, matrix:number[]):Filter; + componentTransfer(components:{rgb?: FilterComponentTransfer; g?: FilterComponentTransfer;}):Filter; + offset(x:number, y:number):Filter; + blend():Filter; + in(source:FilterSource):Filter; + sourceAlpha:FilterSource; + source:FilterSource; + } + + export interface FilterSource { + + } + + + export interface FilterComponentTransfer { + type: string; + tableValues?: string; + slope?: number; + intercept: number; + amplitude: number; + exponent: number; + offset: number; + } + + export interface Element extends Text, Parent { + node:LinkedHTMLElement; + + nested():Doc; + + animate(duration?:number, ease?:string, delay?:number):Animation; + animate(info:{ease?:string; duration?:number; delay?:number}):Animation; + + attr(name:string):any; + attr(obj:Object):Element; + attr(name:string, value:any, namespace?:string):Element; + + viewbox():Viewbox; + viewbox(x:number, y:number, w:number, h:number):Element; + viewbox(obj:Viewbox):Element; + + move(x:number, y:number, anchor?:boolean):Element; + x(x:number, anchor?:boolean):Element; + y(y:number, anchor?:boolean):Element; + x(): number; + y(): number; + + center(x:number, y:number, anchor?:boolean):Element; + cx(x:number, anchor?:boolean):Element; + cy(y:number, anchor?:boolean):Element; + cx(): number; + cy(): number; + + size(w:number, h:number, anchor?:boolean):Element; + + show():Element; + hide():Element; + visible():boolean; + remove():void; + + each(iterator:(i?:number, children?:Element[])=>void, deep?:boolean):void; + filter(adder:(filter:Filter)=>void):Element; + + transform(t:Transform):Element; + transform(): Transform; + + style(name:string, value:string):Element; + style(obj:Object):Element; + style(name:string):string; + style():string; + bbox():BBox; + rbox():RBox; + doc():Doc; + data(name:string):any; + data(name:string, value:any):Element; + remember(name:string, value:any):Element; + remember(obj:Object):Element; + remember(name:string):any; + forget(...keys:string[]):Element; + + fill(fill:{color?:string; opacity?:number}):Element; + fill(color:string):Element; + fill(pattern:Element):Element; + stroke(data:{color?:string; opacity?:number; width?: number}):Element; + stroke(color:string):Element; + opacity(o:number):Element; + rotate(d:number, cx?:number, cy?:number):Element; + skew(x:number, y:number):Element; + scale(x:number, y:number):Element; + translate(x:number, y:number):Element; + + maskWith(element:Element):Element; + masker:Element; + unmask():Element; + + clipWith(element:Element):Element; + clipper:Element; + unclip():Element; + + front():Element; + back():Element; + forward():Element; + backward():Element; + + siblings():Element[]; + position():number; + next():Element; + previous():Element; + before(element:Element):Element; + after(element:Element):Element; + + + click(cb:Function):void; + on(event:string, cb:Function):void; + off(event:string, cb:Function):void; + } + + export interface Mask extends Element { + add(element:Element):Mask; + } + + export interface Text { + content:string; + font(font:{family?:string; size?:number; anchor?:string; leading?:string}):Element; + tspan(text:string):Element; + path(data:string):Element; + plot(data:string):Element; + track:Element; + } + + export interface ElementStatic extends Parent { + new(node:any):Element; + } + + export interface Defs extends Element {} + + + export interface Animation { + stop():Animation; + + attr(name:string, value:any, namespace?:string):Animation; + attr(obj:Object):Animation; + attr(name:string):any; + + viewbox(x:number, y:number, w:number, h:number):Animation; + + move(x:number, y:number, anchor?:boolean):Animation; + x(x:number, anchor?:boolean):Animation; + y(y:number, anchor?:boolean):Animation; + + center(x:number, y:number, anchor?:boolean):Animation; + cx(x:number, anchor?:boolean):Animation; + cy(y:number, anchor?:boolean):Animation; + + size(w:number, h:number, anchor?:boolean):Animation; + during(cb:(pos:number)=>void):Animation; + to(value:number):Animation; + after(cb:()=>void):Animation; + + // TODO style, etc, bbox... + } + + export interface Parent { + put(element:Element, i?:number):Element; + add(element:Element, i?:number):Element; + children():Element[]; + + rect(w:number, h:number):Element; + ellipse(w:number, h:number):Element; + circle(diameter:number):Element; + line(x1:number, y1:number, x2:number, y2:number):Element; + polyline(data:string):Element; + polyline(points:number[][]):Element; + polygon(data:string):Element; + polygon(points:number[][]):Element; + path(data:string):Element; + image(url:string, w?:number, h?:number):Element; + text(text:string):Element; + text(adder:(element:Element)=>void):Element; + use(element:Element):Element; + + group():Element; + } + + export interface BBox { + height:number; + width:number; + y:number; + x:number; + cx:number; + cy:number; + merge(bbox:BBox):BBox; + } + + export interface RBox extends BBox {} + + export interface Attributes { + (name:string, value:any):void; + (obj:Object):void; + (name:string):any; + } + + export interface Viewbox { + x: number; + y: number; + width: number; + height: number; + zoom?: number; + } + + export interface Transform { + x?: number; + y?: number; + rotation?: number; + cx?: number; + cy?: number; + scaleX?: number; + scaleY?: number; + skewX?: number; + skewY?: number; + matrix?: string; // 1,0,0,1,0,0 + a?: number; // direct digits of matrix + b?: number; + c?: number; + d?: number; + e?: number; + f?: number; + } +} + +declare var SVG:svgjs.Library; +declare module "svg.js" { + export = SVG +} diff --git a/node_modules/systemjs/LICENSE b/node_modules/systemjs/LICENSE new file mode 100644 index 0000000..1e467a8 --- /dev/null +++ b/node_modules/systemjs/LICENSE @@ -0,0 +1,10 @@ +MIT License +----------- + +Copyright (C) 2013-2016 Guy Bedford + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/systemjs/README.md b/node_modules/systemjs/README.md new file mode 100644 index 0000000..afe998a --- /dev/null +++ b/node_modules/systemjs/README.md @@ -0,0 +1,149 @@ +SystemJS +======== + +[![Build Status][travis-image]][travis-url] +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/systemjs/systemjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Support](https://supporterhq.com/api/b/33df4abbec4d39260f49015d2457eafe/SystemJS)](https://supporterhq.com/support/33df4abbec4d39260f49015d2457eafe/SystemJS) + +Universal dynamic module loader - loads ES6 modules, AMD, CommonJS and global scripts in the browser and NodeJS. + +* [Loads any module format](docs/module-formats.md) with [exact circular reference and binding support](https://github.com/ModuleLoader/es6-module-loader/blob/v0.17.0/docs/circular-references-bindings.md). +* Loads [ES6 modules compiled into the `System.register` bundle format for production](docs/production-workflows.md), maintaining circular references support. +* Supports RequireJS-style [map](docs/overview.md#map-config), [paths](https://github.com/ModuleLoader/es6-module-loader/blob/master/docs/loader-config.md#paths-implementation), [bundles](docs/production-workflows.md#bundle-extension) and [global shims](docs/module-formats.md#shim-dependencies). +* [Loader plugins](docs/overview.md#plugin-loaders) allow custom transpilation or asset loading. + +Built to the format ES6-specified loader API from [ES6 Specification Draft Rev 27, Section 15](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27), +and will be updated to the [WhatWG loader API](https://whatwg.github.io/loader/) as soon as it can be considered stable for implementation. + +~19KB minified and gzipped, runs in IE8+ and NodeJS. + +For discussion, join the [Gitter Room](https://gitter.im/systemjs/systemjs). + +Documentation +--- + +* [ES6 Modules Overview](docs/es6-modules-overview.md) +* [SystemJS Overview](docs/overview.md) +* [Config API](docs/config-api.md) +* [Module Formats](docs/module-formats.md) +* [Production Workflows](docs/production-workflows.md) +* [System API](docs/system-api.md) +* [Creating Plugins](docs/creating-plugins.md) + +Basic Use +--- + +### Browser + +```html + + +``` + +The above will support loading all module formats, including ES Modules transpiled into the System.register format. + +To load ES6 code with in-browser transpilation, configure one of the following transpiler plugins: + +* [Babel](https://github.com/systemjs/plugin-babel) +* [TypeScript](https://github.com/frankwallis/plugin-typescript) +* [Traceur](http://github.com/systemjs/plugin-traceur) + +### Promise Polyfill + +SystemJS relies on `Promise` being present in the environment. + +For the best performance in IE and older browsers, it is advisable to load a polyfill like [Bluebird](https://github.com/petkaantonov/bluebird) or [es6-promise](https://github.com/stefanpenner/es6-promise) before SystemJS. + +Otherwise, when Promise is not available, SystemJS will attempt to load the `system-polyfills.js` file located in the dist folder which contains the when.js Promise polyfill. + +### NodeJS + +To load modules in NodeJS, install SystemJS with: + +``` + npm install systemjs +``` + +If transpiling ES6, also install the transpiler plugin, following the instructions from the transpiler project page. + +We can then load modules equivalently in NodeJS as we do in the browser: + +```javascript +var SystemJS = require('systemjs'); + +// loads './app.js' from the current directory +SystemJS.import('./app.js').then(function(m) { + console.log(m); +}); +``` + +If you are using jspm as a package manager you will also need to load the generated configuration. +The best way to do this in node is to get your `System` instance through jspm, which will automatically load your config correctly for you: + +```js +var Loader = require('jspm').Loader; +var SystemJS = new Loader(); + +SystemJS.import('lodash').then(function (_) { + console.log(_); +}); +``` + +### Plugins + +Supported loader plugins: + +* [CSS](https://github.com/systemjs/plugin-css) +* [LESS](https://github.com/systemjs/plugin-less) +* [Image](https://github.com/systemjs/plugin-image) +* [JSON](https://github.com/systemjs/plugin-json) +* [Text](https://github.com/systemjs/plugin-text) +* [Node Binary](https://github.com/systemjs/plugin-node-binary) + +Additional Plugins: + +* [Audio](https://github.com/ozsay/plugin-audio) +* [CoffeeScript](https://github.com/forresto/plugin-coffee) +* [Ember Handlebars](https://github.com/n-fuse/plugin-ember-hbs) +* [Handlebars](https://github.com/davis/plugin-hbs) +* [HTML](https://github.com/Hypercubed/systemjs-plugin-html/) +* [Image (lazy)](https://github.com/laurentgoudet/plugin-lazyimage) +* [Jade](https://github.com/johnsoftek/plugin-jade) +* [Jade VirtualDOM](https://github.com/WorldMaker/system-jade-virtualdom) +* [jst](https://github.com/podio/plugin-jst) +* [JSX](https://github.com/floatdrop/plugin-jsx) +* [Markdown](https://github.com/guybedford/plugin-md) +* [raw](https://github.com/matthewbauer/plugin-raw) +* [SASS](https://github.com/screendriver/plugin-sass) +* [SCSS](https://github.com/kevcjones/plugin-scss) +* [sofe](https://github.com/CanopyTax/sofe) +* [SVG](https://github.com/vuzonp/systemjs-plugin-svg) +* [WebFont](https://github.com/guybedford/plugin-font) +* [WebWorkers](https://github.com/casperlamboo/plugin-worker) +* [YAML](https://github.com/tb/plugin-yaml) + +Guides: + +* [Using plugins](docs/overview.md#plugin-loaders) +* [Creating plugins](docs/creating-plugins.md) + +#### Running the tests + +To install the dependencies correctly, run `bower install` from the root of the repo, then open `test/test.html` in a browser with a local server +or file access flags enabled. + +License +--- + +MIT + +[travis-url]: https://travis-ci.org/systemjs/systemjs +[travis-image]: https://travis-ci.org/systemjs/systemjs.svg?branch=master diff --git a/node_modules/systemjs/dist/system-csp-production.js b/node_modules/systemjs/dist/system-csp-production.js new file mode 100644 index 0000000..048a1e1 --- /dev/null +++ b/node_modules/systemjs/dist/system-csp-production.js @@ -0,0 +1,6 @@ +/* + * SystemJS v0.19.39 + */ +!function(){function e(){!function(e){function t(e,n){if("string"!=typeof e)throw new TypeError("URL must be a string");var r=String(e).replace(/^\s+|\s+$/g,"").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);if(!r)throw new RangeError("Invalid URL format");var a=r[1]||"",o=r[2]||"",i=r[3]||"",s=r[4]||"",l=r[5]||"",u=r[6]||"",d=r[7]||"",c=r[8]||"",f=r[9]||"";if(void 0!==n){var m=n instanceof t?n:new t(n),p=!a&&!s&&!o;!p||d||c||(c=m.search),p&&"/"!==d[0]&&(d=d?(!m.host&&!m.username||m.pathname?"":"/")+m.pathname.slice(0,m.pathname.lastIndexOf("/")+1)+d:m.pathname);var h=[];d.replace(/^(\.\.?(\/|$))+/,"").replace(/\/(\.(\/|$))+/g,"/").replace(/\/\.\.$/,"/../").replace(/\/?[^\/]*/g,function(e){"/.."===e?h.pop():h.push(e)}),d=h.join("").replace(/^\//,"/"===d[0]?"/":""),p&&(u=m.port,l=m.hostname,s=m.host,i=m.password,o=m.username),a||(a=m.protocol)}d=d.replace(/\\/g,"/"),this.origin=s?a+(""!==a||""!==s?"//":"")+s:"",this.href=a+(a&&s||"file:"==a?"//":"")+(""!==o?o+(""!==i?":"+i:"")+"@":"")+s+d+c+f,this.protocol=a,this.username=o,this.password=i,this.host=s,this.hostname=l,this.port=u,this.pathname=d,this.search=c,this.hash=f}e.URLPolyfill=t}("undefined"!=typeof self?self:global),function(e){function t(e,t){if(!e.originalErr)for(var n=((e.message||e)+(e.stack?"\n"+e.stack:"")).toString().split("\n"),r=[],a=0;as.length?(o[s]&&"/"||"")+t.substr(s.length):"")}else{var d=s.split("*");if(d.length>2)throw new TypeError("Only one wildcard in a path is permitted");var f=d[0].length;f>=a&&t.substr(0,d[0].length)==d[0]&&t.substr(t.length-d[1].length)==d[1]&&(a=f,r=s,n=t.substr(d[0].length,t.length-d[1].length-d[0].length))}}var m=o[r];return"string"==typeof n&&(m=m.replace("*",n)),m}function m(e){for(var t=[],n=[],r=0,a=e.length;r",linkSets:[],dependencies:[],metadata:{}}}function a(e,t,n){return new Promise(u({step:n.address?"fetch":"locate",loader:e,moduleName:t,moduleMetadata:n&&n.metadata||{},moduleSource:n.source,moduleAddress:n.address}))}function o(t,n,r,a){return new Promise(function(e,o){e(t.loaderObj.normalize(n,r,a))}).then(function(n){var r;if(t.modules[n])return r=e(n),r.status="linked",r.module=t.modules[n],r;for(var a=0,o=t.loads.length;a0)){var n=e.startingLoad;if(e.loader.loaderObj.execute===!1){for(var r=[].concat(e.loads),a=0,o=r.length;a "'+r.paths[o]+'" uses wildcards which are being deprecated for simpler trailing "/" folder paths.')}if(e.defaultJSExtensions&&(r.defaultJSExtensions=e.defaultJSExtensions,w.call(r,"The defaultJSExtensions configuration option is deprecated, use packages configuration instead.")),e.pluginFirst&&(r.pluginFirst=e.pluginFirst),e.map){var i="";for(var o in e.map){var s=e.map[o];if("string"!=typeof s){i+=(i.length?", ":"")+'"'+o+'"';var l=r.defaultJSExtensions&&".js"!=o.substr(o.length-3,3),u=r.decanonicalize(o);l&&".js"==u.substr(u.length-3,3)&&(u=u.substr(0,u.length-3));var c="";for(var f in r.packages)u.substr(0,f.length)==f&&(!u[f.length]||"/"==u[f.length])&&c.split("/").lengtha&&(n=o,a=r));return n}function t(e,t,n,r,a){if(!r||"/"==r[r.length-1]||a||t.defaultExtension===!1)return r;var o=!1;if(t.meta&&p(t.meta,r,function(e,t,n){if(0==n||e.lastIndexOf("*")!=e.length-1)return o=!0}),!o&&e.meta&&p(e.meta,n+"/"+r,function(e,t,n){if(0==n||e.lastIndexOf("*")!=e.length-1)return o=!0}),o)return r;var i="."+(t.defaultExtension||"js");return r.substr(r.length-i.length)!=i?r+i:r}function n(e,n,r,a,i){if(!a){if(!n.main)return r+(e.defaultJSExtensions?".js":"");a="./"==n.main.substr(0,2)?n.main.substr(2):n.main}if(n.map){var s="./"+a,l=S(n.map,s);if(l||(s="./"+t(e,n,r,a,i),s!="./"+a&&(l=S(n.map,s))),l){var u=o(e,n,r,l,s,i);if(u)return u}}return r+"/"+t(e,n,r,a,i)}function r(e,t,n,r){if("."==e)throw new Error("Package "+n+' has a map entry for "." which is not permitted.');return!(t.substr(0,e.length)==e&&r.length>e.length)}function o(e,n,a,o,i,s){"/"==i[i.length-1]&&(i=i.substr(0,i.length-1));var l=n.map[o];if("object"==typeof l)throw new Error("Synchronous conditional normalization not supported sync normalizing "+o+" in "+a);if(r(o,l,a,i)&&"string"==typeof l){if("."==l)l=a;else if("./"==l.substr(0,2))return a+"/"+t(e,n,a,l.substr(2)+i.substr(o.length),s);return e.normalizeSync(l+i.substr(o.length),a+"/")}}function l(e,n,r,a,o){if(!a){if(!n.main)return Promise.resolve(r+(e.defaultJSExtensions?".js":""));a="./"==n.main.substr(0,2)?n.main.substr(2):n.main}var i,s;return n.map&&(i="./"+a,s=S(n.map,i),s||(i="./"+t(e,n,r,a,o),i!="./"+a&&(s=S(n.map,i)))),(s?d(e,n,r,s,i,o):Promise.resolve()).then(function(i){return i?Promise.resolve(i):Promise.resolve(r+"/"+t(e,n,r,a,o))})}function u(e,n,r,a,o,i,s){if("."==o)o=r;else if("./"==o.substr(0,2))return Promise.resolve(r+"/"+t(e,n,r,o.substr(2)+i.substr(a.length),s)).then(function(t){return L.call(e,t,r+"/")});return e.normalize(o+i.substr(a.length),r+"/")}function d(e,t,n,a,o,i){"/"==o[o.length-1]&&(o=o.substr(0,o.length-1));var s=t.map[a];if("string"==typeof s)return r(a,s,n,o)?u(e,t,n,a,s,o,i):Promise.resolve();if(e.builder)return Promise.resolve(n+"/#:"+o);var l=[],d=[];for(var c in s){var f=z(c);d.push({condition:f,map:s[c]}),l.push(e.import(f.module,n))}return Promise.all(l).then(function(e){for(var t=0;tl&&(l=n),v(s,t,n&&l>n)}),v(n.metadata,s)}o.format&&!n.metadata.loader&&(n.metadata.format=n.metadata.format||o.format)}return t})}})}(),function(){function t(){if(s&&"interactive"===s.script.readyState)return s.load;for(var e=0;e=0;i--){for(var s=a[i],l=0;l1;)r=a.shift(),e=e[r]=e[r]||{};r=a.shift(),r in e||(e[r]=n)}s(function(e){return function(){this.meta={},e.call(this)}}),i("locate",function(e){return function(t){var n,r=this.meta,a=t.name,o=0;for(var i in r)if(n=i.indexOf("*"),n!==-1&&i.substr(0,n)===a.substr(0,n)&&i.substr(n+1)===a.substr(a.length-i.length+n+1)){var s=i.split("/").length;s>o&&(o=s),v(t.metadata,r[i],o!=s)}return r[a]&&v(t.metadata,r[a]),e.call(this,t)}});var t=/^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/,n=/\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g;i("translate",function(r){return function(a){if("defined"==a.metadata.format)return a.metadata.deps=a.metadata.deps||[],Promise.resolve(a.source);var o=a.source.match(t);if(o)for(var i=o[0].match(n),s=0;s')}else e()}else if("undefined"!=typeof importScripts){var a="";try{throw new Error("_")}catch(e){e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/,function(e,t){$__curScript={src:t},a=t.replace(/\/[^\/]*$/,"/")})}t&&importScripts(a+"system-polyfills.js"),e()}else $__curScript="undefined"!=typeof __filename?{src:__filename}:null,e()}(); +//# sourceMappingURL=system-csp-production.js.map diff --git a/node_modules/systemjs/dist/system-csp-production.js.map b/node_modules/systemjs/dist/system-csp-production.js.map new file mode 100644 index 0000000..00237ee --- /dev/null +++ b/node_modules/systemjs/dist/system-csp-production.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["system-csp-production.src.js"],"names":["bootstrap","global","URLPolyfill","url","baseURL","TypeError","m","String","replace","match","RangeError","protocol","username","password","host","hostname","port","pathname","search","hash","undefined","base","flag","slice","lastIndexOf","output","p","pop","push","join","this","origin","href","self","__global","addToError","err","msg","originalErr","stack","message","toString","split","newStack","i","length","$__curScript","indexOf","src","newMsg","substr","isBrowser","isWindows","newErr","errArgs","Error","fileName","lineNumber","Module","Loader","options","_loader","loaderObj","loads","modules","importPromises","moduleRecords","defineProperty","get","SystemJSLoader","call","paths","systemJSConstructor","SystemProto","hook","name","prototype","hookConstructor","isAbsolute","absURLRegEx","isRel","isPlain","urlResolve","parent","baseURI","URL","baseURIObj","applyPaths","loader","wildcard","pathMatch","maxWildcardPrefixLen","pathsCache","hasOwnProperty","path","pathParts","wildcardPrefixLen","outPath","group","deps","names","indices","l","index","getESModule","exports","esModule","getOwnPropertyDescriptor","defineOrCopyProperty","extend","value","targetObj","sourceObj","propName","d","Object","ex","a","b","prepend","extendMeta","val","Array","concat","extendPkgConfig","pkgCfgA","pkgCfgB","pkgName","warnInvalidProperties","prop","map","meta","depCache","dNormalized","coreResolve","warn","setPkgConfig","cfg","prependConfig","pkg","packages","basePkg","main","warnings","console","readMemberExpression","pParts","shift","getMapMatch","bestMatch","bestMatchLength","curMatchLength","prepareBaseURL","setProduction","isProduction","isBuilder","set","envModule","newModule","browser","node","_nodeRequire","production","dev","build","default","getNodeModule","parentModuleContext","_nodeModulePaths","require","parentName","mapMatch","has","builder","envSet","envCallback","browserConfig","nodeConfig","devConfig","buildConfig","productionConfig","detectRegisterFormat","source","leadingCommentAndMeta","leadingCommentAndMetaRegEx","createEntry","originalIndices","declare","execute","executingRequire","declarative","normalizedDeps","groupIndex","evaluated","module","esmExports","getGlobalValue","globalValue","first","parseCondition","condition","conditionExport","conditionModule","negation","conditionExportIndex","sysConditions","negate","serializeCondition","conditionObj","resolveCondition","bool","normalize","then","normalizedCondition","load","q","interpolateConditional","conditionalMatch","interpolationRegEx","Promise","resolve","conditionValue","booleanConditional","booleanIndex","isWorker","window","importScripts","document","process","platform","assert","item","thisLen","e","obj","opt","getElementsByTagName","bases","location","cwd","nativeURL","createLoad","status","anonCnt","linkSets","dependencies","metadata","loadModule","asyncStartLoadPartwayThrough","step","address","moduleName","moduleMetadata","moduleSource","moduleAddress","requestLoad","request","refererName","refererAddress","reject","proceedToLocate","proceedToFetch","locate","proceedToTranslate","fetch","translate","instantiate","instantiateResult","depsList","loadPromises","depLoad","key","addLoadToLinkSet","all","updateLinkSetOnLoad","exc","exception","linkSetFailed","stepState","existingLoad","done","linkSet","createLinkSet","startingLoad","loadingCount","j","doLink","error","link","_newModule","finishLoad","abrupt","checkError","pLoad","dep","failed","linkIndex","splice","globalLoadsIndex","trace","depMap","forEach","loadIndex","doDynamicExecute","linkError","createImportPromise","promise","constructor","define","delete","import","parentAddress","sourcePromise","pNames","getOwnPropertyNames","configurable","enumerable","freeze","referrerName","referrerAddress","System","fetchTextFromURL","XMLHttpRequest","authorization","fulfill","xhr","responseText","statusText","sameDomain","doTimeout","domainCheck","exec","XDomainRequest","onload","onerror","ontimeout","onprogress","timeout","onreadystatechange","readyState","addEventListener","open","setRequestHeader","withCredentials","setTimeout","send","fs","readFile","data","dataString","opts","headers","Accept","credentials","r","ok","text","scriptSrc","defaultJSExtensions","pluginFirst","loaderErrorStack","skipExt","resolved","httpRequest","systemImport","__useDefault","systemTranslate","format","apply","arguments","entry","JSON","parse","getConfig","curCurScript","config","isEnvConfig","checkHasConfig","transpilerRuntime","loadedTranspilerRuntime","bundles","packageConfigPaths","objMaps","v","defaultJSExtension","decanonicalize","pkgMatch","packageLength","Math","max","normalized","bundle","normalizedBundleDep","c","getPackage","curPkg","pkgLen","curPkgLen","addDefaultExtension","subPath","skipExtensions","defaultExtension","metaMatch","getMetaMatches","metaPattern","matchMeta","matchDepth","applyPackageConfigSync","mapPath","mapped","doMapSync","validMapping","normalizeSync","applyPackageConfig","doMap","doStringMap","conditionPromises","conditions","conditionValues","createPkgConfigPathObj","lastWildcard","regEx","RegExp","getPackageConfigMatch","configPath","exactMatch","packageConfigPath","packageName","loadPackageConfigPath","pkgConfigPath","configLoader","pluginLoader","systemjs","pkgMeta","matchFn","wildcardIndex","dotRel","exactMeta","decanonicalized","isPlugin","parentPackageName","parentPackage","parentMap","parentMapMatch","pkgConfigMatch","isConfigured","configured","bestDepth","getInteractiveScriptLoad","interactiveScript","script","interactiveLoadingScripts","webWorkerImport","integrity","workerLoad","head","curSystem","curRequire","ieEvents","s","createElement","isOpera","opera","attachEvent","loadingCnt","registerQueue","pushRegister","register","reduceRegister_","scriptLoad","complete","evt","cleanup","detachEvent","removeEventListener","removeChild","async","crossOrigin","setAttribute","appendChild","buildGroups","groups","depName","depEntry","defined","depGroupIndex","startEntry","curGroupDeclarative","linkDeclarativeModule","linkDynamicModule","ModuleRecord","getOrCreateModuleRecord","importers","declaration","locked","importerModule","importerIndex","setter","setters","id","depExports","depModule","len","getModule","ensureEvaluated","nameNormalized","__esModule","seen","registerDynamic","pushRegister_","amd","curMeta","del","doLoad","__exec","grouped","normalizePromises","reduceRegister","forEachGlobal","callback","keys","g","forEachGlobalValue","globalName","ignoredGlobalProps","globalSnapshot","prepareGlobal","globals","encapsulate","curDefine","oldGlobals","singleGlobal","multipleExports","stripOrigin","windowOrigin","requireResolve","parentId","getPathVars","moduleId","filename","pluginIndex","dirname","amdDefine","getCJSDeps","requireIndex","commentRegEx","params","fnBracketRegEx","requireAlias","wsRegEx","requireRegEx","requireRegExs","cjsRequirePre","cjsRequirePost","lastIndex","errback","referer","dynamicRequires","factory","req","contextualRequire","depValues","uri","moduleIndex","exportsIndex","toUrl","amdRequire","getParentName","parentPluginIndex","parsePlugin","argumentName","pluginName","argument","plugin","combinePluginParts","checkDefaultExtension","arg","createNormalizeSync","parsed","pluginSyntaxIndex","loaderNormalized","loaderModule","args","result","sourceMap","originalName","file","sources","calledInstantiate","alias","aliasDeps","_export","setMetaProperty","target","curPart","depth","metaRegEx","metaPartRegEx","metaParts","firstChar","metaString","metaName","metaValue","loadedBundles","matched","curModule","parts","substring","SystemJS","version","doPolyfill","scripts","currentScript","defer","curPath","basePath","systemJSBootstrap","write","__filename"],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/systemjs/dist/system-csp-production.src.js b/node_modules/systemjs/dist/system-csp-production.src.js new file mode 100644 index 0000000..9c5e565 --- /dev/null +++ b/node_modules/systemjs/dist/system-csp-production.src.js @@ -0,0 +1,4536 @@ +/* + * SystemJS v0.19.39 + */ +(function() { +function bootstrap() {// from https://gist.github.com/Yaffle/1088850 +(function(global) { +function URLPolyfill(url, baseURL) { + if (typeof url != 'string') + throw new TypeError('URL must be a string'); + var m = String(url).replace(/^\s+|\s+$/g, "").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); + if (!m) + throw new RangeError('Invalid URL format'); + var protocol = m[1] || ""; + var username = m[2] || ""; + var password = m[3] || ""; + var host = m[4] || ""; + var hostname = m[5] || ""; + var port = m[6] || ""; + var pathname = m[7] || ""; + var search = m[8] || ""; + var hash = m[9] || ""; + if (baseURL !== undefined) { + var base = baseURL instanceof URLPolyfill ? baseURL : new URLPolyfill(baseURL); + var flag = !protocol && !host && !username; + if (flag && !pathname && !search) + search = base.search; + if (flag && pathname[0] !== "/") + pathname = (pathname ? (((base.host || base.username) && !base.pathname ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + pathname) : base.pathname); + // dot segments removal + var output = []; + pathname.replace(/^(\.\.?(\/|$))+/, "") + .replace(/\/(\.(\/|$))+/g, "/") + .replace(/\/\.\.$/, "/../") + .replace(/\/?[^\/]*/g, function (p) { + if (p === "/..") + output.pop(); + else + output.push(p); + }); + pathname = output.join("").replace(/^\//, pathname[0] === "/" ? "/" : ""); + if (flag) { + port = base.port; + hostname = base.hostname; + host = base.host; + password = base.password; + username = base.username; + } + if (!protocol) + protocol = base.protocol; + } + + // convert URLs to use / always + pathname = pathname.replace(/\\/g, '/'); + + this.origin = host ? protocol + (protocol !== "" || host !== "" ? "//" : "") + host : ""; + this.href = protocol + (protocol && host || protocol == "file:" ? "//" : "") + (username !== "" ? username + (password !== "" ? ":" + password : "") + "@" : "") + host + pathname + search + hash; + this.protocol = protocol; + this.username = username; + this.password = password; + this.host = host; + this.hostname = hostname; + this.port = port; + this.pathname = pathname; + this.search = search; + this.hash = hash; +} +global.URLPolyfill = URLPolyfill; +})(typeof self != 'undefined' ? self : global);(function(__global) { + + var isWorker = typeof window == 'undefined' && typeof self != 'undefined' && typeof importScripts != 'undefined'; + var isBrowser = typeof window != 'undefined' && typeof document != 'undefined'; + var isWindows = typeof process != 'undefined' && typeof process.platform != 'undefined' && !!process.platform.match(/^win/); + + if (!__global.console) + __global.console = { assert: function() {} }; + + // IE8 support + var indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, thisLen = this.length; i < thisLen; i++) { + if (this[i] === item) { + return i; + } + } + return -1; + }; + + var defineProperty; + (function () { + try { + if (!!Object.defineProperty({}, 'a', {})) + defineProperty = Object.defineProperty; + } + catch (e) { + defineProperty = function(obj, prop, opt) { + try { + obj[prop] = opt.value || opt.get.call(obj); + } + catch(e) {} + } + } + })(); + + var errArgs = new Error(0, '_').fileName == '_'; + + function addToError(err, msg) { + // parse the stack removing loader code lines for simplification + if (!err.originalErr) { + var stack = ((err.message || err) + (err.stack ? '\n' + err.stack : '')).toString().split('\n'); + var newStack = []; + for (var i = 0; i < stack.length; i++) { + if (typeof $__curScript == 'undefined' || stack[i].indexOf($__curScript.src) == -1) + newStack.push(stack[i]); + } + } + + var newMsg = '(SystemJS) ' + (newStack ? newStack.join('\n\t') : err.message.substr(11)) + '\n\t' + msg; + + // Convert file:/// URLs to paths in Node + if (!isBrowser) + newMsg = newMsg.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, ''); + + var newErr = errArgs ? new Error(newMsg, err.fileName, err.lineNumber) : new Error(newMsg); + + newErr.stack = newMsg; + + // track the original error + newErr.originalErr = err.originalErr || err; + + return newErr; + } + + function __eval(source, debugName, context) { + try { + new Function(source).call(context); + } + catch(e) { + throw addToError(e, 'Evaluating ' + debugName); + } + } + + var baseURI; + + // environent baseURI detection + if (typeof document != 'undefined' && document.getElementsByTagName) { + baseURI = document.baseURI; + + if (!baseURI) { + var bases = document.getElementsByTagName('base'); + baseURI = bases[0] && bases[0].href || window.location.href; + } + } + else if (typeof location != 'undefined') { + baseURI = __global.location.href; + } + + // sanitize out the hash and querystring + if (baseURI) { + baseURI = baseURI.split('#')[0].split('?')[0]; + baseURI = baseURI.substr(0, baseURI.lastIndexOf('/') + 1); + } + else if (typeof process != 'undefined' && process.cwd) { + baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd() + '/'; + if (isWindows) + baseURI = baseURI.replace(/\\/g, '/'); + } + else { + throw new TypeError('No environment baseURI'); + } + + try { + var nativeURL = new __global.URL('test:///').protocol == 'test:'; + } + catch(e) {} + + var URL = nativeURL ? __global.URL : __global.URLPolyfill; + +/* +********************************************************************************************* + + Dynamic Module Loader Polyfill + + - Implemented exactly to the former 2014-08-24 ES6 Specification Draft Rev 27, Section 15 + http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27 + + - Functions are commented with their spec numbers, with spec differences commented. + + - Spec bugs are commented in this code with links. + + - Abstract functions have been combined where possible, and their associated functions + commented. + + - Realm implementation is entirely omitted. + +********************************************************************************************* +*/ + +function Module() {} +// http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag +defineProperty(Module.prototype, 'toString', { + value: function() { + return 'Module'; + } +}); +function Loader(options) { + this._loader = { + loaderObj: this, + loads: [], + modules: {}, + importPromises: {}, + moduleRecords: {} + }; + + // 26.3.3.6 + defineProperty(this, 'global', { + get: function() { + return __global; + } + }); + + // 26.3.3.13 realm not implemented +} + +(function() { + +// Some Helpers + +// logs a linkset snapshot for debugging +/* function snapshot(loader) { + console.log('---Snapshot---'); + for (var i = 0; i < loader.loads.length; i++) { + var load = loader.loads[i]; + var linkSetLog = ' ' + load.name + ' (' + load.status + '): '; + + for (var j = 0; j < load.linkSets.length; j++) { + linkSetLog += '{' + logloads(load.linkSets[j].loads) + '} '; + } + console.log(linkSetLog); + } + console.log(''); +} +function logloads(loads) { + var log = ''; + for (var k = 0; k < loads.length; k++) + log += loads[k].name + (k != loads.length - 1 ? ' ' : ''); + return log; +} */ + + +/* function checkInvariants() { + // see https://bugs.ecmascript.org/show_bug.cgi?id=2603#c1 + + var loads = System._loader.loads; + var linkSets = []; + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + console.assert(load.status == 'loading' || load.status == 'loaded', 'Each load is loading or loaded'); + + for (var j = 0; j < load.linkSets.length; j++) { + var linkSet = load.linkSets[j]; + + for (var k = 0; k < linkSet.loads.length; k++) + console.assert(loads.indexOf(linkSet.loads[k]) != -1, 'linkSet loads are a subset of loader loads'); + + if (linkSets.indexOf(linkSet) == -1) + linkSets.push(linkSet); + } + } + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + for (var j = 0; j < linkSets.length; j++) { + var linkSet = linkSets[j]; + + if (linkSet.loads.indexOf(load) != -1) + console.assert(load.linkSets.indexOf(linkSet) != -1, 'linkSet contains load -> load contains linkSet'); + + if (load.linkSets.indexOf(linkSet) != -1) + console.assert(linkSet.loads.indexOf(load) != -1, 'load contains linkSet -> linkSet contains load'); + } + } + + for (var i = 0; i < linkSets.length; i++) { + var linkSet = linkSets[i]; + for (var j = 0; j < linkSet.loads.length; j++) { + var load = linkSet.loads[j]; + + for (var k = 0; k < load.dependencies.length; k++) { + var depName = load.dependencies[k].value; + var depLoad; + for (var l = 0; l < loads.length; l++) { + if (loads[l].name != depName) + continue; + depLoad = loads[l]; + break; + } + + // loading records are allowed not to have their dependencies yet + // if (load.status != 'loading') + // console.assert(depLoad, 'depLoad found'); + + // console.assert(linkSet.loads.indexOf(depLoad) != -1, 'linkset contains all dependencies'); + } + } + } +} */ + + // 15.2.3 - Runtime Semantics: Loader State + + // 15.2.3.11 + function createLoaderLoad(object) { + return { + // modules is an object for ES5 implementation + modules: {}, + loads: [], + loaderObj: object + }; + } + + // 15.2.3.2 Load Records and LoadRequest Objects + + var anonCnt = 0; + + // 15.2.3.2.1 + function createLoad(name) { + return { + status: 'loading', + name: name || '', + linkSets: [], + dependencies: [], + metadata: {} + }; + } + + // 15.2.3.2.2 createLoadRequestObject, absorbed into calling functions + + // 15.2.4 + + // 15.2.4.1 + function loadModule(loader, name, options) { + return new Promise(asyncStartLoadPartwayThrough({ + step: options.address ? 'fetch' : 'locate', + loader: loader, + moduleName: name, + // allow metadata for import https://bugs.ecmascript.org/show_bug.cgi?id=3091 + moduleMetadata: options && options.metadata || {}, + moduleSource: options.source, + moduleAddress: options.address + })); + } + + // 15.2.4.2 + function requestLoad(loader, request, refererName, refererAddress) { + // 15.2.4.2.1 CallNormalize + return new Promise(function(resolve, reject) { + resolve(loader.loaderObj.normalize(request, refererName, refererAddress)); + }) + // 15.2.4.2.2 GetOrCreateLoad + .then(function(name) { + var load; + if (loader.modules[name]) { + load = createLoad(name); + load.status = 'linked'; + // https://bugs.ecmascript.org/show_bug.cgi?id=2795 + load.module = loader.modules[name]; + return load; + } + + for (var i = 0, l = loader.loads.length; i < l; i++) { + load = loader.loads[i]; + if (load.name != name) + continue; + return load; + } + + load = createLoad(name); + loader.loads.push(load); + + proceedToLocate(loader, load); + + return load; + }); + } + + // 15.2.4.3 + function proceedToLocate(loader, load) { + proceedToFetch(loader, load, + Promise.resolve() + // 15.2.4.3.1 CallLocate + .then(function() { + return loader.loaderObj.locate({ name: load.name, metadata: load.metadata }); + }) + ); + } + + // 15.2.4.4 + function proceedToFetch(loader, load, p) { + proceedToTranslate(loader, load, + p + // 15.2.4.4.1 CallFetch + .then(function(address) { + // adjusted, see https://bugs.ecmascript.org/show_bug.cgi?id=2602 + if (load.status != 'loading') + return; + load.address = address; + + return loader.loaderObj.fetch({ name: load.name, metadata: load.metadata, address: address }); + }) + ); + } + + // 15.2.4.5 + function proceedToTranslate(loader, load, p) { + p + // 15.2.4.5.1 CallTranslate + .then(function(source) { + if (load.status != 'loading') + return; + + load.address = load.address || load.name; + + return Promise.resolve(loader.loaderObj.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source })) + + // 15.2.4.5.2 CallInstantiate + .then(function(source) { + load.source = source; + return loader.loaderObj.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source }); + }) + + // 15.2.4.5.3 InstantiateSucceeded + .then(function(instantiateResult) { + if (instantiateResult === undefined) + throw new TypeError('Declarative modules unsupported in the polyfill.'); + + if (typeof instantiateResult != 'object') + throw new TypeError('Invalid instantiate return value'); + + load.depsList = instantiateResult.deps || []; + load.execute = instantiateResult.execute; + }) + // 15.2.4.6 ProcessLoadDependencies + .then(function() { + load.dependencies = []; + var depsList = load.depsList; + + var loadPromises = []; + for (var i = 0, l = depsList.length; i < l; i++) (function(request, index) { + loadPromises.push( + requestLoad(loader, request, load.name, load.address) + + // 15.2.4.6.1 AddDependencyLoad (load is parentLoad) + .then(function(depLoad) { + + // adjusted from spec to maintain dependency order + // this is due to the System.register internal implementation needs + load.dependencies[index] = { + key: request, + value: depLoad.name + }; + + if (depLoad.status != 'linked') { + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + addLoadToLinkSet(linkSets[i], depLoad); + } + + // console.log('AddDependencyLoad ' + depLoad.name + ' for ' + load.name); + // snapshot(loader); + }) + ); + })(depsList[i], i); + + return Promise.all(loadPromises); + }) + + // 15.2.4.6.2 LoadSucceeded + .then(function() { + // console.log('LoadSucceeded ' + load.name); + // snapshot(loader); + + load.status = 'loaded'; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + updateLinkSetOnLoad(linkSets[i], load); + }); + }) + // 15.2.4.5.4 LoadFailed + ['catch'](function(exc) { + load.status = 'failed'; + load.exception = exc; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) { + linkSetFailed(linkSets[i], load, exc); + } + + console.assert(load.linkSets.length == 0, 'linkSets not removed'); + }); + } + + // 15.2.4.7 PromiseOfStartLoadPartwayThrough absorbed into calling functions + + // 15.2.4.7.1 + function asyncStartLoadPartwayThrough(stepState) { + return function(resolve, reject) { + var loader = stepState.loader; + var name = stepState.moduleName; + var step = stepState.step; + + if (loader.modules[name]) + throw new TypeError('"' + name + '" already exists in the module table'); + + // adjusted to pick up existing loads + var existingLoad; + for (var i = 0, l = loader.loads.length; i < l; i++) { + if (loader.loads[i].name == name) { + existingLoad = loader.loads[i]; + + if (step == 'translate' && !existingLoad.source) { + existingLoad.address = stepState.moduleAddress; + proceedToTranslate(loader, existingLoad, Promise.resolve(stepState.moduleSource)); + } + + // a primary load -> use that existing linkset if it is for the direct load here + // otherwise create a new linkset unit + if (existingLoad.linkSets.length && existingLoad.linkSets[0].loads[0].name == existingLoad.name) + return existingLoad.linkSets[0].done.then(function() { + resolve(existingLoad); + }); + } + } + + var load = existingLoad || createLoad(name); + + load.metadata = stepState.moduleMetadata; + + var linkSet = createLinkSet(loader, load); + + loader.loads.push(load); + + resolve(linkSet.done); + + if (step == 'locate') + proceedToLocate(loader, load); + + else if (step == 'fetch') + proceedToFetch(loader, load, Promise.resolve(stepState.moduleAddress)); + + else { + console.assert(step == 'translate', 'translate step'); + load.address = stepState.moduleAddress; + proceedToTranslate(loader, load, Promise.resolve(stepState.moduleSource)); + } + } + } + + // Declarative linking functions run through alternative implementation: + // 15.2.5.1.1 CreateModuleLinkageRecord not implemented + // 15.2.5.1.2 LookupExport not implemented + // 15.2.5.1.3 LookupModuleDependency not implemented + + // 15.2.5.2.1 + function createLinkSet(loader, startingLoad) { + var linkSet = { + loader: loader, + loads: [], + startingLoad: startingLoad, // added see spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + loadingCount: 0 + }; + linkSet.done = new Promise(function(resolve, reject) { + linkSet.resolve = resolve; + linkSet.reject = reject; + }); + addLoadToLinkSet(linkSet, startingLoad); + return linkSet; + } + // 15.2.5.2.2 + function addLoadToLinkSet(linkSet, load) { + if (load.status == 'failed') + return; + + for (var i = 0, l = linkSet.loads.length; i < l; i++) + if (linkSet.loads[i] == load) + return; + + linkSet.loads.push(load); + load.linkSets.push(linkSet); + + // adjustment, see https://bugs.ecmascript.org/show_bug.cgi?id=2603 + if (load.status != 'loaded') { + linkSet.loadingCount++; + } + + var loader = linkSet.loader; + + for (var i = 0, l = load.dependencies.length; i < l; i++) { + if (!load.dependencies[i]) + continue; + + var name = load.dependencies[i].value; + + if (loader.modules[name]) + continue; + + for (var j = 0, d = loader.loads.length; j < d; j++) { + if (loader.loads[j].name != name) + continue; + + addLoadToLinkSet(linkSet, loader.loads[j]); + break; + } + } + // console.log('add to linkset ' + load.name); + // snapshot(linkSet.loader); + } + + // linking errors can be generic or load-specific + // this is necessary for debugging info + function doLink(linkSet) { + var error = false; + try { + link(linkSet, function(load, exc) { + linkSetFailed(linkSet, load, exc); + error = true; + }); + } + catch(e) { + linkSetFailed(linkSet, null, e); + error = true; + } + return error; + } + + // 15.2.5.2.3 + function updateLinkSetOnLoad(linkSet, load) { + // console.log('update linkset on load ' + load.name); + // snapshot(linkSet.loader); + + console.assert(load.status == 'loaded' || load.status == 'linked', 'loaded or linked'); + + linkSet.loadingCount--; + + if (linkSet.loadingCount > 0) + return; + + // adjusted for spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + var startingLoad = linkSet.startingLoad; + + // non-executing link variation for loader tracing + // on the server. Not in spec. + /***/ + if (linkSet.loader.loaderObj.execute === false) { + var loads = [].concat(linkSet.loads); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + load.module = { + name: load.name, + module: _newModule({}), + evaluated: true + }; + load.status = 'linked'; + finishLoad(linkSet.loader, load); + } + return linkSet.resolve(startingLoad); + } + /***/ + + var abrupt = doLink(linkSet); + + if (abrupt) + return; + + console.assert(linkSet.loads.length == 0, 'loads cleared'); + + linkSet.resolve(startingLoad); + } + + // 15.2.5.2.4 + function linkSetFailed(linkSet, load, exc) { + var loader = linkSet.loader; + var requests; + + checkError: + if (load) { + if (linkSet.loads[0].name == load.name) { + exc = addToError(exc, 'Error loading ' + load.name); + } + else { + for (var i = 0; i < linkSet.loads.length; i++) { + var pLoad = linkSet.loads[i]; + for (var j = 0; j < pLoad.dependencies.length; j++) { + var dep = pLoad.dependencies[j]; + if (dep.value == load.name) { + exc = addToError(exc, 'Error loading ' + load.name + ' as "' + dep.key + '" from ' + pLoad.name); + break checkError; + } + } + } + exc = addToError(exc, 'Error loading ' + load.name + ' from ' + linkSet.loads[0].name); + } + } + else { + exc = addToError(exc, 'Error linking ' + linkSet.loads[0].name); + } + + + var loads = linkSet.loads.concat([]); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + + // store all failed load records + loader.loaderObj.failed = loader.loaderObj.failed || []; + if (indexOf.call(loader.loaderObj.failed, load) == -1) + loader.loaderObj.failed.push(load); + + var linkIndex = indexOf.call(load.linkSets, linkSet); + console.assert(linkIndex != -1, 'link not present'); + load.linkSets.splice(linkIndex, 1); + if (load.linkSets.length == 0) { + var globalLoadsIndex = indexOf.call(linkSet.loader.loads, load); + if (globalLoadsIndex != -1) + linkSet.loader.loads.splice(globalLoadsIndex, 1); + } + } + linkSet.reject(exc); + } + + // 15.2.5.2.5 + function finishLoad(loader, load) { + // add to global trace if tracing + if (loader.loaderObj.trace) { + if (!loader.loaderObj.loads) + loader.loaderObj.loads = {}; + var depMap = {}; + load.dependencies.forEach(function(dep) { + depMap[dep.key] = dep.value; + }); + loader.loaderObj.loads[load.name] = { + name: load.name, + deps: load.dependencies.map(function(dep){ return dep.key }), + depMap: depMap, + address: load.address, + metadata: load.metadata, + source: load.source + }; + } + // if not anonymous, add to the module table + if (load.name) { + console.assert(!loader.modules[load.name] || loader.modules[load.name].module === load.module.module, 'load not in module table'); + loader.modules[load.name] = load.module; + } + var loadIndex = indexOf.call(loader.loads, load); + if (loadIndex != -1) + loader.loads.splice(loadIndex, 1); + for (var i = 0, l = load.linkSets.length; i < l; i++) { + loadIndex = indexOf.call(load.linkSets[i].loads, load); + if (loadIndex != -1) + load.linkSets[i].loads.splice(loadIndex, 1); + } + load.linkSets.splice(0, load.linkSets.length); + } + + function doDynamicExecute(linkSet, load, linkError) { + try { + var module = load.execute(); + } + catch(e) { + linkError(load, e); + return; + } + if (!module || !(module instanceof Module)) + linkError(load, new TypeError('Execution must define a Module instance')); + else + return module; + } + + // 26.3 Loader + + // 26.3.1.1 + // defined at top + + // importPromises adds ability to import a module twice without error - https://bugs.ecmascript.org/show_bug.cgi?id=2601 + function createImportPromise(loader, name, promise) { + var importPromises = loader._loader.importPromises; + return importPromises[name] = promise.then(function(m) { + importPromises[name] = undefined; + return m; + }, function(e) { + importPromises[name] = undefined; + throw e; + }); + } + + Loader.prototype = { + // 26.3.3.1 + constructor: Loader, + // 26.3.3.2 + define: function(name, source, options) { + // check if already defined + if (this._loader.importPromises[name]) + throw new TypeError('Module is already loading.'); + return createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'translate', + loader: this._loader, + moduleName: name, + moduleMetadata: options && options.metadata || {}, + moduleSource: source, + moduleAddress: options && options.address + }))); + }, + // 26.3.3.3 + 'delete': function(name) { + var loader = this._loader; + delete loader.importPromises[name]; + delete loader.moduleRecords[name]; + return loader.modules[name] ? delete loader.modules[name] : false; + }, + // 26.3.3.4 entries not implemented + // 26.3.3.5 + get: function(key) { + if (!this._loader.modules[key]) + return; + return this._loader.modules[key].module; + }, + // 26.3.3.7 + has: function(name) { + return !!this._loader.modules[name]; + }, + // 26.3.3.8 + 'import': function(name, parentName, parentAddress) { + if (typeof parentName == 'object') + parentName = parentName.name; + + // run normalize first + var loaderObj = this; + + // added, see https://bugs.ecmascript.org/show_bug.cgi?id=2659 + return Promise.resolve(loaderObj.normalize(name, parentName)) + .then(function(name) { + var loader = loaderObj._loader; + + if (loader.modules[name]) + return loader.modules[name].module; + + return loader.importPromises[name] || createImportPromise(loaderObj, name, + loadModule(loader, name, {}) + .then(function(load) { + delete loader.importPromises[name]; + return load.module.module; + })); + }); + }, + // 26.3.3.9 keys not implemented + // 26.3.3.10 + load: function(name) { + var loader = this._loader; + if (loader.modules[name]) + return Promise.resolve(); + return loader.importPromises[name] || createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'locate', + loader: loader, + moduleName: name, + moduleMetadata: {}, + moduleSource: undefined, + moduleAddress: undefined + })) + .then(function() { + delete loader.importPromises[name]; + })); + }, + // 26.3.3.11 + module: function(source, options) { + var load = createLoad(); + load.address = options && options.address; + var linkSet = createLinkSet(this._loader, load); + var sourcePromise = Promise.resolve(source); + var loader = this._loader; + var p = linkSet.done.then(function() { + return load.module.module; + }); + proceedToTranslate(loader, load, sourcePromise); + return p; + }, + // 26.3.3.12 + newModule: function (obj) { + if (typeof obj != 'object') + throw new TypeError('Expected object'); + + var m = new Module(); + + var pNames = []; + if (Object.getOwnPropertyNames && obj != null) + pNames = Object.getOwnPropertyNames(obj); + else + for (var key in obj) + pNames.push(key); + + for (var i = 0; i < pNames.length; i++) (function(key) { + defineProperty(m, key, { + configurable: false, + enumerable: true, + get: function () { + return obj[key]; + }, + set: function() { + throw new Error('Module exports cannot be changed externally.'); + } + }); + })(pNames[i]); + + if (Object.freeze) + Object.freeze(m); + + return m; + }, + // 26.3.3.14 + set: function(name, module) { + if (!(module instanceof Module)) + throw new TypeError('Loader.set(' + name + ', module) must be a module'); + this._loader.modules[name] = { + module: module + }; + }, + // 26.3.3.15 values not implemented + // 26.3.3.16 @@iterator not implemented + // 26.3.3.17 @@toStringTag not implemented + + // 26.3.3.18.1 + normalize: function(name, referrerName, referrerAddress) {}, + // 26.3.3.18.2 + locate: function(load) { + return load.name; + }, + // 26.3.3.18.3 + fetch: function(load) { + }, + // 26.3.3.18.4 + translate: function(load) { + return load.source; + }, + // 26.3.3.18.5 + instantiate: function(load) { + } + }; + + var _newModule = Loader.prototype.newModule; + +/* + * ES6 Module Declarative Linking Code + */ + function link(linkSet, linkError) { + + var loader = linkSet.loader; + + if (!linkSet.loads.length) + return; + + var loads = linkSet.loads.concat([]); + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + + var module = doDynamicExecute(linkSet, load, linkError); + if (!module) + return; + load.module = { + name: load.name, + module: module + }; + load.status = 'linked'; + + finishLoad(loader, load); + } + } + +})(); + +var System; + +// SystemJS Loader Class and Extension helpers +function SystemJSLoader() { + Loader.call(this); + + this.paths = {}; + this._loader.paths = {}; + + systemJSConstructor.call(this); +} + +// inline Object.create-style class extension +function SystemProto() {}; +SystemProto.prototype = Loader.prototype; +SystemJSLoader.prototype = new SystemProto(); +SystemJSLoader.prototype.constructor = SystemJSLoader; + +var systemJSConstructor; + +function hook(name, hook) { + SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {}); +} +function hookConstructor(hook) { + systemJSConstructor = hook(systemJSConstructor || function() {}); +} + + +var absURLRegEx = /^[^\/]+:\/\//; +function isAbsolute(name) { + return name.match(absURLRegEx); +} +function isRel(name) { + return (name[0] == '.' && (!name[1] || name[1] == '/' || name[1] == '.')) || name[0] == '/'; +} +function isPlain(name) { + return !isRel(name) && !isAbsolute(name); +} + +var baseURIObj = new URL(baseURI); + +function urlResolve(name, parent) { + // url resolution shortpaths + if (name[0] == '.') { + // dot-relative url normalization + if (name[1] == '/' && name[2] != '.') + return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name.substr(2); + } + else if (name[0] != '/' && name.indexOf(':') == -1) { + // plain parent normalization + return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name; + } + + return new URL(name, parent && parent.replace(/#/g, '%05') || baseURIObj).href.replace(/%05/g, '#'); +} + +// NB no specification provided for System.paths, used ideas discussed in https://github.com/jorendorff/js-loaders/issues/25 +function applyPaths(loader, name) { + // most specific (most number of slashes in path) match wins + var pathMatch = '', wildcard, maxWildcardPrefixLen = 0; + + var paths = loader.paths; + var pathsCache = loader._loader.paths; + + // check to see if we have a paths entry + for (var p in paths) { + if (paths.hasOwnProperty && !paths.hasOwnProperty(p)) + continue; + + // paths sanitization + var path = paths[p]; + if (path !== pathsCache[p]) + path = paths[p] = pathsCache[p] = urlResolve(paths[p], isRel(paths[p]) ? baseURI : loader.baseURL); + + // exact path match + if (p.indexOf('*') === -1) { + if (name == p) + return paths[p]; + + // support trailing / in paths rules + else if (name.substr(0, p.length - 1) == p.substr(0, p.length - 1) && (name.length < p.length || name[p.length - 1] == p[p.length - 1]) && (paths[p][paths[p].length - 1] == '/' || paths[p] == '')) { + return paths[p].substr(0, paths[p].length - 1) + (name.length > p.length ? (paths[p] && '/' || '') + name.substr(p.length) : ''); + } + } + // wildcard path match + else { + var pathParts = p.split('*'); + if (pathParts.length > 2) + throw new TypeError('Only one wildcard in a path is permitted'); + + var wildcardPrefixLen = pathParts[0].length; + if (wildcardPrefixLen >= maxWildcardPrefixLen && + name.substr(0, pathParts[0].length) == pathParts[0] && + name.substr(name.length - pathParts[1].length) == pathParts[1]) { + maxWildcardPrefixLen = wildcardPrefixLen; + pathMatch = p; + wildcard = name.substr(pathParts[0].length, name.length - pathParts[1].length - pathParts[0].length); + } + } + } + + var outPath = paths[pathMatch]; + if (typeof wildcard == 'string') + outPath = outPath.replace('*', wildcard); + + return outPath; +} + +function dedupe(deps) { + var newDeps = []; + for (var i = 0, l = deps.length; i < l; i++) + if (indexOf.call(newDeps, deps[i]) == -1) + newDeps.push(deps[i]) + return newDeps; +} + +function group(deps) { + var names = []; + var indices = []; + for (var i = 0, l = deps.length; i < l; i++) { + var index = indexOf.call(names, deps[i]); + if (index === -1) { + names.push(deps[i]); + indices.push([i]); + } + else { + indices[index].push(i); + } + } + return { names: names, indices: indices }; +} + +var getOwnPropertyDescriptor = true; +try { + Object.getOwnPropertyDescriptor({ a: 0 }, 'a'); +} +catch(e) { + getOwnPropertyDescriptor = false; +} + +// converts any module.exports object into an object ready for SystemJS.newModule +function getESModule(exports) { + var esModule = {}; + // don't trigger getters/setters in environments that support them + if ((typeof exports == 'object' || typeof exports == 'function') && exports !== __global) { + if (getOwnPropertyDescriptor) { + for (var p in exports) { + // The default property is copied to esModule later on + if (p === 'default') + continue; + defineOrCopyProperty(esModule, exports, p); + } + } + else { + extend(esModule, exports); + } + } + esModule['default'] = exports; + defineProperty(esModule, '__useDefault', { + value: true + }); + return esModule; +} + +function defineOrCopyProperty(targetObj, sourceObj, propName) { + try { + var d; + if (d = Object.getOwnPropertyDescriptor(sourceObj, propName)) + defineProperty(targetObj, propName, d); + } + catch (ex) { + // Object.getOwnPropertyDescriptor threw an exception, fall back to normal set property + // we dont need hasOwnProperty here because getOwnPropertyDescriptor would have returned undefined above + targetObj[propName] = sourceObj[propName]; + return false; + } +} + +function extend(a, b, prepend) { + var hasOwnProperty = b && b.hasOwnProperty; + for (var p in b) { + if (hasOwnProperty && !b.hasOwnProperty(p)) + continue; + if (!prepend || !(p in a)) + a[p] = b[p]; + } + return a; +} + +// meta first-level extends where: +// array + array appends +// object + object extends +// other properties replace +function extendMeta(a, b, prepend) { + var hasOwnProperty = b && b.hasOwnProperty; + for (var p in b) { + if (hasOwnProperty && !b.hasOwnProperty(p)) + continue; + var val = b[p]; + if (!(p in a)) + a[p] = val; + else if (val instanceof Array && a[p] instanceof Array) + a[p] = [].concat(prepend ? val : a[p]).concat(prepend ? a[p] : val); + else if (typeof val == 'object' && val !== null && typeof a[p] == 'object') + a[p] = extend(extend({}, a[p]), val, prepend); + else if (!prepend) + a[p] = val; + } +} + +function extendPkgConfig(pkgCfgA, pkgCfgB, pkgName, loader, warnInvalidProperties) { + for (var prop in pkgCfgB) { + if (indexOf.call(['main', 'format', 'defaultExtension', 'basePath'], prop) != -1) { + pkgCfgA[prop] = pkgCfgB[prop]; + } + else if (prop == 'map') { + extend(pkgCfgA.map = pkgCfgA.map || {}, pkgCfgB.map); + } + else if (prop == 'meta') { + extend(pkgCfgA.meta = pkgCfgA.meta || {}, pkgCfgB.meta); + } + else if (prop == 'depCache') { + for (var d in pkgCfgB.depCache) { + var dNormalized; + + if (d.substr(0, 2) == './') + dNormalized = pkgName + '/' + d.substr(2); + else + dNormalized = coreResolve.call(loader, d); + loader.depCache[dNormalized] = (loader.depCache[dNormalized] || []).concat(pkgCfgB.depCache[d]); + } + } + else if (warnInvalidProperties && indexOf.call(['browserConfig', 'nodeConfig', 'devConfig', 'productionConfig'], prop) == -1 && + (!pkgCfgB.hasOwnProperty || pkgCfgB.hasOwnProperty(prop))) { + warn.call(loader, '"' + prop + '" is not a valid package configuration option in package ' + pkgName); + } + } +} + +// deeply-merge (to first level) config with any existing package config +function setPkgConfig(loader, pkgName, cfg, prependConfig) { + var pkg; + + // first package is config by reference for fast path, cloned after that + if (!loader.packages[pkgName]) { + pkg = loader.packages[pkgName] = cfg; + } + else { + var basePkg = loader.packages[pkgName]; + pkg = loader.packages[pkgName] = {}; + + extendPkgConfig(pkg, prependConfig ? cfg : basePkg, pkgName, loader, prependConfig); + extendPkgConfig(pkg, prependConfig ? basePkg : cfg, pkgName, loader, !prependConfig); + } + + // main object becomes main map + if (typeof pkg.main == 'object') { + pkg.map = pkg.map || {}; + pkg.map['./@main'] = pkg.main; + pkg.main['default'] = pkg.main['default'] || './'; + pkg.main = '@main'; + } + + return pkg; +} + +function warn(msg) { + if (this.warnings && typeof console != 'undefined' && console.warn) + console.warn(msg); +} + var fetchTextFromURL; + if (typeof XMLHttpRequest != 'undefined') { + fetchTextFromURL = function(url, authorization, fulfill, reject) { + var xhr = new XMLHttpRequest(); + var sameDomain = true; + var doTimeout = false; + if (!('withCredentials' in xhr)) { + // check if same domain + var domainCheck = /^(\w+:)?\/\/([^\/]+)/.exec(url); + if (domainCheck) { + sameDomain = domainCheck[2] === window.location.host; + if (domainCheck[1]) + sameDomain &= domainCheck[1] === window.location.protocol; + } + } + if (!sameDomain && typeof XDomainRequest != 'undefined') { + xhr = new XDomainRequest(); + xhr.onload = load; + xhr.onerror = error; + xhr.ontimeout = error; + xhr.onprogress = function() {}; + xhr.timeout = 0; + doTimeout = true; + } + function load() { + fulfill(xhr.responseText); + } + function error() { + reject(new Error('XHR error' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url)); + } + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + // in Chrome on file:/// URLs, status is 0 + if (xhr.status == 0) { + if (xhr.responseText) { + load(); + } + else { + // when responseText is empty, wait for load or error event + // to inform if it is a 404 or empty file + xhr.addEventListener('error', error); + xhr.addEventListener('load', load); + } + } + else if (xhr.status === 200) { + load(); + } + else { + error(); + } + } + }; + xhr.open("GET", url, true); + + if (xhr.setRequestHeader) { + xhr.setRequestHeader('Accept', 'application/x-es-module, */*'); + // can set "authorization: true" to enable withCredentials only + if (authorization) { + if (typeof authorization == 'string') + xhr.setRequestHeader('Authorization', authorization); + xhr.withCredentials = true; + } + } + + if (doTimeout) { + setTimeout(function() { + xhr.send(); + }, 0); + } else { + xhr.send(null); + } + }; + } + else if (typeof require != 'undefined' && typeof process != 'undefined') { + var fs; + fetchTextFromURL = function(url, authorization, fulfill, reject) { + if (url.substr(0, 8) != 'file:///') + throw new Error('Unable to fetch "' + url + '". Only file URLs of the form file:/// allowed running in Node.'); + fs = fs || require('fs'); + if (isWindows) + url = url.replace(/\//g, '\\').substr(8); + else + url = url.substr(7); + return fs.readFile(url, function(err, data) { + if (err) { + return reject(err); + } + else { + // Strip Byte Order Mark out if it's the leading char + var dataString = data + ''; + if (dataString[0] === '\ufeff') + dataString = dataString.substr(1); + + fulfill(dataString); + } + }); + }; + } + else if (typeof self != 'undefined' && typeof self.fetch != 'undefined') { + fetchTextFromURL = function(url, authorization, fulfill, reject) { + var opts = { + headers: {'Accept': 'application/x-es-module, */*'} + }; + + if (authorization) { + if (typeof authorization == 'string') + opts.headers['Authorization'] = authorization; + opts.credentials = 'include'; + } + + fetch(url, opts) + .then(function (r) { + if (r.ok) { + return r.text(); + } else { + throw new Error('Fetch error: ' + r.status + ' ' + r.statusText); + } + }) + .then(fulfill, reject); + } + } + else { + throw new TypeError('No environment fetch API available.'); + } +function readMemberExpression(p, value) { + var pParts = p.split('.'); + while (pParts.length) + value = value[pParts.shift()]; + return value; +} + +function getMapMatch(map, name) { + var bestMatch, bestMatchLength = 0; + + for (var p in map) { + if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) { + var curMatchLength = p.split('/').length; + if (curMatchLength <= bestMatchLength) + continue; + bestMatch = p; + bestMatchLength = curMatchLength; + } + } + + return bestMatch; +} + +function prepareBaseURL(loader) { + // ensure baseURl is fully normalized + if (this._loader.baseURL !== this.baseURL) { + if (this.baseURL[this.baseURL.length - 1] != '/') + this.baseURL += '/'; + + this._loader.baseURL = this.baseURL = new URL(this.baseURL, baseURIObj).href; + } +} + +var envModule; +function setProduction(isProduction, isBuilder) { + this.set('@system-env', envModule = this.newModule({ + browser: isBrowser, + node: !!this._nodeRequire, + production: !isBuilder && isProduction, + dev: isBuilder || !isProduction, + build: isBuilder, + 'default': true + })); +} + +hookConstructor(function(constructor) { + return function() { + constructor.call(this); + + // support baseURL + this.baseURL = baseURI; + + // support map and paths + this.map = {}; + + // make the location of the system.js script accessible + if (typeof $__curScript != 'undefined') + this.scriptSrc = $__curScript.src; + + // global behaviour flags + this.warnings = false; + this.defaultJSExtensions = false; + this.pluginFirst = false; + this.loaderErrorStack = false; + + // by default load ".json" files as json + // leading * meta doesn't need normalization + // NB add this in next breaking release + // this.meta['*.json'] = { format: 'json' }; + + // support the empty module, as a concept + this.set('@empty', this.newModule({})); + + setProduction.call(this, false, false); + }; +}); + +// include the node require since we're overriding it +if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser) + SystemJSLoader.prototype._nodeRequire = require; + +/* + Core SystemJS Normalization + + If a name is relative, we apply URL normalization to the page + If a name is an absolute URL, we leave it as-is + + Plain names (neither of the above) run through the map and paths + normalization phases. + + The paths normalization phase applies last (paths extension), which + defines the `decanonicalize` function and normalizes everything into + a URL. + */ + +var parentModuleContext; +function getNodeModule(name, baseURL) { + if (!isPlain(name)) + throw new Error('Node module ' + name + ' can\'t be loaded as it is not a package require.'); + + if (!parentModuleContext) { + var Module = this._nodeRequire('module'); + var base = baseURL.substr(isWindows ? 8 : 7); + parentModuleContext = new Module(base); + parentModuleContext.paths = Module._nodeModulePaths(base); + } + return parentModuleContext.require(name); +} + +function coreResolve(name, parentName) { + // standard URL resolution + if (isRel(name)) + return urlResolve(name, parentName); + else if (isAbsolute(name)) + return name; + + // plain names not starting with './', '://' and '/' go through custom resolution + var mapMatch = getMapMatch(this.map, name); + + if (mapMatch) { + name = this.map[mapMatch] + name.substr(mapMatch.length); + + if (isRel(name)) + return urlResolve(name); + else if (isAbsolute(name)) + return name; + } + + if (this.has(name)) + return name; + + // dynamically load node-core modules when requiring `@node/fs` for example + if (name.substr(0, 6) == '@node/') { + if (!this._nodeRequire) + throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.'); + if (this.builder) + this.set(name, this.newModule({})); + else + this.set(name, this.newModule(getESModule(getNodeModule.call(this, name.substr(6), this.baseURL)))); + return name; + } + + // prepare the baseURL to ensure it is normalized + prepareBaseURL.call(this); + + return applyPaths(this, name) || this.baseURL + name; +} + +hook('normalize', function(normalize) { + return function(name, parentName, skipExt) { + var resolved = coreResolve.call(this, name, parentName); + if (this.defaultJSExtensions && !skipExt && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved)) + resolved += '.js'; + return resolved; + }; +}); + +// percent encode just '#' in urls if using HTTP requests +var httpRequest = typeof XMLHttpRequest != 'undefined'; +hook('locate', function(locate) { + return function(load) { + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + if (httpRequest) + return address.replace(/#/g, '%23'); + return address; + }); + }; +}); + +/* + * Fetch with authorization + */ +hook('fetch', function() { + return function(load) { + return new Promise(function(resolve, reject) { + fetchTextFromURL(load.address, load.metadata.authorization, resolve, reject); + }); + }; +}); + +/* + __useDefault + + When a module object looks like: + newModule( + __useDefault: true, + default: 'some-module' + }) + + Then importing that module provides the 'some-module' + result directly instead of the full module. + + Useful for eg module.exports = function() {} +*/ +hook('import', function(systemImport) { + return function(name, parentName, parentAddress) { + if (parentName && parentName.name) + warn.call(this, 'SystemJS.import(name, { name: parentName }) is deprecated for SystemJS.import(name, parentName), while importing ' + name + ' from ' + parentName.name); + return systemImport.call(this, name, parentName, parentAddress).then(function(module) { + return module.__useDefault ? module['default'] : module; + }); + }; +}); + +/* + * Allow format: 'detect' meta to enable format detection + */ +hook('translate', function(systemTranslate) { + return function(load) { + if (load.metadata.format == 'detect') + load.metadata.format = undefined; + return systemTranslate.apply(this, arguments); + }; +}); + + +/* + * JSON format support + * + * Supports loading JSON files as a module format itself + * + * Usage: + * + * SystemJS.config({ + * meta: { + * '*.json': { format: 'json' } + * } + * }); + * + * Module is returned as if written: + * + * export default {JSON} + * + * No named exports are provided + * + * Files ending in ".json" are treated as json automatically by SystemJS + */ +hook('instantiate', function(instantiate) { + return function(load) { + if (load.metadata.format == 'json' && !this.builder) { + var entry = load.metadata.entry = createEntry(); + entry.deps = []; + entry.execute = function() { + try { + return JSON.parse(load.source); + } + catch(e) { + throw new Error("Invalid JSON file " + load.name); + } + }; + } + }; +}) + +/* + Extend config merging one deep only + + loader.config({ + some: 'random', + config: 'here', + deep: { + config: { too: 'too' } + } + }); + + <=> + + loader.some = 'random'; + loader.config = 'here' + loader.deep = loader.deep || {}; + loader.deep.config = { too: 'too' }; + + + Normalizes meta and package configs allowing for: + + SystemJS.config({ + meta: { + './index.js': {} + } + }); + + To become + + SystemJS.meta['https://thissite.com/index.js'] = {}; + + For easy normalization canonicalization with latest URL support. + +*/ +function envSet(loader, cfg, envCallback) { + if (envModule.browser && cfg.browserConfig) + envCallback(cfg.browserConfig); + if (envModule.node && cfg.nodeConfig) + envCallback(cfg.nodeConfig); + if (envModule.dev && cfg.devConfig) + envCallback(cfg.devConfig); + if (envModule.build && cfg.buildConfig) + envCallback(cfg.buildConfig); + if (envModule.production && cfg.productionConfig) + envCallback(cfg.productionConfig); +} + +SystemJSLoader.prototype.getConfig = function(name) { + var cfg = {}; + var loader = this; + for (var p in loader) { + if (loader.hasOwnProperty && !loader.hasOwnProperty(p) || p in SystemJSLoader.prototype && p != 'transpiler') + continue; + if (indexOf.call(['_loader', 'amdDefine', 'amdRequire', 'defined', 'failed', 'version', 'loads'], p) == -1) + cfg[p] = loader[p]; + } + cfg.production = envModule.production; + return cfg; +}; + +var curCurScript; +SystemJSLoader.prototype.config = function(cfg, isEnvConfig) { + var loader = this; + + if ('loaderErrorStack' in cfg) { + curCurScript = $__curScript; + if (cfg.loaderErrorStack) + $__curScript = undefined; + else + $__curScript = curCurScript; + } + + if ('warnings' in cfg) + loader.warnings = cfg.warnings; + + // transpiler deprecation path + if (cfg.transpilerRuntime === false) + loader._loader.loadedTranspilerRuntime = true; + + if ('production' in cfg || 'build' in cfg) + setProduction.call(loader, !!cfg.production, !!(cfg.build || envModule && envModule.build)); + + if (!isEnvConfig) { + // if using nodeConfig / browserConfig / productionConfig, take baseURL from there + // these exceptions will be unnecessary when we can properly implement config queuings + var baseURL; + envSet(loader, cfg, function(cfg) { + baseURL = baseURL || cfg.baseURL; + }); + baseURL = baseURL || cfg.baseURL; + + // always configure baseURL first + if (baseURL) { + var hasConfig = false; + function checkHasConfig(obj) { + for (var p in obj) + if (obj.hasOwnProperty(p)) + return true; + } + if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths)) + throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.'); + + this.baseURL = baseURL; + prepareBaseURL.call(this); + } + + if (cfg.paths) + extend(loader.paths, cfg.paths); + + envSet(loader, cfg, function(cfg) { + if (cfg.paths) + extend(loader.paths, cfg.paths); + }); + + // warn on wildcard path deprecations + if (this.warnings) { + for (var p in loader.paths) + if (p.indexOf('*') != -1) + warn.call(loader, 'Paths configuration "' + p + '" -> "' + loader.paths[p] + '" uses wildcards which are being deprecated for simpler trailing "/" folder paths.'); + } + } + + if (cfg.defaultJSExtensions) { + loader.defaultJSExtensions = cfg.defaultJSExtensions; + warn.call(loader, 'The defaultJSExtensions configuration option is deprecated, use packages configuration instead.'); + } + + if (cfg.pluginFirst) + loader.pluginFirst = cfg.pluginFirst; + + if (cfg.map) { + var objMaps = ''; + for (var p in cfg.map) { + var v = cfg.map[p]; + + // object map backwards-compat into packages configuration + if (typeof v !== 'string') { + objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"'; + + var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js'; + var prop = loader.decanonicalize(p); + if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js') + prop = prop.substr(0, prop.length - 3); + + // if a package main, revert it + var pkgMatch = ''; + for (var pkg in loader.packages) { + if (prop.substr(0, pkg.length) == pkg + && (!prop[pkg.length] || prop[pkg.length] == '/') + && pkgMatch.split('/').length < pkg.split('/').length) + pkgMatch = pkg; + } + if (pkgMatch && loader.packages[pkgMatch].main) + prop = prop.substr(0, prop.length - loader.packages[pkgMatch].main.length - 1); + + var pkg = loader.packages[prop] = loader.packages[prop] || {}; + pkg.map = v; + } + else { + loader.map[p] = v; + } + } + if (objMaps) + warn.call(loader, 'The map configuration for ' + objMaps + ' uses object submaps, which is deprecated in global map.\nUpdate this to use package contextual map with configs like SystemJS.config({ packages: { "' + p + '": { map: {...} } } }).'); + } + + if (cfg.packageConfigPaths) { + var packageConfigPaths = []; + for (var i = 0; i < cfg.packageConfigPaths.length; i++) { + var path = cfg.packageConfigPaths[i]; + var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/')); + var normalized = coreResolve.call(loader, path.substr(0, packageLength)); + packageConfigPaths[i] = normalized + path.substr(packageLength); + } + loader.packageConfigPaths = packageConfigPaths; + } + + if (cfg.bundles) { + for (var p in cfg.bundles) { + var bundle = []; + for (var i = 0; i < cfg.bundles[p].length; i++) { + var defaultJSExtension = loader.defaultJSExtensions && cfg.bundles[p][i].substr(cfg.bundles[p][i].length - 3, 3) != '.js'; + var normalizedBundleDep = loader.decanonicalize(cfg.bundles[p][i]); + if (defaultJSExtension && normalizedBundleDep.substr(normalizedBundleDep.length - 3, 3) == '.js') + normalizedBundleDep = normalizedBundleDep.substr(0, normalizedBundleDep.length - 3); + bundle.push(normalizedBundleDep); + } + loader.bundles[p] = bundle; + } + } + + if (cfg.packages) { + for (var p in cfg.packages) { + if (p.match(/^([^\/]+:)?\/\/$/)) + throw new TypeError('"' + p + '" is not a valid package name.'); + + var prop = coreResolve.call(loader, p); + + // allow trailing slash in packages + if (prop[prop.length - 1] == '/') + prop = prop.substr(0, prop.length - 1); + + setPkgConfig(loader, prop, cfg.packages[p], false); + } + } + + for (var c in cfg) { + var v = cfg[c]; + + if (indexOf.call(['baseURL', 'map', 'packages', 'bundles', 'paths', 'warnings', 'packageConfigPaths', + 'loaderErrorStack', 'browserConfig', 'nodeConfig', 'devConfig', 'buildConfig', 'productionConfig'], c) != -1) + continue; + + if (typeof v != 'object' || v instanceof Array) { + loader[c] = v; + } + else { + loader[c] = loader[c] || {}; + + for (var p in v) { + // base-level wildcard meta does not normalize to retain catch-all quality + if (c == 'meta' && p[0] == '*') { + extend(loader[c][p] = loader[c][p] || {}, v[p]); + } + else if (c == 'meta') { + // meta can go through global map, with defaultJSExtensions adding + var resolved = coreResolve.call(loader, p); + if (loader.defaultJSExtensions && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved)) + resolved += '.js'; + extend(loader[c][resolved] = loader[c][resolved] || {}, v[p]); + } + else if (c == 'depCache') { + var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js'; + var prop = loader.decanonicalize(p); + if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js') + prop = prop.substr(0, prop.length - 3); + loader[c][prop] = [].concat(v[p]); + } + else { + loader[c][p] = v[p]; + } + } + } + } + + envSet(loader, cfg, function(cfg) { + loader.config(cfg, true); + }); +};/* + * Package Configuration Extension + * + * Example: + * + * SystemJS.packages = { + * jquery: { + * main: 'index.js', // when not set, package name is requested directly + * format: 'amd', + * defaultExtension: 'ts', // defaults to 'js', can be set to false + * modules: { + * '*.ts': { + * loader: 'typescript' + * }, + * 'vendor/sizzle.js': { + * format: 'global' + * } + * }, + * map: { + * // map internal require('sizzle') to local require('./vendor/sizzle') + * sizzle: './vendor/sizzle.js', + * // map any internal or external require of 'jquery/vendor/another' to 'another/index.js' + * './vendor/another.js': './another/index.js', + * // test.js / test -> lib/test.js + * './test.js': './lib/test.js', + * + * // environment-specific map configurations + * './index.js': { + * '~browser': './index-node.js', + * './custom-condition.js|~export': './index-custom.js' + * } + * }, + * // allows for setting package-prefixed depCache + * // keys are normalized module names relative to the package itself + * depCache: { + * // import 'package/index.js' loads in parallel package/lib/test.js,package/vendor/sizzle.js + * './index.js': ['./test'], + * './test.js': ['external-dep'], + * 'external-dep/path.js': ['./another.js'] + * } + * } + * }; + * + * Then: + * import 'jquery' -> jquery/index.js + * import 'jquery/submodule' -> jquery/submodule.js + * import 'jquery/submodule.ts' -> jquery/submodule.ts loaded as typescript + * import 'jquery/vendor/another' -> another/index.js + * + * Detailed Behaviours + * - main can have a leading "./" can be added optionally + * - map and defaultExtension are applied to the main + * - defaultExtension adds the extension only if the exact extension is not present + * - defaultJSExtensions applies after map when defaultExtension is not set + * - if a meta value is available for a module, map and defaultExtension are skipped + * - like global map, package map also applies to subpaths (sizzle/x, ./vendor/another/sub) + * - condition module map is '@env' module in package or '@system-env' globally + * - map targets support conditional interpolation ('./x': './x.#{|env}.js') + * - internal package map targets cannot use boolean conditionals + * + * Package Configuration Loading + * + * Not all packages may already have their configuration present in the System config + * For these cases, a list of packageConfigPaths can be provided, which when matched against + * a request, will first request a ".json" file by the package name to derive the package + * configuration from. This allows dynamic loading of non-predetermined code, a key use + * case in SystemJS. + * + * Example: + * + * SystemJS.packageConfigPaths = ['packages/test/package.json', 'packages/*.json']; + * + * // will first request 'packages/new-package/package.json' for the package config + * // before completing the package request to 'packages/new-package/path' + * SystemJS.import('packages/new-package/path'); + * + * // will first request 'packages/test/package.json' before the main + * SystemJS.import('packages/test'); + * + * When a package matches packageConfigPaths, it will always send a config request for + * the package configuration. + * The package name itself is taken to be the match up to and including the last wildcard + * or trailing slash. + * The most specific package config path will be used. + * Any existing package configurations for the package will deeply merge with the + * package config, with the existing package configurations taking preference. + * To opt-out of the package configuration request for a package that matches + * packageConfigPaths, use the { configured: true } package config option. + * + */ +(function() { + + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + this.packages = {}; + this.packageConfigPaths = []; + }; + }); + + function getPackage(loader, normalized) { + // use most specific package + var curPkg, curPkgLen = 0, pkgLen; + for (var p in loader.packages) { + if (normalized.substr(0, p.length) === p && (normalized.length === p.length || normalized[p.length] === '/')) { + pkgLen = p.split('/').length; + if (pkgLen > curPkgLen) { + curPkg = p; + curPkgLen = pkgLen; + } + } + } + return curPkg; + } + + function addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions) { + // don't apply extensions to folders or if defaultExtension = false + if (!subPath || subPath[subPath.length - 1] == '/' || skipExtensions || pkg.defaultExtension === false) + return subPath; + + var metaMatch = false; + + // exact meta or meta with any content after the last wildcard skips extension + if (pkg.meta) + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + // exact global meta or meta with any content after the last wildcard skips extension + if (!metaMatch && loader.meta) + getMetaMatches(loader.meta, pkgName + '/' + subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + if (metaMatch) + return subPath; + + // work out what the defaultExtension is and add if not there already + // NB reconsider if default should really be ".js"? + var defaultExtension = '.' + (pkg.defaultExtension || 'js'); + if (subPath.substr(subPath.length - defaultExtension.length) != defaultExtension) + return subPath + defaultExtension; + else + return subPath; + } + + function applyPackageConfigSync(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return pkgName + (loader.defaultJSExtensions ? '.js' : ''); + } + + // map config checking without then with extensions + if (pkg.map) { + var mapPath = './' + subPath; + + var mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + if (mapMatch) { + var mapped = doMapSync(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions); + if (mapped) + return mapped; + } + } + + // normal package resolution + return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + } + + function validMapping(mapMatch, mapped, pkgName, path) { + // disallow internal to subpath maps + if (mapMatch == '.') + throw new Error('Package ' + pkgName + ' has a map entry for "." which is not permitted.'); + + // allow internal ./x -> ./x/y or ./x/ -> ./x/y recursive maps + // but only if the path is exactly ./x and not ./x/z + if (mapped.substr(0, mapMatch.length) == mapMatch && path.length > mapMatch.length) + return false; + + return true; + } + + function doMapSync(loader, pkg, pkgName, mapMatch, path, skipExtensions) { + if (path[path.length - 1] == '/') + path = path.substr(0, path.length - 1); + var mapped = pkg.map[mapMatch]; + + if (typeof mapped == 'object') + throw new Error('Synchronous conditional normalization not supported sync normalizing ' + mapMatch + ' in ' + pkgName); + + if (!validMapping(mapMatch, mapped, pkgName, path) || typeof mapped != 'string') + return; + + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions); + + // external map reference + return loader.normalizeSync(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function applyPackageConfig(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return Promise.resolve(pkgName + (loader.defaultJSExtensions ? '.js' : '')); + } + + // map config checking without then with extensions + var mapPath, mapMatch; + + if (pkg.map) { + mapPath = './' + subPath; + mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + } + + return (mapMatch ? doMap(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions) : Promise.resolve()) + .then(function(mapped) { + if (mapped) + return Promise.resolve(mapped); + + // normal package resolution / fallback resolution for no conditional match + return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions)); + }); + } + + function doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions) { + // NB the interpolation cases should strictly skip subsequent interpolation + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions)) + .then(function(name) { + return interpolateConditional.call(loader, name, pkgName + '/'); + }); + + // external map reference + return loader.normalize(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function doMap(loader, pkg, pkgName, mapMatch, path, skipExtensions) { + if (path[path.length - 1] == '/') + path = path.substr(0, path.length - 1); + + var mapped = pkg.map[mapMatch]; + + if (typeof mapped == 'string') { + if (!validMapping(mapMatch, mapped, pkgName, path)) + return Promise.resolve(); + return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions); + } + + // we use a special conditional syntax to allow the builder to handle conditional branch points further + if (loader.builder) + return Promise.resolve(pkgName + '/#:' + path); + + // we load all conditions upfront + var conditionPromises = []; + var conditions = []; + for (var e in mapped) { + var c = parseCondition(e); + conditions.push({ + condition: c, + map: mapped[e] + }); + conditionPromises.push(loader['import'](c.module, pkgName)); + } + + // map object -> conditional map + return Promise.all(conditionPromises) + .then(function(conditionValues) { + // first map condition to match is used + for (var i = 0; i < conditions.length; i++) { + var c = conditions[i].condition; + var value = readMemberExpression(c.prop, conditionValues[i]); + if (!c.negate && value || c.negate && !value) + return conditions[i].map; + } + }) + .then(function(mapped) { + if (mapped) { + if (!validMapping(mapMatch, mapped, pkgName, path)) + return; + return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions); + } + + // no environment match -> fallback to original subPath by returning undefined + }); + } + + // normalizeSync = decanonicalize + package resolution + SystemJSLoader.prototype.normalizeSync = SystemJSLoader.prototype.decanonicalize = SystemJSLoader.prototype.normalize; + + // decanonicalize must JUST handle package defaultExtension: false case when defaultJSExtensions is set + // to be deprecated! + hook('decanonicalize', function(decanonicalize) { + return function(name, parentName) { + if (this.builder) + return decanonicalize.call(this, name, parentName, true); + + var decanonicalized = decanonicalize.call(this, name, parentName, false); + + if (!this.defaultJSExtensions) + return decanonicalized; + + var pkgName = getPackage(this, decanonicalized); + + var pkg = this.packages[pkgName]; + var defaultExtension = pkg && pkg.defaultExtension; + + if (defaultExtension == undefined && pkg && pkg.meta) + getMetaMatches(pkg.meta, decanonicalized.substr(pkgName), function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) { + defaultExtension = false; + return true; + } + }); + + if ((defaultExtension === false || defaultExtension && defaultExtension != '.js') && name.substr(name.length - 3, 3) != '.js' && decanonicalized.substr(decanonicalized.length - 3, 3) == '.js') + decanonicalized = decanonicalized.substr(0, decanonicalized.length - 3); + + return decanonicalized; + }; + }); + + hook('normalizeSync', function(normalizeSync) { + return function(name, parentName, isPlugin) { + var loader = this; + isPlugin = isPlugin === true; + + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name[0] != '.') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch && typeof parentMap[parentMapMatch] == 'string') { + var mapped = doMapSync(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin); + if (mapped) + return mapped; + } + } + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalizeSync.call(loader, name, parentName, false); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return normalized + (defaultJSExtension ? '.js' : ''); + + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfigSync(loader, loader.packages[pkgName] || {}, pkgName, subPath, isPlugin); + }; + }); + + hook('normalize', function(normalize) { + return function(name, parentName, isPlugin) { + var loader = this; + isPlugin = isPlugin === true; + + return Promise.resolve() + .then(function() { + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name.substr(0, 2) != './') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch) + return doMap(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin); + } + + return Promise.resolve(); + }) + .then(function(mapped) { + if (mapped) + return mapped; + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalize.call(loader, name, parentName, false); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return Promise.resolve(normalized + (defaultJSExtension ? '.js' : '')); + + var pkg = loader.packages[pkgName]; + + // if package is already configured or not a dynamic config package, use existing package config + var isConfigured = pkg && (pkg.configured || !pkgConfigMatch); + return (isConfigured ? Promise.resolve(pkg) : loadPackageConfigPath(loader, pkgName, pkgConfigMatch.configPath)) + .then(function(pkg) { + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfig(loader, pkg, pkgName, subPath, isPlugin); + }); + }); + }; + }); + + // check if the given normalized name matches a packageConfigPath + // if so, loads the config + var packageConfigPaths = {}; + + // data object for quick checks against package paths + function createPkgConfigPathObj(path) { + var lastWildcard = path.lastIndexOf('*'); + var length = Math.max(lastWildcard + 1, path.lastIndexOf('/')); + return { + length: length, + regEx: new RegExp('^(' + path.substr(0, length).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^\\/]+') + ')(\\/|$)'), + wildcard: lastWildcard != -1 + }; + } + + // most specific match wins + function getPackageConfigMatch(loader, normalized) { + var pkgName, exactMatch = false, configPath; + for (var i = 0; i < loader.packageConfigPaths.length; i++) { + var packageConfigPath = loader.packageConfigPaths[i]; + var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath)); + if (normalized.length < p.length) + continue; + var match = normalized.match(p.regEx); + if (match && (!pkgName || (!(exactMatch && p.wildcard) && pkgName.length < match[1].length))) { + pkgName = match[1]; + exactMatch = !p.wildcard; + configPath = pkgName + packageConfigPath.substr(p.length); + } + } + + if (!pkgName) + return; + + return { + packageName: pkgName, + configPath: configPath + }; + } + + function loadPackageConfigPath(loader, pkgName, pkgConfigPath) { + var configLoader = loader.pluginLoader || loader; + + // NB remove this when json is default + (configLoader.meta[pkgConfigPath] = configLoader.meta[pkgConfigPath] || {}).format = 'json'; + configLoader.meta[pkgConfigPath].loader = null; + + return configLoader.load(pkgConfigPath) + .then(function() { + var cfg = configLoader.get(pkgConfigPath)['default']; + + // support "systemjs" prefixing + if (cfg.systemjs) + cfg = cfg.systemjs; + + // modules backwards compatibility + if (cfg.modules) { + cfg.meta = cfg.modules; + warn.call(loader, 'Package config file ' + pkgConfigPath + ' is configured with "modules", which is deprecated as it has been renamed to "meta".'); + } + + return setPkgConfig(loader, pkgName, cfg, true); + }); + } + + function getMetaMatches(pkgMeta, subPath, matchFn) { + // wildcard meta + var meta = {}; + var wildcardIndex; + for (var module in pkgMeta) { + // allow meta to start with ./ for flexibility + var dotRel = module.substr(0, 2) == './' ? './' : ''; + if (dotRel) + module = module.substr(2); + + wildcardIndex = module.indexOf('*'); + if (wildcardIndex === -1) + continue; + + if (module.substr(0, wildcardIndex) == subPath.substr(0, wildcardIndex) + && module.substr(wildcardIndex + 1) == subPath.substr(subPath.length - module.length + wildcardIndex + 1)) { + // alow match function to return true for an exit path + if (matchFn(module, pkgMeta[dotRel + module], module.split('/').length)) + return; + } + } + // exact meta + var exactMeta = pkgMeta[subPath] && pkgMeta.hasOwnProperty && pkgMeta.hasOwnProperty(subPath) ? pkgMeta[subPath] : pkgMeta['./' + subPath]; + if (exactMeta) + matchFn(exactMeta, exactMeta, 0); + } + + hook('locate', function(locate) { + return function(load) { + var loader = this; + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + var pkgName = getPackage(loader, load.name); + if (pkgName) { + var pkg = loader.packages[pkgName]; + var subPath = load.name.substr(pkgName.length + 1); + + var meta = {}; + if (pkg.meta) { + var bestDepth = 0; + + // NB support a main shorthand in meta here? + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth > bestDepth) + bestDepth = matchDepth; + extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth); + }); + + extendMeta(load.metadata, meta); + } + + // format + if (pkg.format && !load.metadata.loader) + load.metadata.format = load.metadata.format || pkg.format; + } + + return address; + }); + }; + }); + +})(); +/* + * Script tag fetch + * + * When load.metadata.scriptLoad is true, we load via script tag injection. + */ +(function() { + + if (typeof document != 'undefined') + var head = document.getElementsByTagName('head')[0]; + + var curSystem; + var curRequire; + + // if doing worker executing, this is set to the load record being executed + var workerLoad = null; + + // interactive mode handling method courtesy RequireJS + var ieEvents = head && (function() { + var s = document.createElement('script'); + var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]'; + return s.attachEvent && !(s.attachEvent.toString && s.attachEvent.toString().indexOf('[native code') < 0) && !isOpera; + })(); + + // IE interactive-only part + // we store loading scripts array as { script: ')}else e()}else if("undefined"!=typeof importScripts){var a="";try{throw new Error("_")}catch(e){e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/,function(e,t){$__curScript={src:t},a=t.replace(/\/[^\/]*$/,"/")})}t&&importScripts(a+"system-polyfills.js"),e()}else $__curScript="undefined"!=typeof __filename?{src:__filename}:null,e()}(); +//# sourceMappingURL=system.js.map diff --git a/node_modules/systemjs/dist/system.js.map b/node_modules/systemjs/dist/system.js.map new file mode 100644 index 0000000..95326bb --- /dev/null +++ b/node_modules/systemjs/dist/system.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["system.src.js"],"names":["bootstrap","global","URLPolyfill","url","baseURL","TypeError","m","String","replace","match","RangeError","protocol","username","password","host","hostname","port","pathname","search","hash","undefined","base","flag","slice","lastIndexOf","output","p","pop","push","join","this","origin","href","self","__global","addToError","err","msg","originalErr","stack","message","toString","split","newStack","i","length","$__curScript","indexOf","src","newMsg","substr","isBrowser","isWindows","newErr","errArgs","Error","fileName","lineNumber","Module","Loader","options","_loader","loaderObj","loads","modules","importPromises","moduleRecords","defineProperty","get","SystemJSLoader","call","paths","systemJSConstructor","SystemProto","hook","name","prototype","hookConstructor","isAbsolute","absURLRegEx","isRel","isPlain","urlResolve","parent","baseURI","URL","baseURIObj","applyPaths","loader","wildcard","pathMatch","maxWildcardPrefixLen","pathsCache","hasOwnProperty","path","pathParts","wildcardPrefixLen","outPath","group","deps","names","indices","l","index","getESModule","exports","esModule","getOwnPropertyDescriptor","defineOrCopyProperty","extend","value","targetObj","sourceObj","propName","d","Object","ex","a","b","prepend","extendMeta","val","Array","concat","extendPkgConfig","pkgCfgA","pkgCfgB","pkgName","warnInvalidProperties","prop","map","meta","depCache","dNormalized","coreResolve","warn","setPkgConfig","cfg","prependConfig","pkg","packages","basePkg","main","warnings","console","readMemberExpression","pParts","shift","getMapMatch","bestMatch","bestMatchLength","curMatchLength","prepareBaseURL","setProduction","isProduction","isBuilder","set","envModule","newModule","browser","node","_nodeRequire","production","dev","build","default","getNodeModule","parentModuleContext","_nodeModulePaths","require","parentName","mapMatch","has","builder","envSet","envCallback","browserConfig","nodeConfig","devConfig","buildConfig","productionConfig","detectRegisterFormat","source","leadingCommentAndMeta","leadingCommentAndMetaRegEx","createEntry","originalIndices","declare","execute","executingRequire","declarative","normalizedDeps","groupIndex","evaluated","module","esmExports","getGlobalValue","globalValue","first","parseCondition","condition","conditionExport","conditionModule","negation","conditionExportIndex","sysConditions","negate","serializeCondition","conditionObj","resolveCondition","bool","normalize","then","normalizedCondition","load","q","interpolateConditional","conditionalMatch","interpolationRegEx","Promise","resolve","conditionValue","booleanConditional","booleanIndex","isWorker","window","importScripts","document","process","platform","assert","item","thisLen","e","obj","opt","getElementsByTagName","bases","location","cwd","nativeURL","createLoad","status","anonCnt","linkSets","dependencies","metadata","loadModule","asyncStartLoadPartwayThrough","step","address","moduleName","moduleMetadata","moduleSource","moduleAddress","requestLoad","request","refererName","refererAddress","reject","proceedToLocate","proceedToFetch","locate","proceedToTranslate","fetch","translate","instantiate","instantiateResult","depsList","loadPromises","depLoad","key","addLoadToLinkSet","all","updateLinkSetOnLoad","exc","exception","linkSetFailed","stepState","existingLoad","done","linkSet","createLinkSet","startingLoad","loadingCount","j","doLink","error","link","_newModule","finishLoad","abrupt","checkError","pLoad","dep","failed","linkIndex","splice","globalLoadsIndex","trace","depMap","forEach","loadIndex","doDynamicExecute","linkError","createImportPromise","promise","constructor","define","delete","import","parentAddress","sourcePromise","pNames","getOwnPropertyNames","configurable","enumerable","freeze","referrerName","referrerAddress","System","fetchTextFromURL","XMLHttpRequest","authorization","fulfill","xhr","responseText","statusText","sameDomain","doTimeout","domainCheck","exec","XDomainRequest","onload","onerror","ontimeout","onprogress","timeout","onreadystatechange","readyState","addEventListener","open","setRequestHeader","withCredentials","setTimeout","send","fs","readFile","data","dataString","opts","headers","Accept","credentials","r","ok","text","transpile","transpiler","pluginLoader","__useDefault","transpileFunction","Compiler","traceurTranspile","createLanguageService","typescriptTranspile","babelTranspile","traceur","traceurOptions","script","sourceMaps","filename","inputSourceMap","sourceMap","compiler","doTraceurCompile","compile","babel","babelOptions","code","ast","transform","ts","typescriptOptions","target","ScriptTarget","ES5","inlineSourceMap","ModuleKind","__exec","sourceMapString","hasBuffer","sourceMapPrefix","Buffer","btoa","unescape","encodeURIComponent","getSource","wrap","lastLineIndex","format","JSON","stringify","preExec","curLoad","callCounter","curSystem","SystemJS","postExec","scriptExec","head","body","documentElement","createElement","_e","apply","arguments","integrity","setAttribute","nonce","appendChild","removeChild","register","reduceRegister_","useVm","vm","supportsScriptExec","runInThisContext","eval","scripts","chrome","extension","navigator","userAgent","scriptSrc","defaultJSExtensions","pluginFirst","loaderErrorStack","skipExt","resolved","httpRequest","systemImport","systemTranslate","entry","parse","getConfig","curCurScript","config","isEnvConfig","checkHasConfig","transpilerRuntime","loadedTranspilerRuntime","bundles","packageConfigPaths","objMaps","v","defaultJSExtension","decanonicalize","pkgMatch","packageLength","Math","max","normalized","bundle","normalizedBundleDep","c","getPackage","curPkg","pkgLen","curPkgLen","addDefaultExtension","subPath","skipExtensions","defaultExtension","metaMatch","getMetaMatches","metaPattern","matchMeta","matchDepth","applyPackageConfigSync","mapPath","mapped","doMapSync","validMapping","normalizeSync","applyPackageConfig","doMap","doStringMap","conditionPromises","conditions","conditionValues","createPkgConfigPathObj","lastWildcard","regEx","RegExp","getPackageConfigMatch","configPath","exactMatch","packageConfigPath","packageName","loadPackageConfigPath","pkgConfigPath","configLoader","systemjs","pkgMeta","matchFn","wildcardIndex","dotRel","exactMeta","decanonicalized","isPlugin","parentPackageName","parentPackage","parentMap","parentMapMatch","pkgConfigMatch","isConfigured","configured","bestDepth","getInteractiveScriptLoad","interactiveScript","interactiveLoadingScripts","webWorkerImport","workerLoad","curRequire","ieEvents","s","isOpera","opera","attachEvent","loadingCnt","registerQueue","pushRegister","scriptLoad","complete","evt","cleanup","detachEvent","removeEventListener","async","crossOrigin","buildGroups","groups","depName","depEntry","defined","depGroupIndex","startEntry","curGroupDeclarative","linkDeclarativeModule","linkDynamicModule","ModuleRecord","getOrCreateModuleRecord","importers","declaration","locked","importerModule","importerIndex","setter","setters","id","depExports","depModule","len","getModule","ensureEvaluated","nameNormalized","__esModule","seen","registerDynamic","pushRegister_","amd","curMeta","del","doLoad","grouped","normalizePromises","esmRegEx","traceurRuntimeRegEx","babelHelpersRegEx","args","depInject","loadedTranspiler","transpilerPromise","loaderModule","originalName","file","sources","originalSource","$traceurRuntime","babelHelpers","__globalName","g","globals","gl","exportName","retrieveGlobal","prepareGlobal","encapsulateGlobal","reduceRegister","forEachGlobal","callback","keys","forEachGlobalValue","globalName","ignoredGlobalProps","globalSnapshot","encapsulate","curDefine","oldGlobals","singleGlobal","multipleExports","getCJSDeps","inLocation","locations","cjsRequireRegEx","lastIndex","commentRegEx","stringRegEx","stringLocations","commentLocations","cjsExportsRegEx","hashBangRegEx","metaDeps","cjsRequireDetection","_require","requireResolve","cjsDeferDepsExecute","pathVars","getPathVars","__cjsWrapper","dirname","cjsWrapper","stripOrigin","windowOrigin","parentId","moduleId","pluginIndex","amdDefine","requireIndex","params","fnBracketRegEx","requireAlias","wsRegEx","requireRegEx","requireRegExs","cjsRequirePre","cjsRequirePost","errback","referer","dynamicRequires","factory","req","contextualRequire","depValues","uri","moduleIndex","exportsIndex","toUrl","amdRequire","amdRegEx","builderExecute","getParentName","parentPluginIndex","parsePlugin","argumentName","pluginName","argument","plugin","combinePluginParts","checkDefaultExtension","arg","createNormalizeSync","parsed","pluginSyntaxIndex","loaderNormalized","result","calledInstantiate","alias","aliasDeps","_export","setMetaProperty","curPart","depth","metaRegEx","metaPartRegEx","metaParts","firstChar","metaString","metaName","metaValue","loadedBundles","matched","curModule","parts","substring","version","doPolyfill","currentScript","defer","curPath","basePath","systemJSBootstrap","write","__filename"],"mappings":";;;CAGA,WACA,QAASA,MACT,SAAUC,GACV,QAASC,GAAYC,EAAKC,GACxB,GAAkB,gBAAPD,GACT,KAAM,IAAIE,WAAU,uBACtB,IAAIC,GAAIC,OAAOJ,GAAKK,QAAQ,aAAc,IAAIC,MAAM,mHACpD,KAAKH,EACH,KAAM,IAAII,YAAW,qBACvB,IAAIC,GAAWL,EAAE,IAAM,GACnBM,EAAWN,EAAE,IAAM,GACnBO,EAAWP,EAAE,IAAM,GACnBQ,EAAOR,EAAE,IAAM,GACfS,EAAWT,EAAE,IAAM,GACnBU,EAAOV,EAAE,IAAM,GACfW,EAAWX,EAAE,IAAM,GACnBY,EAASZ,EAAE,IAAM,GACjBa,EAAOb,EAAE,IAAM,EACnB,IAAgBc,SAAZhB,EAAuB,CACzB,GAAIiB,GAAOjB,YAAmBF,GAAcE,EAAU,GAAIF,GAAYE,GAClEkB,GAAQX,IAAaG,IAASF,GAC9BU,GAASL,GAAaC,IACxBA,EAASG,EAAKH,QACZI,GAAwB,MAAhBL,EAAS,KACnBA,EAAYA,IAAcI,EAAKP,OAAQO,EAAKT,UAAcS,EAAKJ,SAAiB,GAAN,KAAYI,EAAKJ,SAASM,MAAM,EAAGF,EAAKJ,SAASO,YAAY,KAAO,GAAKP,EAAYI,EAAKJ,SAEtK,IAAIQ,KACJR,GAAST,QAAQ,kBAAmB,IACjCA,QAAQ,iBAAkB,KAC1BA,QAAQ,UAAW,QACnBA,QAAQ,aAAc,SAAUkB,GACrB,QAANA,EACFD,EAAOE,MAEPF,EAAOG,KAAKF,KAElBT,EAAWQ,EAAOI,KAAK,IAAIrB,QAAQ,MAAuB,MAAhBS,EAAS,GAAa,IAAM,IAClEK,IACFN,EAAOK,EAAKL,KACZD,EAAWM,EAAKN,SAChBD,EAAOO,EAAKP,KACZD,EAAWQ,EAAKR,SAChBD,EAAWS,EAAKT,UAEbD,IACHA,EAAWU,EAAKV,UAIpBM,EAAWA,EAAST,QAAQ,MAAO,KAEnCsB,KAAKC,OAASjB,EAAOH,GAAyB,KAAbA,GAA4B,KAATG,EAAc,KAAO,IAAMA,EAAO,GACtFgB,KAAKE,KAAOrB,GAAYA,GAAYG,GAAoB,SAAZH,EAAsB,KAAO,KAAoB,KAAbC,EAAkBA,GAAyB,KAAbC,EAAkB,IAAMA,EAAW,IAAM,IAAM,IAAMC,EAAOG,EAAWC,EAASC,EAC9LW,KAAKnB,SAAWA,EAChBmB,KAAKlB,SAAWA,EAChBkB,KAAKjB,SAAWA,EAChBiB,KAAKhB,KAAOA,EACZgB,KAAKf,SAAWA,EAChBe,KAAKd,KAAOA,EACZc,KAAKb,SAAWA,EAChBa,KAAKZ,OAASA,EACdY,KAAKX,KAAOA,EAEdlB,EAAOC,YAAcA,GACH,mBAAR+B,MAAsBA,KAAOhC,QAAQ,SAAUiC,GAqCvD,QAASC,GAAWC,EAAKC,GAEvB,IAAKD,EAAIE,YAGP,IAAK,GAFDC,KAAUH,EAAII,SAAWJ,IAAQA,EAAIG,MAAQ,KAAOH,EAAIG,MAAQ,KAAKE,WAAWC,MAAM,MACtFC,KACKC,EAAI,EAAGA,EAAIL,EAAMM,OAAQD,IACL,mBAAhBE,eAA+BP,EAAMK,GAAGG,QAAQD,aAAaE,OAAQ,GAC9EL,EAASf,KAAKW,EAAMK,GAI1B,IAAIK,GAAS,eAAiBN,EAAWA,EAASd,KAAK,QAAUO,EAAII,QAAQU,OAAO,KAAO,OAASb,CAG/Fc,KACHF,EAASA,EAAOzC,QAAQ4C,EAAY,eAAiB,aAAc,IAErE,IAAIC,GAASC,EAAU,GAAIC,OAAMN,EAAQb,EAAIoB,SAAUpB,EAAIqB,YAAc,GAAIF,OAAMN,EAOnF,OALAI,GAAOd,MAAQU,EAGfI,EAAOf,YAAcF,EAAIE,aAAeF,EAEjCiB,EAoEX,QAASK,MAOT,QAASC,GAAOC,GACd9B,KAAK+B,SACHC,UAAWhC,KACXiC,SACAC,WACAC,kBACAC,kBAIFC,EAAerC,KAAM,UACnBsC,IAAK,WACH,MAAOlC,MAi9Bb,QAASmC,KACPV,EAAOW,KAAKxC,MAEZA,KAAKyC,SACLzC,KAAK+B,QAAQU,SAEbC,EAAoBF,KAAKxC,MAI3B,QAAS2C,MAOT,QAASC,GAAKC,EAAMD,GAClBL,EAAeO,UAAUD,GAAQD,EAAKL,EAAeO,UAAUD,IAAS,cAE1E,QAASE,GAAgBH,GACvBF,EAAsBE,EAAKF,GAAuB,cAKpD,QAASM,GAAWH,GAClB,MAAOA,GAAKlE,MAAMsE,GAEpB,QAASC,GAAML,GACb,MAAmB,KAAXA,EAAK,MAAeA,EAAK,IAAiB,KAAXA,EAAK,IAAwB,KAAXA,EAAK,KAA0B,KAAXA,EAAK,GAEpF,QAASM,GAAQN,GACf,OAAQK,EAAML,KAAUG,EAAWH,GAKrC,QAASO,GAAWP,EAAMQ,GAExB,GAAe,KAAXR,EAAK,IAEP,GAAe,KAAXA,EAAK,IAAwB,KAAXA,EAAK,GACzB,OAAQQ,GAAUA,EAAOjC,OAAO,EAAGiC,EAAO3D,YAAY,KAAO,IAAM4D,GAAWT,EAAKzB,OAAO,OAEzF,IAAe,KAAXyB,EAAK,IAAaA,EAAK5B,QAAQ,OAAQ,EAE9C,OAAQoC,GAAUA,EAAOjC,OAAO,EAAGiC,EAAO3D,YAAY,KAAO,IAAM4D,GAAWT,CAGhF,OAAO,IAAIU,GAAIV,EAAMQ,GAAUA,EAAO3E,QAAQ,KAAM,QAAU8E,GAAYtD,KAAKxB,QAAQ,OAAQ,KAIjG,QAAS+E,GAAWC,EAAQb,GAE1B,GAAoBc,GAAhBC,EAAY,GAAcC,EAAuB,EAEjDpB,EAAQiB,EAAOjB,MACfqB,EAAaJ,EAAO3B,QAAQU,KAGhC,KAAK,GAAI7C,KAAK6C,GACZ,IAAIA,EAAMsB,gBAAmBtB,EAAMsB,eAAenE,GAAlD,CAIA,GAAIoE,GAAOvB,EAAM7C,EAKjB,IAJIoE,IAASF,EAAWlE,KACtBoE,EAAOvB,EAAM7C,GAAKkE,EAAWlE,GAAKwD,EAAWX,EAAM7C,GAAIsD,EAAMT,EAAM7C,IAAM0D,EAAUI,EAAOpF,UAGxFsB,EAAEqB,QAAQ,QAAS,EAAI,CACzB,GAAI4B,GAAQjD,EACV,MAAO6C,GAAM7C,EAGV,IAAIiD,EAAKzB,OAAO,EAAGxB,EAAEmB,OAAS,IAAMnB,EAAEwB,OAAO,EAAGxB,EAAEmB,OAAS,KAAO8B,EAAK9B,OAASnB,EAAEmB,QAAU8B,EAAKjD,EAAEmB,OAAS,IAAMnB,EAAEA,EAAEmB,OAAS,MAAyC,KAAjC0B,EAAM7C,GAAG6C,EAAM7C,GAAGmB,OAAS,IAAyB,IAAZ0B,EAAM7C,IACxL,MAAO6C,GAAM7C,GAAGwB,OAAO,EAAGqB,EAAM7C,GAAGmB,OAAS,IAAM8B,EAAK9B,OAASnB,EAAEmB,QAAU0B,EAAM7C,IAAM,KAAO,IAAMiD,EAAKzB,OAAOxB,EAAEmB,QAAU,QAI5H,CACH,GAAIkD,GAAYrE,EAAEgB,MAAM,IACxB,IAAIqD,EAAUlD,OAAS,EACrB,KAAM,IAAIxC,WAAU,2CAEtB,IAAI2F,GAAoBD,EAAU,GAAGlD,MACjCmD,IAAqBL,GACrBhB,EAAKzB,OAAO,EAAG6C,EAAU,GAAGlD,SAAWkD,EAAU,IACjDpB,EAAKzB,OAAOyB,EAAK9B,OAASkD,EAAU,GAAGlD,SAAWkD,EAAU,KAC1DJ,EAAuBK,EACvBN,EAAYhE,EACZ+D,EAAWd,EAAKzB,OAAO6C,EAAU,GAAGlD,OAAQ8B,EAAK9B,OAASkD,EAAU,GAAGlD,OAASkD,EAAU,GAAGlD,UAKvG,GAAIoD,GAAU1B,EAAMmB,EAIpB,OAHuB,gBAAZD,KACTQ,EAAUA,EAAQzF,QAAQ,IAAKiF,IAE1BQ,EAWT,QAASC,GAAMC,GAGb,IAAK,GAFDC,MACAC,KACKzD,EAAI,EAAG0D,EAAIH,EAAKtD,OAAQD,EAAI0D,EAAG1D,IAAK,CAC3C,GAAI2D,GAAQxD,EAAQuB,KAAK8B,EAAOD,EAAKvD,GACjC2D,MAAU,GACZH,EAAMxE,KAAKuE,EAAKvD,IAChByD,EAAQzE,MAAMgB,KAGdyD,EAAQE,GAAO3E,KAAKgB,GAGxB,OAASwD,MAAOA,EAAOC,QAASA,GAYlC,QAASG,GAAYC,GACnB,GAAIC,KAEJ,KAAuB,gBAAXD,IAAyC,kBAAXA,KAA0BA,IAAYvE,EAC5E,GAAIyE,EACF,IAAK,GAAIjF,KAAK+E,GAEF,YAAN/E,GAEJkF,EAAqBF,EAAUD,EAAS/E,OAI1CmF,GAAOH,EAAUD,EAOvB,OAJAC,GAAkB,QAAID,EACtBtC,EAAeuC,EAAU,gBACvBI,OAAO,IAEFJ,EAGT,QAASE,GAAqBG,EAAWC,EAAWC,GAClD,IACE,GAAIC,IACAA,EAAIC,OAAOR,yBAAyBK,EAAWC,KACjD9C,EAAe4C,EAAWE,EAAUC,GAExC,MAAOE,GAIL,MADAL,GAAUE,GAAYD,EAAUC,IACzB,GAIX,QAASJ,GAAOQ,EAAGC,EAAGC,GACpB,GAAI1B,GAAiByB,GAAKA,EAAEzB,cAC5B,KAAK,GAAInE,KAAK4F,GACRzB,IAAmByB,EAAEzB,eAAenE,IAEnC6F,GAAa7F,IAAK2F,KACrBA,EAAE3F,GAAK4F,EAAE5F,GAEb,OAAO2F,GAOT,QAASG,GAAWH,EAAGC,EAAGC,GACxB,GAAI1B,GAAiByB,GAAKA,EAAEzB,cAC5B,KAAK,GAAInE,KAAK4F,GACZ,IAAIzB,GAAmByB,EAAEzB,eAAenE,GAAxC,CAEA,GAAI+F,GAAMH,EAAE5F,EACNA,KAAK2F,GAEFI,YAAeC,QAASL,EAAE3F,YAAcgG,OAC/CL,EAAE3F,MAAQiG,OAAOJ,EAAUE,EAAMJ,EAAE3F,IAAIiG,OAAOJ,EAAUF,EAAE3F,GAAK+F,GAC1C,gBAAPA,IAA2B,OAARA,GAA+B,gBAARJ,GAAE3F,GAC1D2F,EAAE3F,GAAKmF,EAAOA,KAAWQ,EAAE3F,IAAK+F,EAAKF,GAC7BA,IACRF,EAAE3F,GAAK+F,GANPJ,EAAE3F,GAAK+F,GAUb,QAASG,GAAgBC,EAASC,EAASC,EAASvC,EAAQwC,GAC1D,IAAK,GAAIC,KAAQH,GACf,GAAI/E,EAAQuB,MAAM,OAAQ,SAAU,mBAAoB,YAAa2D,KAAS,EAC5EJ,EAAQI,GAAQH,EAAQG,OAErB,IAAY,OAARA,EACPpB,EAAOgB,EAAQK,IAAML,EAAQK,QAAWJ,EAAQI,SAE7C,IAAY,QAARD,EACPpB,EAAOgB,EAAQM,KAAON,EAAQM,SAAYL,EAAQK,UAE/C,IAAY,YAARF,EACP,IAAK,GAAIf,KAAKY,GAAQM,SAAU,CAC9B,GAAIC,EAGFA,GADoB,MAAlBnB,EAAEhE,OAAO,EAAG,GACA6E,EAAU,IAAMb,EAAEhE,OAAO,GAEzBoF,EAAYhE,KAAKkB,EAAQ0B,GACzC1B,EAAO4C,SAASC,IAAgB7C,EAAO4C,SAASC,QAAoBV,OAAOG,EAAQM,SAASlB,SAGvFc,GAAyBjF,EAAQuB,MAAM,gBAAiB,aAAc,YAAa,oBAAqB2D,KAAS,GACpHH,EAAQjC,iBAAkBiC,EAAQjC,eAAeoC,IACrDM,EAAKjE,KAAKkB,EAAQ,IAAMyC,EAAO,4DAA8DF,GAMnG,QAASS,GAAahD,EAAQuC,EAASU,EAAKC,GAC1C,GAAIC,EAGJ,IAAKnD,EAAOoD,SAASb,GAGhB,CACH,GAAIc,GAAUrD,EAAOoD,SAASb,EAC9BY,GAAMnD,EAAOoD,SAASb,MAEtBH,EAAgBe,EAAKD,EAAgBD,EAAMI,EAASd,EAASvC,EAAQkD,GACrEd,EAAgBe,EAAKD,EAAgBG,EAAUJ,EAAKV,EAASvC,GAASkD,OAPtEC,GAAMnD,EAAOoD,SAASb,GAAWU,CAkBnC,OAPuB,gBAAZE,GAAIG,OACbH,EAAIT,IAAMS,EAAIT,QACdS,EAAIT,IAAI,WAAaS,EAAIG,KACzBH,EAAIG,KAAc,QAAIH,EAAIG,KAAc,SAAK,KAC7CH,EAAIG,KAAO,SAGNH,EAGT,QAASJ,GAAKlG,GACRP,KAAKiH,UAA8B,mBAAXC,UAA0BA,QAAQT,KAoJhE,QAASU,GAAqBvH,EAAGoF,GAE/B,IADA,GAAIoC,GAASxH,EAAEgB,MAAM,KACdwG,EAAOrG,QACZiE,EAAQA,EAAMoC,EAAOC,QACvB,OAAOrC,GAGT,QAASsC,GAAYlB,EAAKvD,GACxB,GAAI0E,GAAWC,EAAkB,CAEjC,KAAK,GAAI5H,KAAKwG,GACZ,GAAIvD,EAAKzB,OAAO,EAAGxB,EAAEmB,SAAWnB,IAAMiD,EAAK9B,QAAUnB,EAAEmB,QAA4B,KAAlB8B,EAAKjD,EAAEmB,SAAiB,CACvF,GAAI0G,GAAiB7H,EAAEgB,MAAM,KAAKG,MAClC,IAAI0G,GAAkBD,EACpB,QACFD,GAAY3H,EACZ4H,EAAkBC,EAItB,MAAOF,GAGT,QAASG,GAAehE,GAElB1D,KAAK+B,QAAQzD,UAAY0B,KAAK1B,UACa,KAAzC0B,KAAK1B,QAAQ0B,KAAK1B,QAAQyC,OAAS,KACrCf,KAAK1B,SAAW,KAElB0B,KAAK+B,QAAQzD,QAAU0B,KAAK1B,QAAU,GAAIiF,GAAIvD,KAAK1B,QAASkF,GAAYtD,MAK5E,QAASyH,GAAcC,EAAcC,GACnC7H,KAAK8H,IAAI,cAAeC,GAAY/H,KAAKgI,WACvCC,QAAS5G,EACT6G,OAAQlI,KAAKmI,aACbC,YAAaP,GAAaD,EAC1BS,IAAKR,IAAcD,EACnBU,MAAOT,EACPU,SAAW,KAuDf,QAASC,GAAc3F,EAAMvE,GAC3B,IAAK6E,EAAQN,GACX,KAAM,IAAIpB,OAAM,eAAiBoB,EAAO,mDAE1C,KAAK4F,GAAqB,CACxB,GAAI7G,GAAS5B,KAAKmI,aAAa,UAC3B5I,EAAOjB,EAAQ8C,OAAOE,EAAY,EAAI,EAC1CmH,IAAsB,GAAI7G,GAAOrC,GACjCkJ,GAAoBhG,MAAQb,EAAO8G,iBAAiBnJ,GAEtD,MAAOkJ,IAAoBE,QAAQ9F,GAGrC,QAAS2D,GAAY3D,EAAM+F,GAEzB,GAAI1F,EAAML,GACR,MAAOO,GAAWP,EAAM+F,EACrB,IAAI5F,EAAWH,GAClB,MAAOA,EAGT,IAAIgG,GAAWvB,EAAYtH,KAAKoG,IAAKvD,EAErC,IAAIgG,EAAU,CAGZ,GAFAhG,EAAO7C,KAAKoG,IAAIyC,GAAYhG,EAAKzB,OAAOyH,EAAS9H,QAE7CmC,EAAML,GACR,MAAOO,GAAWP,EACf,IAAIG,EAAWH,GAClB,MAAOA,GAGX,GAAI7C,KAAK8I,IAAIjG,GACX,MAAOA,EAGT,IAAyB,UAArBA,EAAKzB,OAAO,EAAG,GAAgB,CACjC,IAAKpB,KAAKmI,aACR,KAAM,IAAI5J,WAAU,iBAAmBsE,EAAO,6CAKhD,OAJI7C,MAAK+I,QACP/I,KAAK8H,IAAIjF,EAAM7C,KAAKgI,eAEpBhI,KAAK8H,IAAIjF,EAAM7C,KAAKgI,UAAUtD,EAAY8D,EAAchG,KAAKxC,KAAM6C,EAAKzB,OAAO,GAAIpB,KAAK1B,YACnFuE,EAMT,MAFA6E,GAAelF,KAAKxC,MAEbyD,EAAWzD,KAAM6C,IAAS7C,KAAK1B,QAAUuE,EAgJlD,QAASmG,GAAOtF,EAAQiD,EAAKsC,GACvBlB,GAAUE,SAAWtB,EAAIuC,eAC3BD,EAAYtC,EAAIuC,eACdnB,GAAUG,MAAQvB,EAAIwC,YACxBF,EAAYtC,EAAIwC,YACdpB,GAAUM,KAAO1B,EAAIyC,WACvBH,EAAYtC,EAAIyC,WACdrB,GAAUO,OAAS3B,EAAI0C,aACzBJ,EAAYtC,EAAI0C,aACdtB,GAAUK,YAAczB,EAAI2C,kBAC9BL,EAAYtC,EAAI2C,kBA0hCpB,QAASC,GAAqBC,GAC5B,GAAIC,GAAwBD,EAAO7K,MAAM+K,GACzC,OAAOD,IAA+E,mBAAtDD,EAAOpI,OAAOqI,EAAsB,GAAG1I,OAAQ,IAGjF,QAAS4I,KACP,OACE9G,KAAM,KACNwB,KAAM,KACNuF,gBAAiB,KACjBC,QAAS,KACTC,QAAS,KACTC,kBAAkB,EAClBC,aAAa,EACbC,eAAgB,KAChBC,WAAY,KACZC,WAAW,EACXC,OAAQ,KACRxF,SAAU,KACVyF,YAAY,GAgxBhB,QAASC,GAAe3F,GACtB,GAAsB,gBAAXA,GACT,MAAOwC,GAAqBxC,EAASvE,EAEvC,MAAMuE,YAAmBiB,QACvB,KAAM,IAAInE,OAAM,4CAIlB,KAAK,GAFD8I,MACAC,GAAQ,EACH1J,EAAI,EAAGA,EAAI6D,EAAQ5D,OAAQD,IAAK,CACvC,GAAI6E,GAAMwB,EAAqBxC,EAAQ7D,GAAIV,EACvCoK,KACFD,EAAqB,QAAI5E,EACzB6E,GAAQ,GAEVD,EAAY5F,EAAQ7D,GAAGF,MAAM,KAAKf,OAAS8F,EAE7C,MAAO4E,GAk4BP,QAASE,GAAeC,GACtB,GAAIC,GAAiBC,EAAiBC,EAElCA,EAA2B,KAAhBH,EAAU,GACrBI,EAAuBJ,EAAUhL,YAAY,IAsBjD,OArBIoL,KAAwB,GAC1BH,EAAkBD,EAAUtJ,OAAO0J,EAAuB,GAC1DF,EAAkBF,EAAUtJ,OAAOyJ,EAAUC,EAAuBD,GAEhEA,GACFpE,EAAKjE,KAAKxC,KAAM,4BAA8B0K,EAAY,wBAA0BE,EAAkB,KAAOD,EAAkB,KAEvG,KAAtBA,EAAgB,KAClBE,GAAW,EACXF,EAAkBA,EAAgBvJ,OAAO,MAI3CuJ,EAAkB,UAClBC,EAAkBF,EAAUtJ,OAAOyJ,GAC/BE,GAAc9J,QAAQ2J,KAAoB,IAC5CD,EAAkBC,EAClBA,EAAkB,QAKpBR,OAAQQ,GAAmB,cAC3BzE,KAAMwE,EACNK,OAAQH,GAIZ,QAASI,GAAmBC,GAC1B,MAAOA,GAAad,OAAS,KAAOc,EAAaF,OAAS,IAAM,IAAME,EAAa/E,KAGrF,QAASgF,GAAiBD,EAActC,EAAYwC,GAClD,GAAIjL,GAAOH,IACX,OAAOA,MAAKqL,UAAUH,EAAad,OAAQxB,GAC1C0C,KAAK,SAASC,GACb,MAAOpL,GAAKqL,KAAKD,GAChBD,KAAK,SAASG,GACb,GAAIjN,GAAI2I,EAAqB+D,EAAa/E,KAAMhG,EAAKmC,IAAIiJ,GAEzD,IAAIH,GAAoB,iBAAL5M,GACjB,KAAM,IAAID,WAAU,aAAe0M,EAAmBC,GAAgB,iCAExE,OAAOA,GAAaF,QAAUxM,EAAIA,MAMxC,QAASkN,GAAuB7I,EAAM+F,GAEpC,GAAI+C,GAAmB9I,EAAKlE,MAAMiN,GAElC,KAAKD,EACH,MAAOE,SAAQC,QAAQjJ,EAEzB,IAAIqI,GAAeT,EAAejI,KAAKxC,KAAM2L,EAAiB,GAAGvK,OAAO,EAAGuK,EAAiB,GAAG5K,OAAS,GAGxG,OAAIf,MAAK+I,QACA/I,KAAgB,UAAEkL,EAAad,OAAQxB,GAC7C0C,KAAK,SAASV,GAEb,MADAM,GAAad,OAASQ,EACf/H,EAAKnE,QAAQkN,GAAoB,KAAOX,EAAmBC,GAAgB,OAG/EC,EAAiB3I,KAAKxC,KAAMkL,EAActC,GAAY,GAC5D0C,KAAK,SAASS,GACb,GAA8B,gBAAnBA,GACT,KAAM,IAAIxN,WAAU,2BAA6BsE,EAAO,gCAE1D,IAAIkJ,EAAe9K,QAAQ,OAAQ,EACjC,KAAM,IAAI1C,WAAU,sCAAwCsE,GAAQ+F,EAAa,OAASA,EAAa,IAAM,2BAA6BmD,EAAiB,mCAE7J,OAAOlJ,GAAKnE,QAAQkN,GAAoBG,KAI5C,QAASC,GAAmBnJ,EAAM+F,GAEhC,GAAIqD,GAAepJ,EAAKnD,YAAY,KAEpC,IAAIuM,IAAgB,EAClB,MAAOJ,SAAQC,QAAQjJ,EAEzB,IAAIqI,GAAeT,EAAejI,KAAKxC,KAAM6C,EAAKzB,OAAO6K,EAAe,GAGxE,OAAIjM,MAAK+I,QACA/I,KAAgB,UAAEkL,EAAad,OAAQxB,GAC7C0C,KAAK,SAASV,GAEb,MADAM,GAAad,OAASQ,EACf/H,EAAKzB,OAAO,EAAG6K,GAAgB,KAAOhB,EAAmBC,KAG7DC,EAAiB3I,KAAKxC,KAAMkL,EAActC,GAAY,GAC5D0C,KAAK,SAASS,GACb,MAAOA,GAAiBlJ,EAAKzB,OAAO,EAAG6K,GAAgB,WAhmJ3D,GAAIC,GAA4B,mBAAVC,SAAwC,mBAARhM,OAA+C,mBAAjBiM,eAChF/K,EAA6B,mBAAV8K,SAA4C,mBAAZE,UACnD/K,EAA8B,mBAAXgL,UAAqD,mBAApBA,SAAQC,YAA6BD,QAAQC,SAAS5N,MAAM,OAE/GyB,GAAS8G,UACZ9G,EAAS8G,SAAYsF,OAAQ,cAG/B,IASInK,GATApB,EAAU2E,MAAM9C,UAAU7B,SAAW,SAASwL,GAChD,IAAK,GAAI3L,GAAI,EAAG4L,EAAU1M,KAAKe,OAAQD,EAAI4L,EAAS5L,IAClD,GAAId,KAAKc,KAAO2L,EACd,MAAO3L,EAGX,QAAO,IAIT,WACE,IACQuE,OAAOhD,kBAAmB,UAC9BA,EAAiBgD,OAAOhD,gBAE5B,MAAOsK,GACLtK,EAAiB,SAASuK,EAAKzG,EAAM0G,GACnC,IACED,EAAIzG,GAAQ0G,EAAI7H,OAAS6H,EAAIvK,IAAIE,KAAKoK,GAExC,MAAMD,SAKZ,IAsCIrJ,GAtCA9B,EAAwC,KAA9B,GAAIC,OAAM,EAAG,KAAKC,QAyChC,IAAuB,mBAAZ2K,WAA2BA,SAASS,sBAG7C,GAFAxJ,EAAU+I,SAAS/I,SAEdA,EAAS,CACZ,GAAIyJ,GAAQV,SAASS,qBAAqB,OAC1CxJ,GAAUyJ,EAAM,IAAMA,EAAM,GAAG7M,MAAQiM,OAAOa,SAAS9M,UAG/B,mBAAZ8M,YACd1J,EAAUlD,EAAS4M,SAAS9M,KAI9B,IAAIoD,EACFA,EAAUA,EAAQ1C,MAAM,KAAK,GAAGA,MAAM,KAAK,GAC3C0C,EAAUA,EAAQlC,OAAO,EAAGkC,EAAQ5D,YAAY,KAAO,OAEpD,CAAA,GAAsB,mBAAX4M,WAA0BA,QAAQW,IAMhD,KAAM,IAAI1O,WAAU,yBALpB+E,GAAU,WAAahC,EAAY,IAAM,IAAMgL,QAAQW,MAAQ,IAC3D3L,IACFgC,EAAUA,EAAQ5E,QAAQ,MAAO,MAMrC,IACE,GAAIwO,GAAqD,SAAzC,GAAI9M,GAASmD,IAAI,YAAY1E,SAE/C,MAAM8N,IAEN,GAAIpJ,GAAM2J,EAAY9M,EAASmD,IAAMnD,EAAShC,WAwBhDiE,GAAeT,EAAOkB,UAAW,YAC/BkC,MAAO,WACL,MAAO,YAsBX,WAsGE,QAASmI,GAAWtK,GAClB,OACEuK,OAAQ,UACRvK,KAAMA,GAAQ,gBAAiBwK,EAAU,IACzCC,YACAC,gBACAC,aASJ,QAASC,GAAW/J,EAAQb,EAAMf,GAChC,MAAO,IAAI+J,SAAQ6B,GACjBC,KAAM7L,EAAQ8L,QAAU,QAAU,SAClClK,OAAQA,EACRmK,WAAYhL,EAEZiL,eAAgBhM,GAAWA,EAAQ0L,aACnCO,aAAcjM,EAAQ0H,OACtBwE,cAAelM,EAAQ8L,WAK3B,QAASK,GAAYvK,EAAQwK,EAASC,EAAaC,GAEjD,MAAO,IAAIvC,SAAQ,SAASC,EAASuC,GACnCvC,EAAQpI,EAAO1B,UAAUqJ,UAAU6C,EAASC,EAAaC,MAG1D9C,KAAK,SAASzI,GACb,GAAI2I,EACJ,IAAI9H,EAAOxB,QAAQW,GAKjB,MAJA2I,GAAO2B,EAAWtK,GAClB2I,EAAK4B,OAAS,SAEd5B,EAAKpB,OAAS1G,EAAOxB,QAAQW,GACtB2I,CAGT,KAAK,GAAI1K,GAAI,EAAG0D,EAAId,EAAOzB,MAAMlB,OAAQD,EAAI0D,EAAG1D,IAE9C,GADA0K,EAAO9H,EAAOzB,MAAMnB,GAChB0K,EAAK3I,MAAQA,EAEjB,MAAO2I,EAQT,OALAA,GAAO2B,EAAWtK,GAClBa,EAAOzB,MAAMnC,KAAK0L,GAElB8C,EAAgB5K,EAAQ8H,GAEjBA,IAKX,QAAS8C,GAAgB5K,EAAQ8H,GAC/B+C,EAAe7K,EAAQ8H,EACrBK,QAAQC,UAEPR,KAAK,WACJ,MAAO5H,GAAO1B,UAAUwM,QAAS3L,KAAM2I,EAAK3I,KAAM2K,SAAUhC,EAAKgC,cAMvE,QAASe,GAAe7K,EAAQ8H,EAAM5L,GACpC6O,EAAmB/K,EAAQ8H,EACzB5L,EAEC0L,KAAK,SAASsC,GAEb,GAAmB,WAAfpC,EAAK4B,OAIT,MAFA5B,GAAKoC,QAAUA,EAERlK,EAAO1B,UAAU0M,OAAQ7L,KAAM2I,EAAK3I,KAAM2K,SAAUhC,EAAKgC,SAAUI,QAASA,OAMzF,QAASa,GAAmB/K,EAAQ8H,EAAM5L,GACxCA,EAEC0L,KAAK,SAAS9B,GACb,GAAmB,WAAfgC,EAAK4B,OAKT,MAFA5B,GAAKoC,QAAUpC,EAAKoC,SAAWpC,EAAK3I,KAE7BgJ,QAAQC,QAAQpI,EAAO1B,UAAU2M,WAAY9L,KAAM2I,EAAK3I,KAAM2K,SAAUhC,EAAKgC,SAAUI,QAASpC,EAAKoC,QAASpE,OAAQA,KAG5H8B,KAAK,SAAS9B,GAEb,MADAgC,GAAKhC,OAASA,EACP9F,EAAO1B,UAAU4M,aAAc/L,KAAM2I,EAAK3I,KAAM2K,SAAUhC,EAAKgC,SAAUI,QAASpC,EAAKoC,QAASpE,OAAQA,MAIhH8B,KAAK,SAASuD,GACb,GAA0BvP,SAAtBuP,EACF,KAAM,IAAItQ,WAAU,mDAEtB,IAAgC,gBAArBsQ,GACT,KAAM,IAAItQ,WAAU,mCAEtBiN,GAAKsD,SAAWD,EAAkBxK,SAClCmH,EAAK1B,QAAU+E,EAAkB/E,UAGlCwB,KAAK,WACJE,EAAK+B,eAIL,KAAK,GAHDuB,GAAWtD,EAAKsD,SAEhBC,KACKjO,EAAI,EAAG0D,EAAIsK,EAAS/N,OAAQD,EAAI0D,EAAG1D,KAAK,SAAUoN,EAASzJ,GAClEsK,EAAajP,KACXmO,EAAYvK,EAAQwK,EAAS1C,EAAK3I,KAAM2I,EAAKoC,SAG5CtC,KAAK,SAAS0D,GASb,GALAxD,EAAK+B,aAAa9I,IAChBwK,IAAKf,EACLlJ,MAAOgK,EAAQnM,MAGK,UAAlBmM,EAAQ5B,OAEV,IAAK,GADDE,GAAW9B,EAAK8B,SAASzH,WACpB/E,EAAI,EAAG0D,EAAI8I,EAASvM,OAAQD,EAAI0D,EAAG1D,IAC1CoO,EAAiB5B,EAASxM,GAAIkO,QAOrCF,EAAShO,GAAIA,EAEhB,OAAO+K,SAAQsD,IAAIJ,KAIpBzD,KAAK,WAIJE,EAAK4B,OAAS,QAGd,KAAK,GADDE,GAAW9B,EAAK8B,SAASzH,WACpB/E,EAAI,EAAG0D,EAAI8I,EAASvM,OAAQD,EAAI0D,EAAG1D,IAC1CsO,EAAoB9B,EAASxM,GAAI0K,OAI/B,MAAE,SAAS6D,GACjB7D,EAAK4B,OAAS,SACd5B,EAAK8D,UAAYD,CAGjB,KAAK,GADD/B,GAAW9B,EAAK8B,SAASzH,WACpB/E,EAAI,EAAG0D,EAAI8I,EAASvM,OAAQD,EAAI0D,EAAG1D,IAC1CyO,EAAcjC,EAASxM,GAAI0K,EAAM6D,KAUvC,QAAS3B,GAA6B8B,GACpC,MAAO,UAAS1D,EAASuC,GACvB,GAAI3K,GAAS8L,EAAU9L,OACnBb,EAAO2M,EAAU3B,WACjBF,EAAO6B,EAAU7B,IAErB,IAAIjK,EAAOxB,QAAQW,GACjB,KAAM,IAAItE,WAAU,IAAMsE,EAAO,uCAInC,KAAK,GADD4M,GACK3O,EAAI,EAAG0D,EAAId,EAAOzB,MAAMlB,OAAQD,EAAI0D,EAAG1D,IAC9C,GAAI4C,EAAOzB,MAAMnB,GAAG+B,MAAQA,IAC1B4M,EAAe/L,EAAOzB,MAAMnB,GAEhB,aAAR6M,GAAwB8B,EAAajG,SACvCiG,EAAa7B,QAAU4B,EAAUxB,cACjCS,EAAmB/K,EAAQ+L,EAAc5D,QAAQC,QAAQ0D,EAAUzB,gBAKjE0B,EAAanC,SAASvM,QAAU0O,EAAanC,SAAS,GAAGrL,MAAM,GAAGY,MAAQ4M,EAAa5M,MACzF,MAAO4M,GAAanC,SAAS,GAAGoC,KAAKpE,KAAK,WACxCQ,EAAQ2D,IAKhB,IAAIjE,GAAOiE,GAAgBtC,EAAWtK,EAEtC2I,GAAKgC,SAAWgC,EAAU1B,cAE1B,IAAI6B,GAAUC,EAAclM,EAAQ8H,EAEpC9H,GAAOzB,MAAMnC,KAAK0L,GAElBM,EAAQ6D,EAAQD,MAEJ,UAAR/B,EACFW,EAAgB5K,EAAQ8H,GAET,SAARmC,EACPY,EAAe7K,EAAQ8H,EAAMK,QAAQC,QAAQ0D,EAAUxB,iBAIvDxC,EAAKoC,QAAU4B,EAAUxB,cACzBS,EAAmB/K,EAAQ8H,EAAMK,QAAQC,QAAQ0D,EAAUzB,iBAWjE,QAAS6B,GAAclM,EAAQmM,GAC7B,GAAIF,IACFjM,OAAQA,EACRzB,SACA4N,aAAcA,EACdC,aAAc,EAOhB,OALAH,GAAQD,KAAO,GAAI7D,SAAQ,SAASC,EAASuC,GAC3CsB,EAAQ7D,QAAUA,EAClB6D,EAAQtB,OAASA,IAEnBa,EAAiBS,EAASE,GACnBF,EAGT,QAAST,GAAiBS,EAASnE,GACjC,GAAmB,UAAfA,EAAK4B,OAAT,CAGA,IAAK,GAAItM,GAAI,EAAG0D,EAAImL,EAAQ1N,MAAMlB,OAAQD,EAAI0D,EAAG1D,IAC/C,GAAI6O,EAAQ1N,MAAMnB,IAAM0K,EACtB,MAEJmE,GAAQ1N,MAAMnC,KAAK0L,GACnBA,EAAK8B,SAASxN,KAAK6P,GAGA,UAAfnE,EAAK4B,QACPuC,EAAQG,cAKV,KAAK,GAFDpM,GAASiM,EAAQjM,OAEZ5C,EAAI,EAAG0D,EAAIgH,EAAK+B,aAAaxM,OAAQD,EAAI0D,EAAG1D,IACnD,GAAK0K,EAAK+B,aAAazM,GAAvB,CAGA,GAAI+B,GAAO2I,EAAK+B,aAAazM,GAAGkE,KAEhC,KAAItB,EAAOxB,QAAQW,GAGnB,IAAK,GAAIkN,GAAI,EAAG3K,EAAI1B,EAAOzB,MAAMlB,OAAQgP,EAAI3K,EAAG2K,IAC9C,GAAIrM,EAAOzB,MAAM8N,GAAGlN,MAAQA,EAA5B,CAGAqM,EAAiBS,EAASjM,EAAOzB,MAAM8N,GACvC,UASN,QAASC,GAAOL,GACd,GAAIM,IAAQ,CACZ,KACEC,EAAKP,EAAS,SAASnE,EAAM6D,GAC3BE,EAAcI,EAASnE,EAAM6D,GAC7BY,GAAQ,IAGZ,MAAMtD,GACJ4C,EAAcI,EAAS,KAAMhD,GAC7BsD,GAAQ,EAEV,MAAOA,GAIT,QAASb,GAAoBO,EAASnE,GAQpC,GAFAmE,EAAQG,iBAEJH,EAAQG,aAAe,GAA3B,CAIA,GAAID,GAAeF,EAAQE,YAK3B,IAAIF,EAAQjM,OAAO1B,UAAU8H,WAAY,EAAO,CAE9C,IAAK,GADD7H,MAAW4D,OAAO8J,EAAQ1N,OACrBnB,EAAI,EAAG0D,EAAIvC,EAAMlB,OAAQD,EAAI0D,EAAG1D,IAAK,CAC5C,GAAI0K,GAAOvJ,EAAMnB,EACjB0K,GAAKpB,QACHvH,KAAM2I,EAAK3I,KACXuH,OAAQ+F,MACRhG,WAAW,GAEbqB,EAAK4B,OAAS,SACdgD,EAAWT,EAAQjM,OAAQ8H,GAE7B,MAAOmE,GAAQ7D,QAAQ+D,GAIzB,GAAIQ,GAASL,EAAOL,EAEhBU,IAKJV,EAAQ7D,QAAQ+D,IAIlB,QAASN,GAAcI,EAASnE,EAAM6D,GACpC,GAAI3L,GAASiM,EAAQjM,MAGrB4M,GACA,GAAI9E,EACF,GAAImE,EAAQ1N,MAAM,GAAGY,MAAQ2I,EAAK3I,KAChCwM,EAAMhP,EAAWgP,EAAK,iBAAmB7D,EAAK3I,UAE3C,CACH,IAAK,GAAI/B,GAAI,EAAGA,EAAI6O,EAAQ1N,MAAMlB,OAAQD,IAExC,IAAK,GADDyP,GAAQZ,EAAQ1N,MAAMnB,GACjBiP,EAAI,EAAGA,EAAIQ,EAAMhD,aAAaxM,OAAQgP,IAAK,CAClD,GAAIS,GAAMD,EAAMhD,aAAawC,EAC7B,IAAIS,EAAIxL,OAASwG,EAAK3I,KAAM,CAC1BwM,EAAMhP,EAAWgP,EAAK,iBAAmB7D,EAAK3I,KAAO,QAAU2N,EAAIvB,IAAM,UAAYsB,EAAM1N,KAC3F,MAAMyN,IAIZjB,EAAMhP,EAAWgP,EAAK,iBAAmB7D,EAAK3I,KAAO,SAAW8M,EAAQ1N,MAAM,GAAGY,UAInFwM,GAAMhP,EAAWgP,EAAK,iBAAmBM,EAAQ1N,MAAM,GAAGY,KAK5D,KAAK,GADDZ,GAAQ0N,EAAQ1N,MAAM4D,WACjB/E,EAAI,EAAG0D,EAAIvC,EAAMlB,OAAQD,EAAI0D,EAAG1D,IAAK,CAC5C,GAAI0K,GAAOvJ,EAAMnB,EAGjB4C,GAAO1B,UAAUyO,OAAS/M,EAAO1B,UAAUyO,WACvCxP,EAAQuB,KAAKkB,EAAO1B,UAAUyO,OAAQjF,KAAS,GACjD9H,EAAO1B,UAAUyO,OAAO3Q,KAAK0L,EAE/B,IAAIkF,GAAYzP,EAAQuB,KAAKgJ,EAAK8B,SAAUqC,EAG5C,IADAnE,EAAK8B,SAASqD,OAAOD,EAAW,GACJ,GAAxBlF,EAAK8B,SAASvM,OAAa,CAC7B,GAAI6P,GAAmB3P,EAAQuB,KAAKmN,EAAQjM,OAAOzB,MAAOuJ,EACtDoF,KAAoB,GACtBjB,EAAQjM,OAAOzB,MAAM0O,OAAOC,EAAkB,IAGpDjB,EAAQtB,OAAOgB,GAIjB,QAASe,GAAW1M,EAAQ8H,GAE1B,GAAI9H,EAAO1B,UAAU6O,MAAO,CACrBnN,EAAO1B,UAAUC,QACpByB,EAAO1B,UAAUC,SACnB,IAAI6O,KACJtF,GAAK+B,aAAawD,QAAQ,SAASP,GACjCM,EAAON,EAAIvB,KAAOuB,EAAIxL,QAExBtB,EAAO1B,UAAUC,MAAMuJ,EAAK3I,OAC1BA,KAAM2I,EAAK3I,KACXwB,KAAMmH,EAAK+B,aAAanH,IAAI,SAASoK,GAAM,MAAOA,GAAIvB,MACtD6B,OAAQA,EACRlD,QAASpC,EAAKoC,QACdJ,SAAUhC,EAAKgC,SACfhE,OAAQgC,EAAKhC,QAIbgC,EAAK3I,OAEPa,EAAOxB,QAAQsJ,EAAK3I,MAAQ2I,EAAKpB,OAEnC,IAAI4G,GAAY/P,EAAQuB,KAAKkB,EAAOzB,MAAOuJ,EACvCwF,KAAa,GACftN,EAAOzB,MAAM0O,OAAOK,EAAW,EACjC,KAAK,GAAIlQ,GAAI,EAAG0D,EAAIgH,EAAK8B,SAASvM,OAAQD,EAAI0D,EAAG1D,IAC/CkQ,EAAY/P,EAAQuB,KAAKgJ,EAAK8B,SAASxM,GAAGmB,MAAOuJ,GAC7CwF,IAAa,GACfxF,EAAK8B,SAASxM,GAAGmB,MAAM0O,OAAOK,EAAW,EAE7CxF,GAAK8B,SAASqD,OAAO,EAAGnF,EAAK8B,SAASvM,QAGxC,QAASkQ,GAAiBtB,EAASnE,EAAM0F,GACvC,IACE,GAAI9G,GAASoB,EAAK1B,UAEpB,MAAM6C,GAEJ,WADAuE,GAAU1F,EAAMmB,GAGlB,MAAKvC,IAAYA,YAAkBxI,GAG1BwI,MAFP8G,GAAU1F,EAAM,GAAIjN,WAAU,4CAWlC,QAAS4S,GAAoBzN,EAAQb,EAAMuO,GACzC,GAAIjP,GAAiBuB,EAAO3B,QAAQI,cACpC,OAAOA,GAAeU,GAAQuO,EAAQ9F,KAAK,SAAS9M,GAElD,MADA2D,GAAeU,GAAQvD,OAChBd,GACN,SAASmO,GAEV,KADAxK,GAAeU,GAAQvD,OACjBqN,IAiKV,QAASuD,GAAKP,EAASuB,GAErB,GAAIxN,GAASiM,EAAQjM,MAErB,IAAKiM,EAAQ1N,MAAMlB,OAKnB,IAAK,GAFDkB,GAAQ0N,EAAQ1N,MAAM4D,WAEjB/E,EAAI,EAAGA,EAAImB,EAAMlB,OAAQD,IAAK,CACrC,GAAI0K,GAAOvJ,EAAMnB,GAEbsJ,EAAS6G,EAAiBtB,EAASnE,EAAM0F,EAC7C,KAAK9G,EACH,MACFoB,GAAKpB,QACHvH,KAAM2I,EAAK3I,KACXuH,OAAQA,GAEVoB,EAAK4B,OAAS,SAEdgD,EAAW1M,EAAQ8H,IA3oBvB,GAAI6B,GAAU,CAyddxL,GAAOiB,WAELuO,YAAaxP,EAEbyP,OAAQ,SAASzO,EAAM2G,EAAQ1H,GAE7B,GAAI9B,KAAK+B,QAAQI,eAAeU,GAC9B,KAAM,IAAItE,WAAU,6BACtB,OAAO4S,GAAoBnR,KAAM6C,EAAM,GAAIgJ,SAAQ6B,GACjDC,KAAM,YACNjK,OAAQ1D,KAAK+B,QACb8L,WAAYhL,EACZiL,eAAgBhM,GAAWA,EAAQ0L,aACnCO,aAAcvE,EACdwE,cAAelM,GAAWA,EAAQ8L,aAItC2D,OAAU,SAAS1O,GACjB,GAAIa,GAAS1D,KAAK+B,OAGlB,cAFO2B,GAAOvB,eAAeU,SACtBa,GAAOtB,cAAcS,KACrBa,EAAOxB,QAAQW,UAAea,GAAOxB,QAAQW,IAItDP,IAAK,SAAS2M,GACZ,GAAKjP,KAAK+B,QAAQG,QAAQ+M,GAE1B,MAAOjP,MAAK+B,QAAQG,QAAQ+M,GAAK7E,QAGnCtB,IAAK,SAASjG,GACZ,QAAS7C,KAAK+B,QAAQG,QAAQW,IAGhC2O,OAAU,SAAS3O,EAAM+F,EAAY6I,GACV,gBAAd7I,KACTA,EAAaA,EAAW/F,KAG1B,IAAIb,GAAYhC,IAGhB,OAAO6L,SAAQC,QAAQ9J,EAAUqJ,UAAUxI,EAAM+F,IAChD0C,KAAK,SAASzI,GACb,GAAIa,GAAS1B,EAAUD,OAEvB,OAAI2B,GAAOxB,QAAQW,GACVa,EAAOxB,QAAQW,GAAMuH,OAEvB1G,EAAOvB,eAAeU,IAASsO,EAAoBnP,EAAWa,EACnE4K,EAAW/J,EAAQb,MAClByI,KAAK,SAASE,GAEb,aADO9H,GAAOvB,eAAeU,GACtB2I,EAAKpB,OAAOA,aAM3BoB,KAAM,SAAS3I,GACb,GAAIa,GAAS1D,KAAK+B,OAClB,OAAI2B,GAAOxB,QAAQW,GACVgJ,QAAQC,UACVpI,EAAOvB,eAAeU,IAASsO,EAAoBnR,KAAM6C,EAAM,GAAIgJ,SAAQ6B,GAChFC,KAAM,SACNjK,OAAQA,EACRmK,WAAYhL,EACZiL,kBACAC,aAAczO,OACd0O,cAAe1O,UAEhBgM,KAAK,iBACG5H,GAAOvB,eAAeU,OAIjCuH,OAAQ,SAASZ,EAAQ1H,GACvB,GAAI0J,GAAO2B,GACX3B,GAAKoC,QAAU9L,GAAWA,EAAQ8L,OAClC,IAAI+B,GAAUC,EAAc5P,KAAK+B,QAASyJ,GACtCkG,EAAgB7F,QAAQC,QAAQtC,GAChC9F,EAAS1D,KAAK+B,QACdnC,EAAI+P,EAAQD,KAAKpE,KAAK,WACxB,MAAOE,GAAKpB,OAAOA,QAGrB,OADAqE,GAAmB/K,EAAQ8H,EAAMkG,GAC1B9R,GAGToI,UAAW,SAAU4E,GACnB,GAAkB,gBAAPA,GACT,KAAM,IAAIrO,WAAU,kBAEtB,IAAIC,GAAI,GAAIoD,GAER+P,IACJ,IAAItM,OAAOuM,qBAA8B,MAAPhF,EAChC+E,EAAStM,OAAOuM,oBAAoBhF,OAEpC,KAAK,GAAIqC,KAAOrC,GACd+E,EAAO7R,KAAKmP,EAEhB,KAAK,GAAInO,GAAI,EAAGA,EAAI6Q,EAAO5Q,OAAQD,KAAK,SAAUmO,GAChD5M,EAAe7D,EAAGyQ,GAChB4C,cAAc,EACdC,YAAY,EACZxP,IAAK,WACH,MAAOsK,GAAIqC,IAEbnH,IAAK,WACH,KAAM,IAAIrG,OAAM,qDAGnBkQ,EAAO7Q,GAKV,OAHIuE,QAAO0M,QACT1M,OAAO0M,OAAOvT,GAETA,GAGTsJ,IAAK,SAASjF,EAAMuH,GAClB,KAAMA,YAAkBxI,IACtB,KAAM,IAAIrD,WAAU,cAAgBsE,EAAO,6BAC7C7C,MAAK+B,QAAQG,QAAQW,IACnBuH,OAAQA,IAQZiB,UAAW,SAASxI,EAAMmP,EAAcC,KAExCzD,OAAQ,SAAShD,GACf,MAAOA,GAAK3I,MAGd6L,MAAO,SAASlD,KAGhBmD,UAAW,SAASnD,GAClB,MAAOA,GAAKhC,QAGdoF,YAAa,SAASpD,KAIxB,IAAI2E,GAAatO,EAAOiB,UAAUkF,YAgCpC,IAAIkK,GAEEC,CACJ,IAA6B,mBAAlBC,gBACTD,EAAmB,SAAS9T,EAAKgU,EAAeC,EAASjE,GAsBvD,QAAS7C,KACP8G,EAAQC,EAAIC,cAEd,QAASvC,KACP5B,EAAO,GAAI5M,OAAM,aAAe8Q,EAAInF,OAAS,KAAOmF,EAAInF,QAAUmF,EAAIE,WAAa,IAAMF,EAAIE,WAAc,IAAM,IAAM,IAAM,YAAcpU,IAzB7I,GAAIkU,GAAM,GAAIH,gBACVM,GAAa,EACbC,GAAY,CAChB,MAAM,mBAAqBJ,IAAM,CAE/B,GAAIK,GAAc,uBAAuBC,KAAKxU,EAC1CuU,KACFF,EAAaE,EAAY,KAAOzG,OAAOa,SAAShO,KAC5C4T,EAAY,KACdF,GAAcE,EAAY,KAAOzG,OAAOa,SAASnO,WAGlD6T,GAAuC,mBAAlBI,kBACxBP,EAAM,GAAIO,gBACVP,EAAIQ,OAASvH,EACb+G,EAAIS,QAAU/C,EACdsC,EAAIU,UAAYhD,EAChBsC,EAAIW,WAAa,aACjBX,EAAIY,QAAU,EACdR,GAAY,GASdJ,EAAIa,mBAAqB,WACA,IAAnBb,EAAIc,aAEY,GAAdd,EAAInF,OACFmF,EAAIC,aACNhH,KAKA+G,EAAIe,iBAAiB,QAASrD,GAC9BsC,EAAIe,iBAAiB,OAAQ9H,IAGT,MAAf+G,EAAInF,OACX5B,IAGAyE,MAINsC,EAAIgB,KAAK,MAAOlV,GAAK,GAEjBkU,EAAIiB,mBACNjB,EAAIiB,iBAAiB,SAAU,gCAE3BnB,IAC0B,gBAAjBA,IACTE,EAAIiB,iBAAiB,gBAAiBnB,GACxCE,EAAIkB,iBAAkB,IAItBd,EACFe,WAAW,WACTnB,EAAIoB,QACH,GAEHpB,EAAIoB,KAAK,WAIV,IAAsB,mBAAXhL,UAA4C,mBAAX2D,SAAwB,CACvE,GAAIsH,EACJzB,GAAmB,SAAS9T,EAAKgU,EAAeC,EAASjE,GACvD,GAAwB,YAApBhQ,EAAI+C,OAAO,EAAG,GAChB,KAAM,IAAIK,OAAM,oBAAsBpD,EAAM,kEAM9C,OALAuV,GAAKA,GAAMjL,QAAQ,MAEjBtK,EADEiD,EACIjD,EAAIK,QAAQ,MAAO,MAAM0C,OAAO,GAEhC/C,EAAI+C,OAAO,GACZwS,EAAGC,SAASxV,EAAK,SAASiC,EAAKwT,GACpC,GAAIxT,EACF,MAAO+N,GAAO/N,EAId,IAAIyT,GAAaD,EAAO,EACF,YAAlBC,EAAW,KACbA,EAAaA,EAAW3S,OAAO,IAEjCkR,EAAQyB,UAKX,CAAA,GAAmB,mBAAR5T,OAA4C,mBAAdA,MAAKuO,MAwBjD,KAAM,IAAInQ,WAAU,sCAvBpB4T,GAAmB,SAAS9T,EAAKgU,EAAeC,EAASjE,GACvD,GAAI2F,IACFC,SAAUC,OAAU,gCAGlB7B,KAC0B,gBAAjBA,KACT2B,EAAKC,QAAuB,cAAI5B,GAClC2B,EAAKG,YAAc,WAGrBzF,MAAMrQ,EAAK2V,GACR1I,KAAK,SAAU8I,GACd,GAAIA,EAAEC,GACJ,MAAOD,GAAEE,MAET,MAAM,IAAI7S,OAAM,gBAAkB2S,EAAEhH,OAAS,IAAMgH,EAAE3B,cAGxDnH,KAAKgH,EAASjE,IASvB,GAAIkG,GAAY,WAKd,QAASA,GAAU/I,GACjB,GAAIrL,GAAOH,IAEX,OAAO6L,SAAQC,QAAQ1L,EAA4B,cAAnBD,EAAKqU,WAA6B,KAAOrU,EAAKqU,cACtErU,EAAKsU,cAAgBtU,GAAc,OAAEA,EAAKqU,aACjDlJ,KAAK,SAASkJ,GACTA,EAAWE,eACbF,EAAaA,EAAoB,QAEnC,IAAIG,EASJ,OAPEA,GADEH,EAAWI,SACOC,EACbL,EAAWM,sBACEC,EAEAC,EAGf,2BAA6BL,EAAkBnS,KAAKrC,EAAMqL,EAAMgJ,GAAc,SAAWhJ,EAAK3I,KAAO,sBAAwB2I,EAAKoC,QAAU,gBAIvJ,QAASiH,GAAiBrJ,EAAMyJ,GAC9B,GAAInT,GAAU9B,KAAKkV,kBACnBpT,GAAQI,QAAU,cAClBJ,EAAQqT,QAAS,EACU7V,SAAvBwC,EAAQsT,aACVtT,EAAQsT,WAAa,UACvBtT,EAAQuT,SAAW7J,EAAKoC,QACxB9L,EAAQwT,eAAiB9J,EAAKgC,SAAS+H,UACvCzT,EAAQ+L,YAAa,CAErB,IAAI2H,GAAW,GAAIP,GAAQL,SAAS9S,EAEpC,OAAO2T,GAAiBjK,EAAKhC,OAAQgM,EAAU1T,EAAQuT,UAEzD,QAASI,GAAiBjM,EAAQgM,EAAUH,GAC1C,IACE,MAAOG,GAASE,QAAQlM,EAAQ6L,GAElC,MAAM1I,GAGJ,GAAIA,EAAE5L,OACJ,KAAM4L,GAAE,EAEV,MAAMA,IAIV,QAASqI,GAAexJ,EAAMmK,GAC5B,GAAI7T,GAAU9B,KAAK4V,gBASnB,OARA9T,GAAQI,QAAU,SACQ5C,SAAtBwC,EAAQyT,YACVzT,EAAQyT,UAAY,UACtBzT,EAAQwT,eAAiB9J,EAAKgC,SAAS+H,UACvCzT,EAAQuT,SAAW7J,EAAKoC,QACxB9L,EAAQ+T,MAAO,EACf/T,EAAQgU,KAAM,EAEPH,EAAMI,UAAUvK,EAAKhC,OAAQ1H,GAAS+T,KAG/C,QAASd,GAAoBvJ,EAAMwK,GACjC,GAAIlU,GAAU9B,KAAKiW,qBASnB,OARAnU,GAAQoU,OAASpU,EAAQoU,QAAUF,EAAGG,aAAaC,IACzB9W,SAAtBwC,EAAQyT,YACVzT,EAAQyT,WAAY,GAClBzT,EAAQyT,WAAazT,EAAQuU,mBAAoB,IACnDvU,EAAQuU,iBAAkB,GAE5BvU,EAAQsI,OAAS4L,EAAGM,WAAWpE,OAExB8D,EAAGzB,UAAU/I,EAAKhC,OAAQ1H,EAAS0J,EAAKoC,SAGjD,MA9EA/L,GAAOiB,UAAU0R,WAAa,UA8EvBD,IAcT5R,GAAYG,UAAYjB,EAAOiB,UAC/BP,EAAeO,UAAY,GAAIH,GAC/BJ,EAAeO,UAAUuO,YAAc9O,CAEvC,IAAIG,GAUAO,EAAc,eAWdO,EAAa,GAAID,GAAID,GA6FrBuB,GAA2B,CAC/B,KACEQ,OAAOR,0BAA2BU,EAAG,GAAK,KAE5C,MAAMoH,GACJ9H,GAA2B,EAuI7B,GAAI0R,KAEJ,WAYE,QAASF,GAAgBG,GACvB,MAAIC,GACKC,EAAkB,GAAIC,QAAOH,GAAiB7V,SAAS,UACxC,mBAARiW,MACPF,EAAkBE,KAAKC,SAASC,mBAAmBN,KAEnD,GAGX,QAASO,GAAUvL,EAAMwL,GACvB,GAAIC,GAAgBzL,EAAKhC,OAAO9J,YAAY,KAGhB,WAAxB8L,EAAKgC,SAAS0J,SAChBF,GAAO,EAET,IAAIzB,GAAY/J,EAAKgC,SAAS+H,SAC9B,IAAIA,EAAW,CACb,GAAwB,gBAAbA,GACT,KAAM,IAAIhX,WAAU,oDAEtBgX,GAAY4B,KAAKC,UAAU7B,GAG7B,OAAQyB,EAAO,gCAAkC,IAAMxL,EAAKhC,QAAUwN,EAAO,wBAA0B,KAEvD,oBAAzCxL,EAAKhC,OAAOpI,OAAO6V,EAAe,IACjC,mBAAqBzL,EAAKoC,SAAW2H,EAAY,cAAgB,IAAM,KAExEA,GAAac,EAAgBd,IAAc,IAoBpD,QAAS8B,GAAQ3T,EAAQ8H,GACvB8L,EAAU9L,EACW,GAAjB+L,MACFC,EAAYpX,EAAS8R,QACvB9R,EAAS8R,OAAS9R,EAASqX,SAAW/T,EAExC,QAASgU,KACc,KAAfH,IACJnX,EAAS8R,OAAS9R,EAASqX,SAAWD,GACxCF,EAAUhY,OA0CZ,QAASqY,GAAWnM,GACboM,IACHA,EAAOvL,SAASuL,MAAQvL,SAASwL,MAAQxL,SAASyL,gBAEpD,IAAI3C,GAAS9I,SAAS0L,cAAc,SACpC5C,GAAOb,KAAOyC,EAAUvL,GAAM,EAC9B,IACImB,GADAqG,EAAU7G,OAAO6G,OAkBrB,IAhBA7G,OAAO6G,QAAU,SAASgF,GACxBrL,EAAItM,EAAW2X,EAAI,cAAgBxM,EAAKoC,SACpCoF,GACFA,EAAQiF,MAAMjY,KAAMkY,YAExBb,EAAQrX,KAAMwL,GAEVA,EAAKgC,SAAS2K,WAChBhD,EAAOiD,aAAa,YAAa5M,EAAKgC,SAAS2K,WAC7C3M,EAAKgC,SAAS6K,OAChBlD,EAAOiD,aAAa,QAAS5M,EAAKgC,SAAS6K,OAE7CT,EAAKU,YAAYnD,GACjByC,EAAKW,YAAYpD,GACjBuC,IACAvL,OAAO6G,QAAUA,EACbrG,EACF,KAAMA,GAvIV,GAAI8J,GAA6B,mBAAVE,OACvB,KACMF,GAAmD,QAAtC,GAAIE,QAAO,KAAKhW,SAAS,YACxC8V,GAAY,GAEhB,MAAM9J,GACJ8J,GAAY,EAGd,GAiCIa,GAjCAZ,EAAkB,sDAqCtB9T,GAAK,gBAAiB,WACpB,MAAO,UAAS4V,GACd,QAAKlB,IAGLtX,KAAKyY,gBAAgBnB,EAASkB,IACvB,KAKX,IAAIhB,GAcAkB,EACAC,EAdApB,EAAc,CAelBhB,IAAS,SAAS/K,GAChB,GAAKA,EAAKhC,OAAV,CAEA,IAAKgC,EAAKgC,SAAS2K,WAAa3M,EAAKgC,SAAS6K,QAAUO,EACtD,MAAOjB,GAAWnV,KAAKxC,KAAMwL,EAC/B,KACE6L,EAAQrX,KAAMwL,GACd8L,EAAU9L,GAELmN,GAAM3Y,KAAKmI,eACdwQ,EAAK3Y,KAAKmI,aAAa,MACvBuQ,EAAQC,EAAGE,iBAAiB,6CAA+C7Y,MAEzE0Y,EACFC,EAAGE,iBAAiB9B,EAAUvL,GAAM,IAAS6J,SAAU7J,EAAKoC,SAAWpC,EAAKgC,SAAS+H,UAAY,cAAgB,OAEjH,EAAIuD,MAAM/B,EAAUvL,GAAM,IAC5BkM,IAEF,MAAM/K,GAEJ,KADA+K,KACMrX,EAAWsM,EAAG,cAAgBnB,EAAKoC,WAI7C,IAAIgL,IAAqB,CACzB,IAAIvX,GAAgC,mBAAZgL,WAA2BA,SAASS,qBAAsB,CAChF,GAAIiM,GAAU1M,SAASS,qBAAqB,SAC5C9L,cAAe+X,EAAQA,EAAQhY,OAAS,GAElCoL,OAAO6M,QAAU7M,OAAO6M,OAAOC,WAAaC,UAAUC,UAAUxa,MAAM,eAC1Eia,GAAqB,GAKzB,GAAIhB,KA+DN,IAAI7P,GAYJhF,GAAgB,SAASsO,GACvB,MAAO,YACLA,EAAY7O,KAAKxC,MAGjBA,KAAK1B,QAAUgF,EAGftD,KAAKoG,OAGsB,mBAAhBpF,gBACThB,KAAKoZ,UAAYpY,aAAaE,KAGhClB,KAAKiH,UAAW,EAChBjH,KAAKqZ,qBAAsB,EAC3BrZ,KAAKsZ,aAAc,EACnBtZ,KAAKuZ,kBAAmB,EAQxBvZ,KAAK8H,IAAI,SAAU9H,KAAKgI,eAExBL,EAAcnF,KAAKxC,MAAM,GAAO,MAKd,mBAAX2I,UAA4C,mBAAX2D,UAA2BA,QAAQrE,UAC7E1F,EAAeO,UAAUqF,aAAeQ,QAgB1C,IAAIF,GAqDJ7F,GAAK,YAAa,SAASyI,GACzB,MAAO,UAASxI,EAAM+F,EAAY4Q,GAChC,GAAIC,GAAWjT,EAAYhE,KAAKxC,KAAM6C,EAAM+F,EAG5C,QAFI5I,KAAKqZ,qBAAwBG,GAAsD,OAA3CC,EAASrY,OAAOqY,EAAS1Y,OAAS,EAAG,IAAgBoC,EAAQsW,KACvGA,GAAY,OACPA,IAKX,IAAIC,IAAuC,mBAAlBtH,eACzBxP,GAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,MAAOK,SAAQC,QAAQ0C,EAAOhM,KAAKxC,KAAMwL,IACxCF,KAAK,SAASsC,GACb,MAAI8L,IACK9L,EAAQlP,QAAQ,KAAM,OACxBkP,OAQbhL,EAAK,QAAS,WACZ,MAAO,UAAS4I,GACd,MAAO,IAAIK,SAAQ,SAASC,EAASuC,GACnC8D,EAAiB3G,EAAKoC,QAASpC,EAAKgC,SAAS6E,cAAevG,EAASuC,QAmB3EzL,EAAK,SAAU,SAAS+W,GACtB,MAAO,UAAS9W,EAAM+F,EAAY6I,GAGhC,MAFI7I,IAAcA,EAAW/F,MAC3B4D,EAAKjE,KAAKxC,KAAM,oHAAsH6C,EAAO,SAAW+F,EAAW/F,MAC9J8W,EAAanX,KAAKxC,KAAM6C,EAAM+F,EAAY6I,GAAenG,KAAK,SAASlB,GAC5E,MAAOA,GAAOsK,aAAetK,EAAgB,QAAIA,OAQvDxH,EAAK,YAAa,SAASgX,GACzB,MAAO,UAASpO,GAGd,MAF4B,UAAxBA,EAAKgC,SAAS0J,SAChB1L,EAAKgC,SAAS0J,OAAS5X,QAClBsa,EAAgB3B,MAAMjY,KAAMkY,cA0BvCtV,EAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACd,GAA4B,QAAxBA,EAAKgC,SAAS0J,SAAqBlX,KAAK+I,QAAS,CACnD,GAAI8Q,GAAQrO,EAAKgC,SAASqM,MAAQlQ,GAClCkQ,GAAMxV,QACNwV,EAAM/P,QAAU,WACd,IACE,MAAOqN,MAAK2C,MAAMtO,EAAKhC,QAEzB,MAAMmD,GACJ,KAAM,IAAIlL,OAAM,qBAAuB+J,EAAK3I,YAsDtDN,EAAeO,UAAUiX,UAAY,SAASlX,GAC5C,GAAI8D,MACAjD,EAAS1D,IACb,KAAK,GAAIJ,KAAK8D,GACRA,EAAOK,iBAAmBL,EAAOK,eAAenE,IAAMA,IAAK2C,GAAeO,WAAkB,cAALlD,GAEvFqB,EAAQuB,MAAM,UAAW,YAAa,aAAc,UAAW,SAAU,UAAW,SAAU5C,KAAM,IACtG+G,EAAI/G,GAAK8D,EAAO9D,GAGpB,OADA+G,GAAIyB,WAAaL,GAAUK,WACpBzB,EAGT,IAAIqT,GACJzX,GAAeO,UAAUmX,OAAS,SAAStT,EAAKuT,GAiC1C,QAASC,GAAevN,GACtB,IAAK,GAAIhN,KAAKgN,GACZ,GAAIA,EAAI7I,eAAenE,GACrB,OAAO,EAnCjB,GAAI8D,GAAS1D,IAoBb,IAlBI,oBAAsB2G,KACxBqT,GAAehZ,aACX2F,EAAI4S,iBACNvY,aAAe1B,OAEf0B,aAAegZ,IAGf,YAAcrT,KAChBjD,EAAOuD,SAAWN,EAAIM,UAGpBN,EAAIyT,qBAAsB,IAC5B1W,EAAO3B,QAAQsY,yBAA0B,IAEvC,cAAgB1T,IAAO,SAAWA,KACpCgB,EAAcnF,KAAKkB,IAAUiD,EAAIyB,cAAezB,EAAI2B,OAASP,IAAaA,GAAUO,SAEjF4R,EAAa,CAGhB,GAAI5b,EAOJ,IANA0K,EAAOtF,EAAQiD,EAAK,SAASA,GAC3BrI,EAAUA,GAAWqI,EAAIrI,UAE3BA,EAAUA,GAAWqI,EAAIrI,QAGZ,CAOX,GAAI6b,EAAezW,EAAOoD,WAAaqT,EAAezW,EAAO2C,OAAS8T,EAAezW,EAAO4C,WAAa6T,EAAezW,EAAO4W,UAAYH,EAAezW,EAAO6W,oBAC/J,KAAM,IAAIhc,WAAU,qGAEtByB,MAAK1B,QAAUA,EACfoJ,EAAelF,KAAKxC,MAYtB,GATI2G,EAAIlE,OACNsC,EAAOrB,EAAOjB,MAAOkE,EAAIlE,OAE3BuG,EAAOtF,EAAQiD,EAAK,SAASA,GACvBA,EAAIlE,OACNsC,EAAOrB,EAAOjB,MAAOkE,EAAIlE,SAIzBzC,KAAKiH,SACP,IAAK,GAAIrH,KAAK8D,GAAOjB,MACf7C,EAAEqB,QAAQ,OAAQ,GACpBwF,EAAKjE,KAAKkB,EAAQ,wBAA0B9D,EAAI,SAAW8D,EAAOjB,MAAM7C,GAAK,sFAYrF,GARI+G,EAAI0S,sBACN3V,EAAO2V,oBAAsB1S,EAAI0S,oBACjC5S,EAAKjE,KAAKkB,EAAQ,oGAGhBiD,EAAI2S,cACN5V,EAAO4V,YAAc3S,EAAI2S,aAEvB3S,EAAIP,IAAK,CACX,GAAIoU,GAAU,EACd,KAAK,GAAI5a,KAAK+G,GAAIP,IAAK,CACrB,GAAIqU,GAAI9T,EAAIP,IAAIxG,EAGhB,IAAiB,gBAAN6a,GAAgB,CACzBD,IAAYA,EAAQzZ,OAAS,KAAO,IAAM,IAAMnB,EAAI,GAEpD,IAAI8a,GAAqBhX,EAAO2V,qBAAoD,OAA7BzZ,EAAEwB,OAAOxB,EAAEmB,OAAS,EAAG,GAC1EoF,EAAOzC,EAAOiX,eAAe/a,EAC7B8a,IAAyD,OAAnCvU,EAAK/E,OAAO+E,EAAKpF,OAAS,EAAG,KACrDoF,EAAOA,EAAK/E,OAAO,EAAG+E,EAAKpF,OAAS,GAGtC,IAAI6Z,GAAW,EACf,KAAK,GAAI/T,KAAOnD,GAAOoD,SACjBX,EAAK/E,OAAO,EAAGyF,EAAI9F,SAAW8F,KACzBV,EAAKU,EAAI9F,SAA+B,KAApBoF,EAAKU,EAAI9F,UAC/B6Z,EAASha,MAAM,KAAKG,OAAS8F,EAAIjG,MAAM,KAAKG,SACjD6Z,EAAW/T,EAEX+T,IAAYlX,EAAOoD,SAAS8T,GAAU5T,OACxCb,EAAOA,EAAK/E,OAAO,EAAG+E,EAAKpF,OAAS2C,EAAOoD,SAAS8T,GAAU5T,KAAKjG,OAAS,GAE9E,IAAI8F,GAAMnD,EAAOoD,SAASX,GAAQzC,EAAOoD,SAASX,MAClDU,GAAIT,IAAMqU,MAGV/W,GAAO0C,IAAIxG,GAAK6a,EAGhBD,GACF/T,EAAKjE,KAAKkB,EAAQ,6BAA+B8W,EAAU,wJAA0J5a,EAAI,2BAG7N,GAAI+G,EAAI4T,mBAAoB,CAE1B,IAAK,GADDA,MACKzZ,EAAI,EAAGA,EAAI6F,EAAI4T,mBAAmBxZ,OAAQD,IAAK,CACtD,GAAIkD,GAAO2C,EAAI4T,mBAAmBzZ,GAC9B+Z,EAAgBC,KAAKC,IAAI/W,EAAKtE,YAAY,KAAO,EAAGsE,EAAKtE,YAAY,MACrEsb,EAAaxU,EAAYhE,KAAKkB,EAAQM,EAAK5C,OAAO,EAAGyZ,GACzDN,GAAmBzZ,GAAKka,EAAahX,EAAK5C,OAAOyZ,GAEnDnX,EAAO6W,mBAAqBA,EAG9B,GAAI5T,EAAI2T,QACN,IAAK,GAAI1a,KAAK+G,GAAI2T,QAAS,CAEzB,IAAK,GADDW,MACKna,EAAI,EAAGA,EAAI6F,EAAI2T,QAAQ1a,GAAGmB,OAAQD,IAAK,CAC9C,GAAI4Z,GAAqBhX,EAAO2V,qBAAoF,OAA7D1S,EAAI2T,QAAQ1a,GAAGkB,GAAGM,OAAOuF,EAAI2T,QAAQ1a,GAAGkB,GAAGC,OAAS,EAAG,GAC1Gma,EAAsBxX,EAAOiX,eAAehU,EAAI2T,QAAQ1a,GAAGkB,GAC3D4Z,IAAuF,OAAjEQ,EAAoB9Z,OAAO8Z,EAAoBna,OAAS,EAAG,KACnFma,EAAsBA,EAAoB9Z,OAAO,EAAG8Z,EAAoBna,OAAS,IACnFka,EAAOnb,KAAKob,GAEdxX,EAAO4W,QAAQ1a,GAAKqb,EAIxB,GAAItU,EAAIG,SACN,IAAK,GAAIlH,KAAK+G,GAAIG,SAAU,CAC1B,GAAIlH,EAAEjB,MAAM,oBACV,KAAM,IAAIJ,WAAU,IAAMqB,EAAI,iCAEhC,IAAIuG,GAAOK,EAAYhE,KAAKkB,EAAQ9D,EAGP,MAAzBuG,EAAKA,EAAKpF,OAAS,KACrBoF,EAAOA,EAAK/E,OAAO,EAAG+E,EAAKpF,OAAS,IAEtC2F,EAAahD,EAAQyC,EAAMQ,EAAIG,SAASlH,IAAI,GAIhD,IAAK,GAAIub,KAAKxU,GAAK,CACjB,GAAI8T,GAAI9T,EAAIwU,EAEZ,IAAIla,EAAQuB,MAAM,UAAW,MAAO,WAAY,UAAW,QAAS,WAAY,qBAC1E,mBAAoB,gBAAiB,aAAc,YAAa,cAAe,oBAAqB2Y,KAAM,EAGhH,GAAgB,gBAALV,IAAiBA,YAAa7U,OACvClC,EAAOyX,GAAKV,MAET,CACH/W,EAAOyX,GAAKzX,EAAOyX,MAEnB,KAAK,GAAIvb,KAAK6a,GAEZ,GAAS,QAALU,GAAuB,KAARvb,EAAE,GACnBmF,EAAOrB,EAAOyX,GAAGvb,GAAK8D,EAAOyX,GAAGvb,OAAU6a,EAAE7a,QAEzC,IAAS,QAALub,EAAa,CAEpB,GAAI1B,GAAWjT,EAAYhE,KAAKkB,EAAQ9D,EACpC8D,GAAO2V,qBAAkE,OAA3CI,EAASrY,OAAOqY,EAAS1Y,OAAS,EAAG,KAAgBoC,EAAQsW,KAC7FA,GAAY,OACd1U,EAAOrB,EAAOyX,GAAG1B,GAAY/V,EAAOyX,GAAG1B,OAAiBgB,EAAE7a,QAEvD,IAAS,YAALub,EAAiB,CACxB,GAAIT,GAAqBhX,EAAO2V,qBAAoD,OAA7BzZ,EAAEwB,OAAOxB,EAAEmB,OAAS,EAAG,GAC1EoF,EAAOzC,EAAOiX,eAAe/a,EAC7B8a,IAAyD,OAAnCvU,EAAK/E,OAAO+E,EAAKpF,OAAS,EAAG,KACrDoF,EAAOA,EAAK/E,OAAO,EAAG+E,EAAKpF,OAAS,IACtC2C,EAAOyX,GAAGhV,MAAWN,OAAO4U,EAAE7a,QAG9B8D,GAAOyX,GAAGvb,GAAK6a,EAAE7a,IAMzBoJ,EAAOtF,EAAQiD,EAAK,SAASA,GAC3BjD,EAAOuW,OAAOtT,GAAK,MA4FvB,WAUE,QAASyU,GAAW1X,EAAQsX,GAE1B,GAAIK,GAAuBC,EAAfC,EAAY,CACxB,KAAK,GAAI3b,KAAK8D,GAAOoD,SACfkU,EAAW5Z,OAAO,EAAGxB,EAAEmB,UAAYnB,GAAMob,EAAWja,SAAWnB,EAAEmB,QAAmC,MAAzBia,EAAWpb,EAAEmB,UAC1Fua,EAAS1b,EAAEgB,MAAM,KAAKG,OAClBua,EAASC,IACXF,EAASzb,EACT2b,EAAYD,GAIlB,OAAOD,GAGT,QAASG,GAAoB9X,EAAQmD,EAAKZ,EAASwV,EAASC,GAE1D,IAAKD,GAA0C,KAA/BA,EAAQA,EAAQ1a,OAAS,IAAa2a,GAAkB7U,EAAI8U,oBAAqB,EAC/F,MAAOF,EAET,IAAIG,IAAY,CAgBhB,IAbI/U,EAAIR,MACNwV,EAAehV,EAAIR,KAAMoV,EAAS,SAASK,EAAaC,EAAWC,GACjE,GAAkB,GAAdA,GAAmBF,EAAYpc,YAAY,MAAQoc,EAAY/a,OAAS,EAC1E,MAAO6a,IAAY,KAIpBA,GAAalY,EAAO2C,MACvBwV,EAAenY,EAAO2C,KAAMJ,EAAU,IAAMwV,EAAS,SAASK,EAAaC,EAAWC,GACpF,GAAkB,GAAdA,GAAmBF,EAAYpc,YAAY,MAAQoc,EAAY/a,OAAS,EAC1E,MAAO6a,IAAY,IAGrBA,EACF,MAAOH,EAIT,IAAIE,GAAmB,KAAO9U,EAAI8U,kBAAoB,KACtD,OAAIF,GAAQra,OAAOqa,EAAQ1a,OAAS4a,EAAiB5a,SAAW4a,EACvDF,EAAUE,EAEVF,EAGX,QAASQ,GAAuBvY,EAAQmD,EAAKZ,EAASwV,EAASC,GAE7D,IAAKD,EAAS,CACZ,IAAI5U,EAAIG,KAMN,MAAOf,IAAWvC,EAAO2V,oBAAsB,MAAQ,GALvDoC,GAAmC,MAAzB5U,EAAIG,KAAK5F,OAAO,EAAG,GAAayF,EAAIG,KAAK5F,OAAO,GAAKyF,EAAIG,KASvE,GAAIH,EAAIT,IAAK,CACX,GAAI8V,GAAU,KAAOT,EAEjB5S,EAAWvB,EAAYT,EAAIT,IAAK8V,EAQpC,IALKrT,IACHqT,EAAU,KAAOV,EAAoB9X,EAAQmD,EAAKZ,EAASwV,EAASC,GAChEQ,GAAW,KAAOT,IACpB5S,EAAWvB,EAAYT,EAAIT,IAAK8V,KAEhCrT,EAAU,CACZ,GAAIsT,GAASC,EAAU1Y,EAAQmD,EAAKZ,EAAS4C,EAAUqT,EAASR,EAChE,IAAIS,EACF,MAAOA,IAKb,MAAOlW,GAAU,IAAMuV,EAAoB9X,EAAQmD,EAAKZ,EAASwV,EAASC,GAG5E,QAASW,GAAaxT,EAAUsT,EAAQlW,EAASjC,GAE/C,GAAgB,KAAZ6E,EACF,KAAM,IAAIpH,OAAM,WAAawE,EAAU,mDAIzC,SAAIkW,EAAO/a,OAAO,EAAGyH,EAAS9H,SAAW8H,GAAY7E,EAAKjD,OAAS8H,EAAS9H,QAM9E,QAASqb,GAAU1Y,EAAQmD,EAAKZ,EAAS4C,EAAU7E,EAAM0X,GAC1B,KAAzB1X,EAAKA,EAAKjD,OAAS,KACrBiD,EAAOA,EAAK5C,OAAO,EAAG4C,EAAKjD,OAAS,GACtC,IAAIob,GAAStV,EAAIT,IAAIyC,EAErB,IAAqB,gBAAVsT,GACT,KAAM,IAAI1a,OAAM,wEAA0EoH,EAAW,OAAS5C,EAEhH,IAAKoW,EAAaxT,EAAUsT,EAAQlW,EAASjC,IAA0B,gBAAVmY,GAA7D,CAIA,GAAc,KAAVA,EACFA,EAASlW,MAGN,IAA2B,MAAvBkW,EAAO/a,OAAO,EAAG,GACxB,MAAO6E,GAAU,IAAMuV,EAAoB9X,EAAQmD,EAAKZ,EAASkW,EAAO/a,OAAO,GAAK4C,EAAK5C,OAAOyH,EAAS9H,QAAS2a,EAGpH,OAAOhY,GAAO4Y,cAAcH,EAASnY,EAAK5C,OAAOyH,EAAS9H,QAASkF,EAAU,MAG/E,QAASsW,GAAmB7Y,EAAQmD,EAAKZ,EAASwV,EAASC,GAEzD,IAAKD,EAAS,CACZ,IAAI5U,EAAIG,KAMN,MAAO6E,SAAQC,QAAQ7F,GAAWvC,EAAO2V,oBAAsB,MAAQ,IALvEoC,GAAmC,MAAzB5U,EAAIG,KAAK5F,OAAO,EAAG,GAAayF,EAAIG,KAAK5F,OAAO,GAAKyF,EAAIG,KASvE,GAAIkV,GAASrT,CAcb,OAZIhC,GAAIT,MACN8V,EAAU,KAAOT,EACjB5S,EAAWvB,EAAYT,EAAIT,IAAK8V,GAG3BrT,IACHqT,EAAU,KAAOV,EAAoB9X,EAAQmD,EAAKZ,EAASwV,EAASC,GAChEQ,GAAW,KAAOT,IACpB5S,EAAWvB,EAAYT,EAAIT,IAAK8V,OAI9BrT,EAAW2T,EAAM9Y,EAAQmD,EAAKZ,EAAS4C,EAAUqT,EAASR,GAAkB7P,QAAQC,WAC3FR,KAAK,SAAS6Q,GACb,MAAIA,GACKtQ,QAAQC,QAAQqQ,GAGlBtQ,QAAQC,QAAQ7F,EAAU,IAAMuV,EAAoB9X,EAAQmD,EAAKZ,EAASwV,EAASC,MAI9F,QAASe,GAAY/Y,EAAQmD,EAAKZ,EAAS4C,EAAUsT,EAAQnY,EAAM0X,GAGjE,GAAc,KAAVS,EACFA,EAASlW,MAGN,IAA2B,MAAvBkW,EAAO/a,OAAO,EAAG,GACxB,MAAOyK,SAAQC,QAAQ7F,EAAU,IAAMuV,EAAoB9X,EAAQmD,EAAKZ,EAASkW,EAAO/a,OAAO,GAAK4C,EAAK5C,OAAOyH,EAAS9H,QAAS2a,IACjIpQ,KAAK,SAASzI,GACb,MAAO6I,GAAuBlJ,KAAKkB,EAAQb,EAAMoD,EAAU,MAI/D,OAAOvC,GAAO2H,UAAU8Q,EAASnY,EAAK5C,OAAOyH,EAAS9H,QAASkF,EAAU,KAG3E,QAASuW,GAAM9Y,EAAQmD,EAAKZ,EAAS4C,EAAU7E,EAAM0X,GACtB,KAAzB1X,EAAKA,EAAKjD,OAAS,KACrBiD,EAAOA,EAAK5C,OAAO,EAAG4C,EAAKjD,OAAS,GAEtC,IAAIob,GAAStV,EAAIT,IAAIyC,EAErB,IAAqB,gBAAVsT,GACT,MAAKE,GAAaxT,EAAUsT,EAAQlW,EAASjC,GAEtCyY,EAAY/Y,EAAQmD,EAAKZ,EAAS4C,EAAUsT,EAAQnY,EAAM0X,GADxD7P,QAAQC,SAKnB,IAAIpI,EAAOqF,QACT,MAAO8C,SAAQC,QAAQ7F,EAAU,MAAQjC,EAG3C,IAAI0Y,MACAC,IACJ,KAAK,GAAIhQ,KAAKwP,GAAQ,CACpB,GAAIhB,GAAI1Q,EAAekC,EACvBgQ,GAAW7c,MACT4K,UAAWyQ,EACX/U,IAAK+V,EAAOxP,KAEd+P,EAAkB5c,KAAK4D,EAAe,OAAEyX,EAAE/Q,OAAQnE,IAIpD,MAAO4F,SAAQsD,IAAIuN,GAClBpR,KAAK,SAASsR,GAEb,IAAK,GAAI9b,GAAI,EAAGA,EAAI6b,EAAW5b,OAAQD,IAAK,CAC1C,GAAIqa,GAAIwB,EAAW7b,GAAG4J,UAClB1F,EAAQmC,EAAqBgU,EAAEhV,KAAMyW,EAAgB9b,GACzD,KAAKqa,EAAEnQ,QAAUhG,GAASmW,EAAEnQ,SAAWhG,EACrC,MAAO2X,GAAW7b,GAAGsF,OAG1BkF,KAAK,SAAS6Q,GACb,GAAIA,EAAQ,CACV,IAAKE,EAAaxT,EAAUsT,EAAQlW,EAASjC,GAC3C,MACF,OAAOyY,GAAY/Y,EAAQmD,EAAKZ,EAAS4C,EAAUsT,EAAQnY,EAAM0X,MA8JvE,QAASmB,GAAuB7Y,GAC9B,GAAI8Y,GAAe9Y,EAAKtE,YAAY,KAChCqB,EAAS+Z,KAAKC,IAAI+B,EAAe,EAAG9Y,EAAKtE,YAAY,KACzD,QACEqB,OAAQA,EACRgc,MAAO,GAAIC,QAAO,KAAOhZ,EAAK5C,OAAO,EAAGL,GAAQrC,QAAQ,qBAAsB,QAAQA,QAAQ,MAAO,WAAa,YAClHiF,SAAUmZ,IAAgB,GAK9B,QAASG,GAAsBvZ,EAAQsX,GAErC,IAAK,GADD/U,GAA6BiX,EAApBC,GAAa,EACjBrc,EAAI,EAAGA,EAAI4C,EAAO6W,mBAAmBxZ,OAAQD,IAAK,CACzD,GAAIsc,GAAoB1Z,EAAO6W,mBAAmBzZ,GAC9ClB,EAAI2a,EAAmB6C,KAAuB7C,EAAmB6C,GAAqBP,EAAuBO,GACjH,MAAIpC,EAAWja,OAASnB,EAAEmB,QAA1B,CAEA,GAAIpC,GAAQqc,EAAWrc,MAAMiB,EAAEmd,QAC3Bpe,GAAWsH,IAAckX,GAAcvd,EAAE+D,YAAasC,EAAQlF,OAASpC,EAAM,GAAGoC,WAClFkF,EAAUtH,EAAM,GAChBwe,GAAcvd,EAAE+D,SAChBuZ,EAAajX,EAAUmX,EAAkBhc,OAAOxB,EAAEmB,UAItD,GAAKkF,EAGL,OACEoX,YAAapX,EACbiX,WAAYA,GAIhB,QAASI,GAAsB5Z,EAAQuC,EAASsX,GAC9C,GAAIC,GAAe9Z,EAAO+Q,cAAgB/Q,CAM1C,QAHC8Z,EAAanX,KAAKkX,GAAiBC,EAAanX,KAAKkX,QAAsBrG,OAAS,OACrFsG,EAAanX,KAAKkX,GAAe7Z,OAAS,KAEnC8Z,EAAahS,KAAK+R,GACxBjS,KAAK,WACJ,GAAI3E,GAAM6W,EAAalb,IAAIib,GAAwB,OAYnD,OATI5W,GAAI8W,WACN9W,EAAMA,EAAI8W,UAGR9W,EAAIzE,UACNyE,EAAIN,KAAOM,EAAIzE,QACfuE,EAAKjE,KAAKkB,EAAQ,uBAAyB6Z,EAAgB,yFAGtD7W,EAAahD,EAAQuC,EAASU,GAAK,KAI9C,QAASkV,GAAe6B,EAASjC,EAASkC,GAExC,GACIC,EACJ,KAAK,GAAIxT,KAAUsT,GAAS,CAE1B,GAAIG,GAAgC,MAAvBzT,EAAOhJ,OAAO,EAAG,GAAa,KAAO,EAKlD,IAJIyc,IACFzT,EAASA,EAAOhJ,OAAO,IAEzBwc,EAAgBxT,EAAOnJ,QAAQ,KAC3B2c,KAAkB,GAGlBxT,EAAOhJ,OAAO,EAAGwc,IAAkBnC,EAAQra,OAAO,EAAGwc,IAClDxT,EAAOhJ,OAAOwc,EAAgB,IAAMnC,EAAQra,OAAOqa,EAAQ1a,OAASqJ,EAAOrJ,OAAS6c,EAAgB,IAErGD,EAAQvT,EAAQsT,EAAQG,EAASzT,GAASA,EAAOxJ,MAAM,KAAKG,QAC9D,OAIN,GAAI+c,GAAYJ,EAAQjC,IAAYiC,EAAQ3Z,gBAAkB2Z,EAAQ3Z,eAAe0X,GAAWiC,EAAQjC,GAAWiC,EAAQ,KAAOjC,EAC9HqC,IACFH,EAAQG,EAAWA,EAAW,GAldlC/a,EAAgB,SAASsO,GACvB,MAAO,YACLA,EAAY7O,KAAKxC,MACjBA,KAAK8G,YACL9G,KAAKua,yBAoOThY,EAAeO,UAAUwZ,cAAgB/Z,EAAeO,UAAU6X,eAAiBpY,EAAeO,UAAUuI,UAI5GzI,EAAK,iBAAkB,SAAS+X,GAC9B,MAAO,UAAS9X,EAAM+F,GACpB,GAAI5I,KAAK+I,QACP,MAAO4R,GAAenY,KAAKxC,KAAM6C,EAAM+F,GAAY,EAErD,IAAImV,GAAkBpD,EAAenY,KAAKxC,KAAM6C,EAAM+F,GAAY,EAElE,KAAK5I,KAAKqZ,oBACR,MAAO0E,EAET,IAAI9X,GAAUmV,EAAWpb,KAAM+d,GAE3BlX,EAAM7G,KAAK8G,SAASb,GACpB0V,EAAmB9U,GAAOA,EAAI8U,gBAalC,OAXwBrc,SAApBqc,GAAiC9U,GAAOA,EAAIR,MAC9CwV,EAAehV,EAAIR,KAAM0X,EAAgB3c,OAAO6E,GAAU,SAAS6V,EAAaC,EAAWC,GACzF,GAAkB,GAAdA,GAAmBF,EAAYpc,YAAY,MAAQoc,EAAY/a,OAAS,EAE1E,MADA4a,IAAmB,GACZ,KAIRA,KAAqB,GAASA,GAAwC,OAApBA,IAAiE,OAAnC9Y,EAAKzB,OAAOyB,EAAK9B,OAAS,EAAG,IAAwE,OAAzDgd,EAAgB3c,OAAO2c,EAAgBhd,OAAS,EAAG,KAClLgd,EAAkBA,EAAgB3c,OAAO,EAAG2c,EAAgBhd,OAAS,IAEhEgd,KAIXnb,EAAK,gBAAiB,SAAS0Z,GAC7B,MAAO,UAASzZ,EAAM+F,EAAYoV,GAChC,GAAIta,GAAS1D,IAKb,IAJAge,EAAWA,KAAa,EAIpBpV,EACF,GAAIqV,GAAoB7C,EAAW1X,EAAQkF,IACvClF,EAAO2V,qBAAsE,OAA/CzQ,EAAWxH,OAAOwH,EAAW7H,OAAS,EAAG,IACvEqa,EAAW1X,EAAQkF,EAAWxH,OAAO,EAAGwH,EAAW7H,OAAS;AAElE,GAAImd,GAAgBD,GAAqBva,EAAOoD,SAASmX,EAGzD,IAAIC,GAA4B,KAAXrb,EAAK,GAAW,CACnC,GAAIsb,GAAYD,EAAc9X,IAC1BgY,EAAiBD,GAAa7W,EAAY6W,EAAWtb,EAEzD,IAAIub,GAAsD,gBAA7BD,GAAUC,GAA6B,CAClE,GAAIjC,GAASC,EAAU1Y,EAAQwa,EAAeD,EAAmBG,EAAgBvb,EAAMmb,EACvF,IAAI7B,EACF,MAAOA,IAIb,GAAIzB,GAAqBhX,EAAO2V,qBAA0D,OAAnCxW,EAAKzB,OAAOyB,EAAK9B,OAAS,EAAG,GAGhFia,EAAasB,EAAc9Z,KAAKkB,EAAQb,EAAM+F,GAAY,EAG1D8R,IAAqE,OAA/CM,EAAW5Z,OAAO4Z,EAAWja,OAAS,EAAG,KACjE2Z,GAAqB,GACnBA,IACFM,EAAaA,EAAW5Z,OAAO,EAAG4Z,EAAWja,OAAS,GAExD,IAAIsd,GAAiBpB,EAAsBvZ,EAAQsX,GAC/C/U,EAAUoY,GAAkBA,EAAehB,aAAejC,EAAW1X,EAAQsX,EAEjF,KAAK/U,EACH,MAAO+U,IAAcN,EAAqB,MAAQ,GAEpD,IAAIe,GAAUT,EAAW5Z,OAAO6E,EAAQlF,OAAS,EAEjD,OAAOkb,GAAuBvY,EAAQA,EAAOoD,SAASb,OAAgBA,EAASwV,EAASuC,MAI5Fpb,EAAK,YAAa,SAASyI,GACzB,MAAO,UAASxI,EAAM+F,EAAYoV,GAChC,GAAIta,GAAS1D,IAGb,OAFAge,GAAWA,KAAa,EAEjBnS,QAAQC,UACdR,KAAK,WAGJ,GAAI1C,EACF,GAAIqV,GAAoB7C,EAAW1X,EAAQkF,IACvClF,EAAO2V,qBAAsE,OAA/CzQ,EAAWxH,OAAOwH,EAAW7H,OAAS,EAAG,IACvEqa,EAAW1X,EAAQkF,EAAWxH,OAAO,EAAGwH,EAAW7H,OAAS,GAElE,IAAImd,GAAgBD,GAAqBva,EAAOoD,SAASmX,EAGzD,IAAIC,GAAsC,MAArBrb,EAAKzB,OAAO,EAAG,GAAY,CAC9C,GAAI+c,GAAYD,EAAc9X,IAC1BgY,EAAiBD,GAAa7W,EAAY6W,EAAWtb,EAEzD,IAAIub,EACF,MAAO5B,GAAM9Y,EAAQwa,EAAeD,EAAmBG,EAAgBvb,EAAMmb,GAGjF,MAAOnS,SAAQC,YAEhBR,KAAK,SAAS6Q,GACb,GAAIA,EACF,MAAOA,EAET,IAAIzB,GAAqBhX,EAAO2V,qBAA0D,OAAnCxW,EAAKzB,OAAOyB,EAAK9B,OAAS,EAAG,GAGhFia,EAAa3P,EAAU7I,KAAKkB,EAAQb,EAAM+F,GAAY,EAGtD8R,IAAqE,OAA/CM,EAAW5Z,OAAO4Z,EAAWja,OAAS,EAAG,KACjE2Z,GAAqB,GACnBA,IACFM,EAAaA,EAAW5Z,OAAO,EAAG4Z,EAAWja,OAAS,GAExD,IAAIsd,GAAiBpB,EAAsBvZ,EAAQsX,GAC/C/U,EAAUoY,GAAkBA,EAAehB,aAAejC,EAAW1X,EAAQsX,EAEjF,KAAK/U,EACH,MAAO4F,SAAQC,QAAQkP,GAAcN,EAAqB,MAAQ,IAEpE,IAAI7T,GAAMnD,EAAOoD,SAASb,GAGtBqY,EAAezX,IAAQA,EAAI0X,aAAeF,EAC9C,QAAQC,EAAezS,QAAQC,QAAQjF,GAAOyW,EAAsB5Z,EAAQuC,EAASoY,EAAenB,aACnG5R,KAAK,SAASzE,GACb,GAAI4U,GAAUT,EAAW5Z,OAAO6E,EAAQlF,OAAS,EAEjD,OAAOwb,GAAmB7Y,EAAQmD,EAAKZ,EAASwV,EAASuC,SAQjE,IAAIzD,KA0FJ3X,GAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,GAAI9H,GAAS1D,IACb,OAAO6L,SAAQC,QAAQ0C,EAAOhM,KAAKxC,KAAMwL,IACxCF,KAAK,SAASsC,GACb,GAAI3H,GAAUmV,EAAW1X,EAAQ8H,EAAK3I,KACtC,IAAIoD,EAAS,CACX,GAAIY,GAAMnD,EAAOoD,SAASb,GACtBwV,EAAUjQ,EAAK3I,KAAKzB,OAAO6E,EAAQlF,OAAS,GAE5CsF,IACJ,IAAIQ,EAAIR,KAAM,CACZ,GAAImY,GAAY,CAGhB3C,GAAehV,EAAIR,KAAMoV,EAAS,SAASK,EAAaC,EAAWC,GAC7DA,EAAawC,IACfA,EAAYxC,GACdtW,EAAWW,EAAM0V,EAAWC,GAAcwC,EAAYxC,KAGxDtW,EAAW8F,EAAKgC,SAAUnH,GAIxBQ,EAAIqQ,SAAW1L,EAAKgC,SAAS9J,SAC/B8H,EAAKgC,SAAS0J,OAAS1L,EAAKgC,SAAS0J,QAAUrQ,EAAIqQ,QAGvD,MAAOtJ,WAWf,WAsBE,QAAS6Q,KACP,GAAIC,GAA6D,gBAAxCA,EAAkBvJ,OAAO9B,WAChD,MAAOqL,GAAkBlT,IAE3B,KAAK,GAAI1K,GAAI,EAAGA,EAAI6d,EAA0B5d,OAAQD,IACpD,GAAsD,eAAlD6d,EAA0B7d,GAAGqU,OAAO9B,WAEtC,MADAqL,GAAoBC,EAA0B7d,GACvC4d,EAAkBlT,KA0C/B,QAASoT,GAAgBlb,EAAQ8H,GAC/B,MAAO,IAAIK,SAAQ,SAASC,EAASuC,GAC/B7C,EAAKgC,SAAS2K,WAChB9J,EAAO,GAAI5M,OAAM,oEAEnBod,EAAarT,CACb,KACEY,cAAcZ,EAAKoC,SAErB,MAAMjB,GACJkS,EAAa,KACbxQ,EAAO1B,GAETkS,EAAa,KAGRrT,EAAKgC,SAASqM,OACjBxL,EAAO,GAAI5M,OAAM+J,EAAKoC,QAAU,+GAElC9B,EAAQ,MAxFZ,GAAuB,mBAAZO,UACT,GAAIuL,GAAOvL,SAASS,qBAAqB,QAAQ,EAEnD,IAAI0K,GACAsH,EAeAJ,EAZAG,EAAa,KAGbE,EAAWnH,GAAQ,WACrB,GAAIoH,GAAI3S,SAAS0L,cAAc,UAC3BkH,EAA2B,mBAAVC,QAA8C,mBAArBA,MAAMve,UACpD,OAAOqe,GAAEG,eAAiBH,EAAEG,YAAYxe,UAAYqe,EAAEG,YAAYxe,WAAWM,QAAQ,gBAAkB,KAAOge,KAK5GN,KAkBAS,EAAa,EACbC,IACJzc,GAAK,gBAAiB,SAAS0c,GAC7B,MAAO,UAAS9G,GAEd,OAAI8G,EAAa9c,KAAKxC,KAAMwY,KAIxBqG,EACF7e,KAAKyY,gBAAgBoG,EAAYrG,GAI1BuG,EACP/e,KAAKyY,gBAAgBgG,IAA4BjG,GAI1C4G,EACPC,EAAcvf,KAAK0Y,GAOnBxY,KAAKyY,gBAAgB,KAAMD,IAEtB,MA4BX5V,EAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GACd,GAAI9H,GAAS1D,IAEb,OAA4B,QAAxBwL,EAAKgC,SAAS0J,QAAqB1L,EAAKgC,SAAS+R,aAAgBle,GAAc6K,GAG/EA,EACK0S,EAAgBlb,EAAQ8H,GAE1B,GAAIK,SAAQ,SAASC,EAASuC,GA+BnC,QAASmR,GAASC,GAChB,IAAIT,EAAE3L,YAA8B,UAAhB2L,EAAE3L,YAA0C,YAAhB2L,EAAE3L,WAAlD,CAOA,GAJA+L,IAIK5T,EAAKgC,SAASqM,OAAUwF,EAActe,QAGtC,IAAKge,EAAU,CAClB,IAAK,GAAIje,GAAI,EAAGA,EAAIue,EAActe,OAAQD,IACxC4C,EAAO+U,gBAAgBjN,EAAM6T,EAAcve,GAC7Cue,WALA3b,GAAO+U,gBAAgBjN,EAQzBkU,KAGKlU,EAAKgC,SAASqM,OAAUrO,EAAKgC,SAASyN,QACzC5M,EAAO,GAAI5M,OAAM+J,EAAK3I,KAAO,kKAE/BiJ,EAAQ,KAGV,QAASmE,GAAMwP,GACbC,IACArR,EAAO,GAAI5M,OAAM,yBAA2B+J,EAAKoC,UAGnD,QAAS8R,KAIP,GAHAtf,EAAS8R,OAASsF,EAClBpX,EAASuI,QAAUmW,EAEfE,EAAEW,YAAa,CACjBX,EAAEW,YAAY,qBAAsBH,EACpC,KAAK,GAAI1e,GAAI,EAAGA,EAAI6d,EAA0B5d,OAAQD,IAChD6d,EAA0B7d,GAAGqU,QAAU6J,IACrCN,GAAqBA,EAAkBvJ,QAAU6J,IACnDN,EAAoB,MACtBC,EAA0BhO,OAAO7P,EAAG,QAIxCke,GAAEY,oBAAoB,OAAQJ,GAAU,GACxCR,EAAEY,oBAAoB,QAAS3P,GAAO,EAGxC2H,GAAKW,YAAYyG,GA/EnB,GAAIA,GAAI3S,SAAS0L,cAAc,SAE/BiH,GAAEa,OAAQ,EAENrU,EAAKgC,SAASsS,cAChBd,EAAEc,YAActU,EAAKgC,SAASsS,aAE5BtU,EAAKgC,SAAS2K,WAChB6G,EAAE5G,aAAa,YAAa5M,EAAKgC,SAAS2K,WAExC4G,GACFC,EAAEG,YAAY,qBAAsBK,GACpCb,EAA0B7e,MACxBqV,OAAQ6J,EACRxT,KAAMA,MAIRwT,EAAE1L,iBAAiB,OAAQkM,GAAU,GACrCR,EAAE1L,iBAAiB,QAASrD,GAAO,IAGrCmP,IAEA5H,EAAYpX,EAAS8R,OACrB4M,EAAa1e,EAASuI,QAEtBqW,EAAE9d,IAAMsK,EAAKoC,QACbgK,EAAKU,YAAY0G,KAlCVtQ,EAAMlM,KAAKxC,KAAMwL,QAgJhC,IAAI9B,IAA6B,2FAwBjC,WAsGE,QAASqW,GAAYlG,EAAOnW,EAAQsc,GAGlC,GAFAA,EAAOnG,EAAM3P,YAAc8V,EAAOnG,EAAM3P,gBAEpCjJ,EAAQuB,KAAKwd,EAAOnG,EAAM3P,YAAa2P,KAAU,EAArD,CAGAmG,EAAOnG,EAAM3P,YAAYpK,KAAK+Z,EAE9B,KAAK,GAAI/Y,GAAI,EAAG0D,EAAIqV,EAAM5P,eAAelJ,OAAQD,EAAI0D,EAAG1D,IAAK,CAC3D,GAAImf,GAAUpG,EAAM5P,eAAenJ,GAC/Bof,EAAWxc,EAAOyc,QAAQF,EAG9B,IAAKC,IAAYA,EAAS/V,UAA1B,CAIA,GAAIiW,GAAgBvG,EAAM3P,YAAcgW,EAASlW,aAAe6P,EAAM7P,YAGtE,IAA4B,OAAxBkW,EAAShW,YAAuBgW,EAAShW,WAAakW,EAAe,CAGvE,GAA4B,OAAxBF,EAAShW,aACX8V,EAAOE,EAAShW,YAAYyG,OAAO1P,EAAQuB,KAAKwd,EAAOE,EAAShW,YAAagW,GAAW,GAG9C,GAAtCF,EAAOE,EAAShW,YAAYnJ,QAC9B,KAAM,IAAIU,OAAM,kCAGpBye,GAAShW,WAAakW,EAGxBL,EAAYG,EAAUxc,EAAQsc,MAIlC,QAAS9P,GAAKrN,EAAMwd,EAAY3c,GAE9B,IAAI2c,EAAWjW,OAAf,CAGAiW,EAAWnW,WAAa,CAExB,IAAI8V,KAEJD,GAAYM,EAAY3c,EAAQsc,EAGhC,KAAK,GADDM,KAAwBD,EAAWrW,aAAegW,EAAOjf,OAAS,EAC7DD,EAAIkf,EAAOjf,OAAS,EAAGD,GAAK,EAAGA,IAAK,CAE3C,IAAK,GADDsD,GAAQ4b,EAAOlf,GACViP,EAAI,EAAGA,EAAI3L,EAAMrD,OAAQgP,IAAK,CACrC,GAAI8J,GAAQzV,EAAM2L,EAGduQ,GACFC,EAAsB1G,EAAOnW,GAE7B8c,EAAkB3G,EAAOnW,GAE7B4c,GAAuBA,IAK3B,QAASG,MAOT,QAASC,GAAwB7d,EAAMT,GACrC,MAAOA,GAAcS,KAAUT,EAAcS,IAC3CA,KAAMA,EACN0K,gBACA5I,QAAS,GAAI8b,GACbE,eAIJ,QAASJ,GAAsB1G,EAAOnW,GAEpC,IAAImW,EAAMzP,OAAV,CAGA,GAAIhI,GAAgBsB,EAAO3B,QAAQK,cAC/BgI,EAASyP,EAAMzP,OAASsW,EAAwB7G,EAAMhX,KAAMT,GAC5DuC,EAAUkV,EAAMzP,OAAOzF,QAEvBic,EAAc/G,EAAMhQ,QAAQrH,KAAKpC,EAAU,SAASyC,EAAMmC,GAG5D,GAFAoF,EAAOyW,QAAS,EAEG,gBAARhe,GACT,IAAK,GAAIjD,KAAKiD,GACZ8B,EAAQ/E,GAAKiD,EAAKjD,OAGpB+E,GAAQ9B,GAAQmC,CAGlB,KAAK,GAAIlE,GAAI,EAAG0D,EAAI4F,EAAOuW,UAAU5f,OAAQD,EAAI0D,EAAG1D,IAAK,CACvD,GAAIggB,GAAiB1W,EAAOuW,UAAU7f,EACtC,KAAKggB,EAAeD,OAAQ,CAC1B,GAAIE,GAAgB9f,EAAQuB,KAAKse,EAAevT,aAAcnD,GAC1D4W,EAASF,EAAeG,QAAQF,EAChCC,IACFA,EAAOrc,IAKb,MADAyF,GAAOyW,QAAS,EACT7b,IACJkc,GAAIrH,EAAMhX,MAWf,IAT0B,kBAAf+d,KACTA,GAAgBK,WAAanX,QAAS8W,IAGxCA,EAAcA,IAAiBK,WAAanX,QAAS,cAErDM,EAAO6W,QAAUL,EAAYK,QAC7B7W,EAAON,QAAU8W,EAAY9W,SAExBM,EAAO6W,UAAY7W,EAAON,QAC7B,KAAM,IAAIvL,WAAU,oCAAsCsb,EAAMhX,KAIlE,KAAK,GAAI/B,GAAI,EAAG0D,EAAIqV,EAAM5P,eAAelJ,OAAQD,EAAI0D,EAAG1D,IAAK,CAC3D,GAKIqgB,GALAlB,EAAUpG,EAAM5P,eAAenJ,GAC/Bof,EAAWxc,EAAOyc,QAAQF,GAC1BmB,EAAYhf,EAAc6d,EAK1BmB,GACFD,EAAaC,EAAUzc,QAGhBub,IAAaA,EAASlW,YAC7BmX,EAAajB,EAAStb,SAGdsb,GAKRK,EAAsBL,EAAUxc,GAChC0d,EAAYlB,EAAS9V,OACrB+W,EAAaC,EAAUzc,SANvBwc,EAAazd,EAAOpB,IAAI2d,GAUtBmB,GAAaA,EAAUT,WACzBS,EAAUT,UAAU7gB,KAAKsK,GACzBA,EAAOmD,aAAazN,KAAKshB,IAGzBhX,EAAOmD,aAAazN,KAAK,KAK3B,KAAK,GADD8J,GAAkBiQ,EAAMjQ,gBAAgB9I,GACnCiP,EAAI,EAAGsR,EAAMzX,EAAgB7I,OAAQgP,EAAIsR,IAAOtR,EAAG,CAC1D,GAAItL,GAAQmF,EAAgBmG,EACxB3F,GAAO6W,QAAQxc,IACjB2F,EAAO6W,QAAQxc,GAAO0c,MAO9B,QAASG,GAAUze,EAAMa,GACvB,GAAIiB,GACAkV,EAAQnW,EAAOyc,QAAQtd,EAE3B,IAAKgX,EAOCA,EAAM7P,YACRuX,EAAgB1e,EAAMgX,KAAWnW,GAEzBmW,EAAM1P,WACdqW,EAAkB3G,EAAOnW,GAE3BiB,EAAUkV,EAAMzP,OAAOzF,YAXvB,IADAA,EAAUjB,EAAOpB,IAAIO,IAChB8B,EACH,KAAM,IAAIlD,OAAM,6BAA+BoB,EAAO,IAa1D,SAAMgX,GAASA,EAAM7P,cAAgBrF,GAAWA,EAAQ+P,aAC/C/P,EAAiB,QAEnBA,EAGT,QAAS6b,GAAkB3G,EAAOnW,GAChC,IAAImW,EAAMzP,OAAV,CAGA,GAAIzF,MAEAyF,EAASyP,EAAMzP,QAAWzF,QAASA,EAASuc,GAAIrH,EAAMhX,KAG1D,KAAKgX,EAAM9P,iBACT,IAAK,GAAIjJ,GAAI,EAAG0D,EAAIqV,EAAM5P,eAAelJ,OAAQD,EAAI0D,EAAG1D,IAAK,CAC3D,GAAImf,GAAUpG,EAAM5P,eAAenJ,GAE/Bof,EAAWxc,EAAOyc,QAAQF,EAC1BC,IACFM,EAAkBN,EAAUxc,GAKlCmW,EAAM1P,WAAY,CAClB,IAAIxK,GAASka,EAAM/P,QAAQtH,KAAKpC,EAAU,SAASyC,GACjD,IAAK,GAAI/B,GAAI,EAAG0D,EAAIqV,EAAMxV,KAAKtD,OAAQD,EAAI0D,EAAG1D,IAC5C,GAAI+Y,EAAMxV,KAAKvD,IAAM+B,EAErB,MAAOye,GAAUzH,EAAM5P,eAAenJ,GAAI4C,EAG5C,IAAI8d,GAAiB9d,EAAO4Y,cAAczZ,EAAMgX,EAAMhX,KACtD,IAAI5B,EAAQuB,KAAKqX,EAAM5P,eAAgBuX,KAAmB,EACxD,MAAOF,GAAUE,EAAgB9d,EAEnC,MAAM,IAAIjC,OAAM,UAAYoB,EAAO,oCAAsCgX,EAAMhX,OAC9E8B,EAASyF,EAEG9K,UAAXK,IACFyK,EAAOzF,QAAUhF,GAGnBgF,EAAUyF,EAAOzF,QAGbA,IAAYA,EAAQ8c,YAAc9c,YAAmB/C,IACvDiY,EAAMjV,SAAWlB,EAAOsE,UAAUrD,GAE3BkV,EAAMxP,YAAc1F,IAAYvE,EACvCyZ,EAAMjV,SAAWlB,EAAOsE,UAAUtD,EAAYC,IAG9CkV,EAAMjV,SAAWlB,EAAOsE,WAAYO,QAAW5D,EAAS+P,cAAc,KAY1E,QAAS6M,GAAgB1T,EAAYgM,EAAO6H,EAAMhe,GAEhD,GAAKmW,IAASA,EAAM1P,WAAc0P,EAAM7P,YAAxC,CAKA0X,EAAK5hB,KAAK+N,EAEV,KAAK,GAAI/M,GAAI,EAAG0D,EAAIqV,EAAM5P,eAAelJ,OAAQD,EAAI0D,EAAG1D,IAAK,CAC3D,GAAImf,GAAUpG,EAAM5P,eAAenJ,EAC/BG,GAAQuB,KAAKkf,EAAMzB,KAAY,IAC5Bvc,EAAOyc,QAAQF,GAGlBsB,EAAgBtB,EAASvc,EAAOyc,QAAQF,GAAUyB,EAAMhe,GAFxDA,EAAOpB,IAAI2d,IAMbpG,EAAM1P,YAGV0P,EAAM1P,WAAY,EAClB0P,EAAMzP,OAAON,QAAQtH,KAAKpC,KAvX5BmC,EAAeO,UAAU0V,SAAW,SAAS3V,EAAMwB,EAAMwF,GASvD,GARmB,gBAARhH,KACTgH,EAAUxF,EACVA,EAAOxB,EACPA,EAAO,MAKa,iBAAXgH,GACT,MAAO7J,MAAK2hB,gBAAgB1J,MAAMjY,KAAMkY,UAE1C,IAAI2B,GAAQlQ,GAIZkQ,GAAMhX,KAAOA,IAAS7C,KAAK2a,gBAAkB3a,KAAKqL,WAAW7I,KAAKxC,KAAM6C,GACxEgX,EAAM7P,aAAc,EACpB6P,EAAMxV,KAAOA,EACbwV,EAAMhQ,QAAUA,EAEhB7J,KAAK4hB,eACHC,KAAK,EACLhI,MAAOA,KAGXtX,EAAeO,UAAU6e,gBAAkB,SAAS9e,EAAMwB,EAAMwF,EAASC,GACpD,gBAARjH,KACTiH,EAAUD,EACVA,EAAUxF,EACVA,EAAOxB,EACPA,EAAO,KAIT,IAAIgX,GAAQlQ,GACZkQ,GAAMhX,KAAOA,IAAS7C,KAAK2a,gBAAkB3a,KAAKqL,WAAW7I,KAAKxC,KAAM6C,GACxEgX,EAAMxV,KAAOA,EACbwV,EAAM/P,QAAUA,EAChB+P,EAAM9P,iBAAmBF,EAEzB7J,KAAK4hB,eACHC,KAAK,EACLhI,MAAOA,KAGXjX,EAAK,kBAAmB,WACtB,MAAO,UAAS4I,EAAMgN,GACpB,GAAKA,EAAL,CAGA,GAAIqB,GAAQrB,EAASqB,MACjBiI,EAAUtW,GAAQA,EAAKgC,QAW3B,IARIqM,EAAMhX,OACFgX,EAAMhX,OAAQ7C,MAAKmgB,UACvBngB,KAAKmgB,QAAQtG,EAAMhX,MAAQgX,GAEzBiI,IACFA,EAAQ7G,QAAS,KAGhBpB,EAAMhX,MAAQ2I,IAASsW,EAAQjI,OAASA,EAAMhX,MAAQ2I,EAAK3I,KAAM,CACpE,IAAKif,EACH,KAAM,IAAIvjB,WAAU,+IACtB,IAAIujB,EAAQjI,MACV,KAAsB,YAAlBiI,EAAQ5K,OACJ,GAAIzV,OAAM,sDAAwD+J,EAAK3I,KAAO,0EAE9E,GAAIpB,OAAM,UAAY+J,EAAK3I,KAAO,mBAAqBif,EAAQ5K,OAAS,8CAE7E4K,GAAQ5K,SACX4K,EAAQ5K,OAAS,YACnB4K,EAAQjI,MAAQA,OAKtB9W,EAAgB,SAASsO,GACvB,MAAO,YACLA,EAAY7O,KAAKxC,MAEjBA,KAAKmgB,WACLngB,KAAK+B,QAAQK,oBAuEjBC,EAAeoe,EAAc,YAC3Bzb,MAAO,WACL,MAAO,YA8NXpC,EAAK,SAAU,SAASmf,GACtB,MAAO,UAASlf,GAGd,aAFO7C,MAAK+B,QAAQK,cAAcS,SAC3B7C,MAAKmgB,QAAQtd,GACbkf,EAAIvf,KAAKxC,KAAM6C,MAI1BD,EAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GACd,MAAIxL,MAAKmgB,QAAQ3U,EAAK3I,OACpB2I,EAAKgC,SAAS0J,OAAS,UAChB,KAGT1L,EAAKgC,SAASnJ,KAAOmH,EAAKgC,SAASnJ,SAE5BqK,EAAMlM,KAAKxC,KAAMwL,OAI5B5I,EAAK,YAAa,SAAS+L,GAEzB,MAAO,UAASnD,GAEd,MADAA,GAAKgC,SAASnJ,KAAOmH,EAAKgC,SAASnJ,SAC5BwH,QAAQC,QAAQ6C,EAAUsJ,MAAMjY,KAAMkY,YAAY5M,KAAK,SAAS9B,GAIrE,OAF4B,YAAxBgC,EAAKgC,SAAS0J,SAAyB1L,EAAKgC,SAAS0J,QAAU3N,EAAqBiC,EAAKhC,WAC3FgC,EAAKgC,SAAS0J,OAAS,YAClB1N,OAMb5G,EAAK,OAAQ,SAASof,GACpB,MAAO,UAAShH,GACd,GAAItX,GAAS1D,KACT6Z,EAAQnW,EAAOyc,QAAQnF,EAE3B,QAAKnB,GAASA,EAAMxV,KAAKtD,OAChBihB,EAAO/J,MAAMjY,KAAMkY,YAE5B2B,EAAMjQ,gBAAkBiQ,EAAM5P,kBAI9BiG,EAAK8K,EAAYnB,EAAOnW,GAGxB6d,EAAgBvG,EAAYnB,KAAWnW,GAClCmW,EAAMjV,WACTiV,EAAMjV,SAAWlB,EAAOsE,UAAU6R,EAAMzP,OAAOzF,UAG5CjB,EAAOmN,QACVnN,EAAOyc,QAAQnF,GAAc1b,QAG/BoE,EAAOoE,IAAIkT,EAAYnB,EAAMjV,UAEtBiH,QAAQC,cAInBlJ,EAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACc,UAAxBA,EAAKgC,SAAS0J,SAChB1L,EAAKgC,SAAS0J,OAAS5X,QAIzBsP,EAAYpM,KAAKxC,KAAMwL,EAEvB,IAEIqO,GAFAnW,EAAS1D,IAKb,IAAI0D,EAAOyc,QAAQ3U,EAAK3I,MACtBgX,EAAQnW,EAAOyc,QAAQ3U,EAAK3I,MAEvBgX,EAAM7P,cACT6P,EAAMxV,KAAOwV,EAAMxV,KAAKwB,OAAO2F,EAAKgC,SAASnJ,OAC/CwV,EAAMxV,KAAOwV,EAAMxV,KAAKwB,OAAO2F,EAAKgC,SAASnJ,UAK1C,IAAImH,EAAKgC,SAASqM,MACrBA,EAAQrO,EAAKgC,SAASqM,MACtBA,EAAMxV,KAAOwV,EAAMxV,KAAKwB,OAAO2F,EAAKgC,SAASnJ,UAK1C,MAAMX,EAAOqF,SAAWyC,EAAKgC,SAASyN,QACX,YAAxBzP,EAAKgC,SAAS0J,QAAgD,OAAxB1L,EAAKgC,SAAS0J,QAA2C,OAAxB1L,EAAKgC,SAAS0J,QAAkB,CAK7G,GAHqB,mBAAVX,KACTA,GAAO/T,KAAKkB,EAAQ8H,IAEjBA,EAAKgC,SAASqM,QAAUrO,EAAKgC,SAASyN,OACzC,KAAM,IAAIxZ,OAAM+J,EAAK3I,KAAO,gBAAkB2I,EAAKgC,SAAS0J,OAAS,uBAEvE2C,GAAQrO,EAAKgC,SAASqM,MAGlBA,GAASrO,EAAKgC,SAASnJ,OACzBwV,EAAMxV,KAAOwV,EAAMxV,KAAKwB,OAAO2F,EAAKgC,SAASnJ,OAI5CwV,IACHA,EAAQlQ,IACRkQ,EAAMxV,KAAOmH,EAAKgC,SAASnJ,KAC3BwV,EAAM/P,QAAU,cAIlBpG,EAAOyc,QAAQ3U,EAAK3I,MAAQgX,CAE5B,IAAIoI,GAAU7d,EAAMyV,EAAMxV,KAE1BwV,GAAMxV,KAAO4d,EAAQ3d,MACrBuV,EAAMjQ,gBAAkBqY,EAAQ1d,QAChCsV,EAAMhX,KAAO2I,EAAK3I,KAClBgX,EAAMxP,WAAamB,EAAKgC,SAASnD,cAAe,CAIhD,KAAK,GADD6X,MACKphB,EAAI,EAAG0D,EAAIqV,EAAMxV,KAAKtD,OAAQD,EAAI0D,EAAG1D,IAC5CohB,EAAkBpiB,KAAK+L,QAAQC,QAAQpI,EAAO2H,UAAUwO,EAAMxV,KAAKvD,GAAI0K,EAAK3I,OAE9E,OAAOgJ,SAAQsD,IAAI+S,GAAmB5W,KAAK,SAASrB,GAIlD,MAFA4P,GAAM5P,eAAiBA,GAGrB5F,KAAMwV,EAAMxV,KACZyF,QAAS,WAgBP,MAbAoG,GAAK1E,EAAK3I,KAAMgX,EAAOnW,GAGvB6d,EAAgB/V,EAAK3I,KAAMgX,KAAWnW,GAEjCmW,EAAMjV,WACTiV,EAAMjV,SAAWlB,EAAOsE,UAAU6R,EAAMzP,OAAOzF,UAG5CjB,EAAOmN,QACVnN,EAAOyc,QAAQ3U,EAAK3I,MAAQvD,QAGvBua,EAAMjV,mBAUzB,WAEE,GAAIud,GAAW,gLAEXC,EAAsB,wBACtBC,EAAoB,mBAExBzf,GAAK,YAAa,SAAS+L,GACzB,MAAO,UAASnD,GACd,GAAI9H,GAAS1D,KACTsiB,EAAOpK,SACX,OAAOvJ,GAAUsJ,MAAMvU,EAAQ4e,GAC9BhX,KAAK,SAAS9B,GAEb,GAA4B,OAAxBgC,EAAKgC,SAAS0J,QAA2C,OAAxB1L,EAAKgC,SAAS0J,SAAoB1L,EAAKgC,SAAS0J,QAAU1N,EAAO7K,MAAMwjB,GAAW,CAMrH,GAL4B,OAAxB3W,EAAKgC,SAAS0J,QAChBzQ,EAAKjE,KAAKkB,EAAQ,UAAY8H,EAAK3I,KAAO,qGAE5C2I,EAAKgC,SAAS0J,OAAS,MAEnB1L,EAAKgC,SAASnJ,KAAM,CAEtB,IAAK,GADDke,GAAY,GACPzhB,EAAI,EAAGA,EAAI0K,EAAKgC,SAASnJ,KAAKtD,OAAQD,IAC7CyhB,GAAa,WAAa/W,EAAKgC,SAASnJ,KAAKvD,GAAK,KACpD0K,GAAKhC,OAAS+Y,EAAY/Y,EAG5B,GAAI9F,EAAO8Q,cAAe,EAAO,CAE/B,GAAI9Q,EAAOqF,QACT,MAAOS,EACT,MAAM,IAAIjL,WAAU,kFAUtB,MALAmF,GAAO3B,QAAQygB,iBAAmB9e,EAAO3B,QAAQygB,mBAAoB,EACjE9e,EAAO+Q,eACT/Q,EAAO+Q,aAAa1S,QAAQygB,iBAAmB9e,EAAO3B,QAAQygB,mBAAoB,IAG5E9e,EAAO3B,QAAQ0gB,oBACrB/e,EAAO3B,QAAQ0gB,kBAAoB5W,QAAQC,QACzC1L,EAA8B,cAArBsD,EAAO8Q,WAA6B,KAAO9Q,EAAO8Q,cAAgB9Q,EAAO+Q,cAAgB/Q,GAAgB,OAAEA,EAAO8Q,eAC3HlJ,KAAK,SAASkJ,GAIhB,MAHA9Q,GAAO3B,QAAQsY,yBAA0B,EAGrC7F,EAAW7F,UAET6F,GAAchJ,EAAKgC,SAASkV,aACvBlX,EAAKhC,QAGwB,gBAA3BgC,GAAKgC,SAAS+H,YACvB/J,EAAKgC,SAAS+H,UAAY4B,KAAK2C,MAAMtO,EAAKgC,SAAS+H,YAE9C1J,QAAQC,QAAQ0I,EAAW7F,UAAUsJ,MAAMvU,EAAQ4e,IACzDhX,KAAK,SAAS9B,GAEb,GAAI+L,GAAY/J,EAAKgC,SAAS+H,SAC9B,IAAIA,GAAiC,gBAAbA,GAAuB,CAC7C,GAAIoN,GAAenX,EAAKoC,QAAQhN,MAAM,KAAK,EAGtC2U,GAAUqN,MAAQrN,EAAUqN,MAAQpX,EAAKoC,UAC5C2H,EAAUqN,KAAOD,EAAe,iBAG7BpN,EAAUsN,SAAWtN,EAAUsN,QAAQ9hB,QAAU,KAAOwU,EAAUsN,QAAQ,IAAMtN,EAAUsN,QAAQ,IAAMrX,EAAKoC,YAChH2H,EAAUsN,SAAWF,IAKzB,MAF4B,OAAxBnX,EAAKgC,SAAS0J,SAAoBxT,EAAOqF,SAAWQ,EAAqBC,KAC3EgC,EAAKgC,SAAS0J,OAAS,YAClB1N,MAKP9F,EAAOqF,UACTyC,EAAKgC,SAASsV,eAAiBtX,EAAKhC,QAG/B+K,EAAU/R,KAAKkB,EAAQ8H,GAC7BF,KAAK,SAAS9B,GAGb,MADAgC,GAAKgC,SAAS+H,UAAYjW,OACnBkK,MAER,SAASlJ,GACV,KAAMD,GAAWC,EAAK,0CAA4CkL,EAAK3I,QAK3E,GAAIa,EAAO8Q,cAAe,EACxB,MAAOhL,EA+BT,IA5BI9F,EAAO3B,QAAQygB,oBAAqB,GAA+B,WAArB9e,EAAO8Q,YAAgD,cAArB9Q,EAAO8Q,YAAmD,SAArB9Q,EAAO8Q,YACzHhJ,EAAK3I,MAAQa,EAAO4Y,cAAc5Y,EAAO8Q,cAG1ChL,EAAOzI,OAAS,MAAQyK,EAAKgC,SAAS0J,SACxC1L,EAAKgC,SAAS0J,OAAS,SAEG,YAAtBxT,EAAO8Q,aACThJ,EAAKgC,SAAS7I,QAAU,WACA,eAAtBjB,EAAO8Q,aACThJ,EAAKgC,SAAS7I,QAAU,OAG5BjB,EAAO3B,QAAQygB,kBAAmB,GAIhC9e,EAAO3B,QAAQsY,2BAA4B,IACzC7O,EAAK3I,MAAQa,EAAO4Y,cAAc,oBAC/B9Q,EAAK3I,MAAQa,EAAO4Y,cAAc,6BACnC9S,EAAOzI,OAAS,MAClByK,EAAKgC,SAAS0J,OAAS1L,EAAKgC,SAAS0J,QAAU,UAEjDxT,EAAO3B,QAAQsY,yBAA0B,KAKhB,YAAxB7O,EAAKgC,SAAS0J,QAAwB1L,EAAKgC,SAASyN,SAAWvX,EAAO3B,QAAQsY,2BAA4B,EAAM,CACnH,GAAyB,WAArB3W,EAAO8Q,aAA4BpU,EAAS2iB,iBAAmBvX,EAAKhC,OAAO7K,MAAMyjB,GAEnF,MADA1e,GAAO3B,QAAQsY,wBAA0B3W,EAAO3B,QAAQsY,0BAA2B,EAC5E3W,EAAe,OAAE,mBAAmB4H,KAAK,WAC9C,MAAO9B,IAGX,IAAyB,SAArB9F,EAAO8Q,aAA0BpU,EAAS4iB,cAAgBxX,EAAKhC,OAAO7K,MAAM0jB,GAE9E,MADA3e,GAAO3B,QAAQsY,wBAA0B3W,EAAO3B,QAAQsY,0BAA2B,EAC5E3W,EAAe,OAAE,0BAA0B4H,KAAK,WACrD,MAAO9B,KAKb,MAAOA,UAgBf,IAAIyZ,IAA8B,mBAAR9iB,MAAsB,OAAS,QAEzDyC,GAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GAGd,MAFIA,GAAKgC,SAAS7I,UAAY6G,EAAKgC,SAAS0J,SAC1C1L,EAAKgC,SAAS0J,OAAS,UAClBxI,EAAMlM,KAAKxC,KAAMwL,MAQ5B5I,EAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACd,GAAI9H,GAAS1D,IAMb,IAJKwL,EAAKgC,SAAS0J,SACjB1L,EAAKgC,SAAS0J,OAAS,UAGG,UAAxB1L,EAAKgC,SAAS0J,SAAuB1L,EAAKgC,SAASqM,MAAO,CAE5D,GAAIA,GAAQlQ,GAEZ6B,GAAKgC,SAASqM,MAAQA,EAEtBA,EAAMxV,OAEN,KAAK,GAAI6e,KAAK1X,GAAKgC,SAAS2V,QAAS,CACnC,GAAIC,GAAK5X,EAAKgC,SAAS2V,QAAQD,EAC3BE,IACFvJ,EAAMxV,KAAKvE,KAAKsjB,GAGpBvJ,EAAM/P,QAAU,SAASnB,EAAShE,EAASyF,GAEzC,GAAI+Y,EACJ,IAAI3X,EAAKgC,SAAS2V,QAAS,CACzBA,IACA,KAAK,GAAID,KAAK1X,GAAKgC,SAAS2V,QACtB3X,EAAKgC,SAAS2V,QAAQD,KACxBC,EAAQD,GAAKva,EAAQ6C,EAAKgC,SAAS2V,QAAQD,KAGjD,GAAIG,GAAa7X,EAAKgC,SAAS7I,OAE3B0e,KACF7X,EAAKhC,QAAU,KAAOyZ,GAAe,KAAOI,EAAa,QAAUA,EAAa,IAElF,IAAIC,GAAiB5f,EAAOpB,IAAI,oBAAoBihB,cAAcnZ,EAAO8W,GAAImC,EAAYF,IAAW3X,EAAKgC,SAASgW,kBAGlH,OAFAjN,IAAO/T,KAAKkB,EAAQ8H,GAEb8X,KAGX,MAAO1U,GAAYpM,KAAKxC,KAAMwL,MAyBlC5I,EAAK,kBAAmB,SAAS6gB,GAC/B,MAAO,UAASjY,EAAMgN,GACpB,GAAIA,IAAchN,EAAKgC,SAAS7I,WAAauH,GAAoC,UAAxBV,EAAKgC,SAAS0J,QACrE,MAAOuM,GAAejhB,KAAKxC,KAAMwL,EAAMgN,EAEzChN,GAAKgC,SAAS0J,OAAS,QACvB,IAAI2C,GAAQrO,EAAKgC,SAASqM,MAAQlQ,GAClCkQ,GAAMxV,KAAOmH,EAAKgC,SAASnJ,IAC3B,IAAIkG,GAAcD,EAAekB,EAAKgC,SAAS7I,QAC/CkV,GAAM/P,QAAU,WACd,MAAOS,OAKbxH,EAAgB,SAASsO,GACvB,MAAO,YAYL,QAASqS,GAAcC,GACrB,GAAIte,OAAOue,KACTve,OAAOue,KAAKxjB,GAAU2Q,QAAQ4S,OAE9B,KAAK,GAAIT,KAAK9iB,GACP2D,EAAevB,KAAKpC,EAAU8iB,IAEnCS,EAAST,GAIf,QAASW,GAAmBF,GAC1BD,EAAc,SAASI,GACrB,GAAI7iB,EAAQuB,KAAKuhB,EAAoBD,KAAe,EAApD,CAEA,IACE,GAAI9e,GAAQ5E,EAAS0jB,GAEvB,MAAOnX,GACLoX,EAAmBjkB,KAAKgkB,GAE1BH,EAASG,EAAY9e,MAhCzB,GAAItB,GAAS1D,IACbqR,GAAY7O,KAAKkB,EAEjB,IAMIsgB,GANAjgB,EAAiBsB,OAAOvC,UAAUiB,eAGlCggB,GAAsB,KAAM,iBAAkB,eAAgB,gBAAiB,SAAU,eAAgB,WAC3G,wBAAyB,oBAAqB,kBAAmB,kBAAmB,kBA6BtFrgB,GAAOoE,IAAI,mBAAoBpE,EAAOsE,WACpCub,cAAe,SAAS1V,EAAYlJ,EAASwe,EAASc,GAEpD,GAAIC,GAAY9jB,EAASkR,MAEzBlR,GAASkR,OAAShS,MAGlB,IAAI6kB,EACJ,IAAIhB,EAAS,CACXgB,IACA,KAAK,GAAIjB,KAAKC,GACZgB,EAAWjB,GAAK9iB,EAAS8iB,GACzB9iB,EAAS8iB,GAAKC,EAAQD,GAc1B,MATKve,KACHqf,KAEAH,EAAmB,SAAShhB,EAAMmC,GAChCgf,EAAenhB,GAAQmC,KAKpB,WACL,GAEIof,GAFA7Z,EAAc5F,EAAU2F,EAAe3F,MAGvC0f,IAAoB1f,CA6BxB,IA3BKA,IAAWsf,GACdJ,EAAmB,SAAShhB,EAAMmC,GAC5Bgf,EAAenhB,KAAUmC,GAET,mBAATA,KAIPif,IACF7jB,EAASyC,GAAQvD,QAEdqF,IACH4F,EAAY1H,GAAQmC,EAEO,mBAAhBof,GACJC,GAAmBD,IAAiBpf,IACvCqf,GAAkB,GAGpBD,EAAepf,MAKvBuF,EAAc8Z,EAAkB9Z,EAAc6Z,EAG1CD,EACF,IAAK,GAAIjB,KAAKiB,GACZ/jB,EAAS8iB,GAAKiB,EAAWjB,EAI7B,OAFA9iB,GAASkR,OAAS4S,EAEX3Z,UASjB,WAaE,QAAS+Z,GAAW9a,GAUlB,QAAS+a,GAAWC,EAAW7lB,GAC7B,IAAK,GAAImC,GAAI,EAAGA,EAAI0jB,EAAUzjB,OAAQD,IACpC,GAAI0jB,EAAU1jB,GAAG,GAAKnC,EAAM8F,OAAS+f,EAAU1jB,GAAG,GAAKnC,EAAM8F,MAC3D,OAAO,CACX,QAAO,EAbTggB,EAAgBC,UAAYC,EAAaD,UAAYE,EAAYF,UAAY,CAE7E,IAEI/lB,GAFA0F,KAKAwgB,KAAsBC,IAS1B,IAAItb,EAAOzI,OAASyI,EAAO5I,MAAM,MAAMG,OAAS,IAAK,CACnD,KAAOpC,EAAQimB,EAAY/R,KAAKrJ,IAC9Bqb,EAAgB/kB,MAAMnB,EAAM8F,MAAO9F,EAAM8F,MAAQ9F,EAAM,GAAGoC,QAI5D,MAAOpC,EAAQgmB,EAAa9R,KAAKrJ,IAE1B+a,EAAWM,EAAiBlmB,IAC/BmmB,EAAiBhlB,MAAMnB,EAAM8F,MAAQ9F,EAAM,GAAGoC,OAAQpC,EAAM8F,MAAQ9F,EAAM,GAAGoC,OAAS,IAI5F,KAAOpC,EAAQ8lB,EAAgB5R,KAAKrJ,IAElC,IAAK+a,EAAWM,EAAiBlmB,KAAW4lB,EAAWO,EAAkBnmB,GAAQ,CAC/E,GAAI6R,GAAM7R,EAAM,GAAGyC,OAAO,EAAGzC,EAAM,GAAGoC,OAAS,EAE/C,IAAIyP,EAAI7R,MAAM,OACZ,QAEyB,MAAvB6R,EAAIA,EAAIzP,OAAS,KACnByP,EAAMA,EAAIpP,OAAO,EAAGoP,EAAIzP,OAAS,IACnCsD,EAAKvE,KAAK0Q,GAId,MAAOnM,GAtDT,GAAI0gB,GAAkB,8HAElBN,EAAkB,iHAClBE,EAAe,oDAEfC,EAAc,mEAGdI,EAAgB,SAiDpBpiB,GAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACd,GAAI9H,GAAS1D,IAQb,IAPKwL,EAAKgC,SAAS0J,SACjB6N,EAAgBL,UAAY,EAC5BD,EAAgBC,UAAY,GACxBD,EAAgB5R,KAAKrH,EAAKhC,SAAWub,EAAgBlS,KAAKrH,EAAKhC,WACjEgC,EAAKgC,SAAS0J,OAAS,QAGC,OAAxB1L,EAAKgC,SAAS0J,OAAiB,CACjC,GAAI+N,GAAWzZ,EAAKgC,SAASnJ,KACzBA,EAAOmH,EAAKgC,SAAS0X,uBAAwB,KAAaZ,EAAW9Y,EAAKhC,OAE9E,KAAK,GAAI0Z,KAAK1X,GAAKgC,SAAS2V,QACtB3X,EAAKgC,SAAS2V,QAAQD,IACxB7e,EAAKvE,KAAK0L,EAAKgC,SAAS2V,QAAQD,GAEpC,IAAIrJ,GAAQlQ,GAEZ6B,GAAKgC,SAASqM,MAAQA,EAEtBA,EAAMxV,KAAOA,EACbwV,EAAM9P,kBAAmB,EACzB8P,EAAM/P,QAAU,SAASqb,EAAUxgB,EAASyF,GAC1C,QAASzB,GAAQ9F,GAGf,MAF6B,KAAzBA,EAAKA,EAAK9B,OAAS,KACrB8B,EAAOA,EAAKzB,OAAO,EAAGyB,EAAK9B,OAAS,IAC/BokB,EAASlN,MAAMjY,KAAMkY,WAU9B,GARAvP,EAAQmD,QAAU,SAASjJ,GACzB,MAAOa,GAAOpB,IAAI,iBAAiB8iB,eAAeviB,EAAMuH,EAAO8W,KAGjE9W,EAAO3H,SACP2H,EAAOzB,QAAUwc,GAGZ3Z,EAAKgC,SAAS6X,oBACjB,IAAK,GAAIvkB,GAAI,EAAGA,EAAImkB,EAASlkB,OAAQD,IACnC6H,EAAQsc,EAASnkB,GAErB,IAAIwkB,GAAW5hB,EAAOpB,IAAI,iBAAiBijB,YAAYnb,EAAO8W,IAC1DsE,GACF7gB,QAASA,EACT2d,MAAO3Z,EAAShE,EAASyF,EAAQkb,EAASjQ,SAAUiQ,EAASG,QAASrlB,EAAUA,IAG9EslB,EAAa,2EAGjB,IAAIla,EAAKgC,SAAS2V,QAChB,IAAK,GAAID,KAAK1X,GAAKgC,SAAS2V,QAC1BqC,EAAalD,KAAKxiB,KAAK6I,EAAQ6C,EAAKgC,SAAS2V,QAAQD,KACrDwC,GAAc,KAAOxC,CAIzB,IAAI5R,GAASlR,EAASkR,MACtBlR,GAASkR,OAAShS,OAClBc,EAASolB,aAAeA,EAExBha,EAAKhC,OAASkc,EAAa,MAAQla,EAAKhC,OAAO9K,QAAQsmB,EAAe,IAAM,uDAE5EzO,GAAO/T,KAAKkB,EAAQ8H,GAEpBpL,EAASolB,aAAelmB,OACxBc,EAASkR,OAASA,GAItB,MAAO1C,GAAYpM,KAAKkB,EAAQ8H,SAItCzI,EAAgB,SAASsO,GACvB,MAAO,YAOL,QAASsU,GAAY3hB,GACnB,MAAyB,YAArBA,EAAK5C,OAAO,EAAG,GACV4C,EAAK5C,OAAO,IAAME,GAEvBskB,GAAgB5hB,EAAK5C,OAAO,EAAGwkB,EAAa7kB,SAAW6kB,EAClD5hB,EAAK5C,OAAOwkB,EAAa7kB,QAE3BiD,EAbT,GAAIN,GAAS1D,IAGb,IAFAqR,EAAY7O,KAAKkB,GAEI,mBAAVyI,SAA4C,mBAAZE,WAA2BF,OAAOa,SAC3E,GAAI4Y,GAAe5Y,SAASnO,SAAW,KAAOmO,SAAS/N,UAAY+N,SAAS9N,KAAO,IAAM8N,SAAS9N,KAAO,GAY3GwE,GAAOoE,IAAI,gBAAiBpE,EAAOsE,WACjCod,eAAgB,SAASlX,EAAS2X,GAChC,MAAOF,GAAYjiB,EAAO4Y,cAAcpO,EAAS2X,KAEnDN,YAAa,SAASO,GAEpB,GACIzQ,GADA0Q,EAAcD,EAASpmB,YAAY,IAGrC2V,GADE0Q,IAAe,EACND,EAAS1kB,OAAO,EAAG2kB,GAEnBD,CAEb,IAAIL,GAAUpQ,EAASzU,MAAM,IAI7B,OAHA6kB,GAAQ5lB,MACR4lB,EAAUA,EAAQ1lB,KAAK,MAGrBsV,SAAUsQ,EAAYtQ,GACtBoQ,QAASE,EAAYF,WAW/B7iB,EAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GAId,MAFIA,GAAKgC,SAAS+R,YAAcle,IAC9BjB,EAASkR,OAAStR,KAAKgmB,WAClBtX,EAAMlM,KAAKxC,KAAMwL,MAI5BzI,EAAgB,SAASsO,GACvB,MAAO,YAYL,QAASiT,GAAW9a,EAAQyc,GAG1Bzc,EAASA,EAAO9K,QAAQimB,EAAc,GAGtC,IAAIuB,GAAS1c,EAAO7K,MAAMwnB,GACtBC,GAAgBF,EAAO,GAAGtlB,MAAM,KAAKqlB,IAAiB,WAAWvnB,QAAQ2nB,EAAS,IAGlFC,EAAeC,EAAcH,KAAkBG,EAAcH,GAAgB,GAAIpJ,QAAOwJ,EAAgBJ,EAAeK,EAAgB,KAE3IH,GAAa5B,UAAY,CAKzB,KAHA,GAEI/lB,GAFA0F,KAGG1F,EAAQ2nB,EAAazT,KAAKrJ,IAC/BnF,EAAKvE,KAAKnB,EAAM,IAAMA,EAAM,GAE9B,OAAO0F,GAOT,QAASsE,GAAQrE,EAAOqf,EAAU+C,EAASC,GAEzC,GAAoB,gBAATriB,MAAuBA,YAAiBsB,QACjD,MAAO+C,GAAQsP,MAAM,KAAMrS,MAAM9C,UAAU6N,OAAOnO,KAAK0V,UAAW,EAAGA,UAAUnX,OAAS,GAK1F,IAFoB,gBAATuD,IAAwC,kBAAZqf,KACrCrf,GAASA,MACPA,YAAiBsB,QAWhB,CAAA,GAAoB,gBAATtB,GAAmB,CACjC,GAAIoW,GAAqBhX,EAAO2V,qBAA4D,OAArC/U,EAAMlD,OAAOkD,EAAMvD,OAAS,EAAG,GAClFia,EAAatX,EAAOiX,eAAerW,EAAOqiB,EAC1CjM,IAAqE,OAA/CM,EAAW5Z,OAAO4Z,EAAWja,OAAS,EAAG,KACjEia,EAAaA,EAAW5Z,OAAO,EAAG4Z,EAAWja,OAAS,GACxD,IAAIqJ,GAAS1G,EAAOpB,IAAI0Y,EACxB,KAAK5Q,EACH,KAAM,IAAI3I,OAAM,sCAAwC6C,EAAQ,QAAU0W,GAAc2L,EAAU,UAAYA,EAAU,KAAO,KACjI,OAAOvc,GAAOsK,aAAetK,EAAgB,QAAIA,EAIjD,KAAM,IAAI7L,WAAU,mBArBpB,IAAK,GADDqoB,MACK9lB,EAAI,EAAGA,EAAIwD,EAAMvD,OAAQD,IAChC8lB,EAAgB9mB,KAAK4D,EAAe,OAAEY,EAAMxD,GAAI6lB,GAClD9a,SAAQsD,IAAIyX,GAAiBtb,KAAK,SAASpJ,GACrCyhB,GACFA,EAAS1L,MAAM,KAAM/V,IACtBwkB,GAmBP,QAASpV,GAAOzO,EAAMwB,EAAMwiB,GAuC1B,QAAS/c,GAAQgd,EAAKniB,EAASyF,GAiB3B,QAAS2c,GAAkBziB,EAAOqf,EAAU+C,GAC1C,MAAoB,gBAATpiB,IAAwC,kBAAZqf,GAC9BmD,EAAIxiB,GACNqE,EAAQnG,KAAKkB,EAAQY,EAAOqf,EAAU+C,EAAStc,EAAO8W,IAlBjE,IAAK,GADD8F,MACKlmB,EAAI,EAAGA,EAAIuD,EAAKtD,OAAQD,IAC/BkmB,EAAUlnB,KAAKgnB,EAAIziB,EAAKvD,IAE1BsJ,GAAO6c,IAAM7c,EAAO8W,GAEpB9W,EAAO6P,OAAS,aAGZiN,IAAe,GACjBF,EAAUrW,OAAOuW,EAAa,EAAG9c,GAE/B+c,IAAgB,GAClBH,EAAUrW,OAAOwW,EAAc,EAAGxiB,GAEhCshB,IAAgB,IAMlBc,EAAkBK,MAAQ,SAASvkB,GAEjC,GAAI6X,GAAqBhX,EAAO2V,qBAA0D,OAAnCxW,EAAKzB,OAAOyB,EAAK9B,OAAS,EAAG,GAChF1C,EAAMqF,EAAOiX,eAAe9X,EAAMuH,EAAO8W,GAG7C,OAFIxG,IAAuD,OAAjCrc,EAAI+C,OAAO/C,EAAI0C,OAAS,EAAG,KACnD1C,EAAMA,EAAI+C,OAAO,EAAG/C,EAAI0C,OAAS,IAC5B1C,GAET2oB,EAAUrW,OAAOsV,EAAc,EAAGc,GAIpC,IAAIjI,GAAa1e,EAASuI,OAC1BvI,GAASuI,QAAUA,CAEnB,IAAIhJ,GAASknB,EAAQ5O,MAAMkP,IAAgB,EAAK/mB,EAAWuE,EAASqiB,EAOpE,IALA5mB,EAASuI,QAAUmW,EAEE,mBAAVnf,IAAyByK,IAClCzK,EAASyK,EAAOzF,SAEG,mBAAVhF,GACT,MAAOA,GAnFQ,gBAARkD,KACTgkB,EAAUxiB,EACVA,EAAOxB,EACPA,EAAO,MAEHwB,YAAgBuB,SACpBihB,EAAUxiB,EACVA,GAAQ,UAAW,UAAW,UAAUsM,OAAO,EAAGkW,EAAQ9lB,SAGtC,kBAAX8lB,KACTA,EAAU,SAAUA,GAClB,MAAO,YAAa,MAAOA,KAC1BA,IAGyBvnB,SAA1B+E,EAAKA,EAAKtD,OAAS,IACrBsD,EAAKxE,KAGP,IAAIomB,GAAckB,EAAcD,GAE3BjB,EAAehlB,EAAQuB,KAAK6B,EAAM,cAAe,IAEpDA,EAAKsM,OAAOsV,EAAc,GAIrBpjB,IACHwB,EAAOA,EAAKwB,OAAOye,EAAWuC,EAAQlmB,WAAYslB,OAGjDkB,EAAelmB,EAAQuB,KAAK6B,EAAM,cAAe,GACpDA,EAAKsM,OAAOwW,EAAc,IAEvBD,EAAcjmB,EAAQuB,KAAK6B,EAAM,aAAc,GAClDA,EAAKsM,OAAOuW,EAAa,EAkD3B,IAAIrN,GAAQlQ,GACZkQ,GAAMhX,KAAOA,IAASa,EAAOiX,gBAAkBjX,EAAO2H,WAAW7I,KAAKkB,EAAQb,GAC9EgX,EAAMxV,KAAOA,EACbwV,EAAM/P,QAAUA,EAEhBpG,EAAOke,eACLC,KAAK,EACLhI,MAAOA,IAtKX,GAAInW,GAAS1D,IACbqR,GAAY7O,KAAKxC,KAEjB,IAAI2kB,GAAe,2CACf6B,EAAgB,kCAChBC,EAAiB,6CACjBN,EAAiB,eACjBE,EAAU,aAEVE,IAgKJjV,GAAOuQ,OAGPjf,EAAK,kBAAmB,SAAS6gB,GAC/B,MAAO,UAASjY,EAAMgN,GAEpB,IAAKA,IAAaA,EAASqJ,IACzB,MAAO4B,GAAejhB,KAAKxC,KAAMwL,EAAMgN,EAEzC,IAAIsJ,GAAUtW,GAAQA,EAAKgC,SACvBqM,EAAQrB,EAASqB,KAErB,IAAIiI,EACF,GAAKA,EAAQ5K,QAA4B,UAAlB4K,EAAQ5K,QAE1B,IAAK2C,EAAMhX,MAA0B,OAAlBif,EAAQ5K,OAC9B,KAAM,IAAIzV,OAAM,qCAAuCqgB,EAAQ5K,OAAS,WAAa1L,EAAK3I,UAF1Fif,GAAQ5K,OAAS,KAMrB,IAAK2C,EAAMhX,KAkBLif,IACGA,EAAQjI,OAAUiI,EAAQ7G,OAEtB6G,EAAQjI,OAASiI,EAAQjI,MAAMhX,MAAQif,EAAQjI,MAAMhX,MAAQ2I,EAAK3I,OACzEif,EAAQjI,MAAQva,QAFhBwiB,EAAQjI,MAAQA,EAKlBiI,EAAQ7G,QAAS,GAIbpB,EAAMhX,OAAQ7C,MAAKmgB,UACvBngB,KAAKmgB,QAAQtG,EAAMhX,MAAQgX,OA9Bd,CACf,IAAKiI,EACH,KAAM,IAAIvjB,WAAU,mCAEtB,IAAIujB,EAAQjI,QAAUiI,EAAQjI,MAAMhX,KAClC,KAAM,IAAIpB,OAAM,wCAA0C+J,EAAK3I,KAEjEif,GAAQjI,MAAQA,MA4BtBnW,EAAOsiB,UAAY1U,EACnB5N,EAAO2jB,WAAa1e,KAKxB,WAIE,GAAI2e,GAAW,yRAEf1kB,GAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACd,GAAI9H,GAAS1D,IAEb,IAA4B,OAAxBwL,EAAKgC,SAAS0J,SAAoB1L,EAAKgC,SAAS0J,QAAU1L,EAAKhC,OAAO7K,MAAM2oB,GAG9E,GAFA9b,EAAKgC,SAAS0J,OAAS,MAElBxT,EAAOqF,SAAWrF,EAAOoG,WAAY,EAexC0B,EAAKgC,SAAS1D,QAAU,WACtB,MAAO0B,GAAKgC,SAAS+Z,eAAetP,MAAMjY,KAAMkY,gBAhBH,CAC/C,GAAIgM,GAAY9jB,EAASkR,MACzBlR,GAASkR,OAAStR,KAAKgmB,SAEvB,KACEzP,GAAO/T,KAAKkB,EAAQ8H,GAEtB,QACEpL,EAASkR,OAAS4S,EAGpB,IAAK1Y,EAAKgC,SAASqM,QAAUrO,EAAKgC,SAASyN,OACzC,KAAM,IAAI1c,WAAU,cAAgBiN,EAAK3I,KAAO,mBAStD,MAAO+L,GAAYpM,KAAKkB,EAAQ8H,SActC,WACE,QAASgc,GAAc9jB,EAAQkF,GAE7B,GAAIA,EAAY,CACd,GAAI6e,EACJ,IAAI/jB,EAAO4V,aACT,IAAKmO,EAAoB7e,EAAWlJ,YAAY,QAAS,EACvD,MAAOkJ,GAAWxH,OAAOqmB,EAAoB,OAG/C,KAAKA,EAAoB7e,EAAW3H,QAAQ,QAAS,EACnD,MAAO2H,GAAWxH,OAAO,EAAGqmB,EAGhC,OAAO7e,IAIX,QAAS8e,GAAYhkB,EAAQb,GAC3B,GAAI8kB,GACAC,EAEA7B,EAAcljB,EAAKnD,YAAY,IAEnC,IAAIqmB,IAAe,EAYnB,MATIriB,GAAO4V,aACTqO,EAAe9kB,EAAKzB,OAAO2kB,EAAc,GACzC6B,EAAa/kB,EAAKzB,OAAO,EAAG2kB,KAG5B4B,EAAe9kB,EAAKzB,OAAO,EAAG2kB,GAC9B6B,EAAa/kB,EAAKzB,OAAO2kB,EAAc,IAAM4B,EAAavmB,OAAOumB,EAAajoB,YAAY,KAAO,KAIjGmoB,SAAUF,EACVG,OAAQF,GAKZ,QAASG,GAAmBrkB,EAAQikB,EAAcC,EAAYjM,GAI5D,MAHIA,IAAuE,OAAnDgM,EAAavmB,OAAOumB,EAAa5mB,OAAS,EAAG,KACnE4mB,EAAeA,EAAavmB,OAAO,EAAGumB,EAAa5mB,OAAS,IAE1D2C,EAAO4V,YACFsO,EAAa,IAAMD,EAGnBA,EAAe,IAAMC,EAOhC,QAASI,GAAsBtkB,EAAQukB,GACrC,MAAOvkB,GAAO2V,qBAAwD,OAAjC4O,EAAI7mB,OAAO6mB,EAAIlnB,OAAS,EAAG,GAGlE,QAASmnB,GAAoB5L,GAC3B,MAAO,UAASzZ,EAAM+F,EAAYoV,GAChC,GAAIta,GAAS1D,KAETmoB,EAAST,EAAYhkB,EAAQb,EAGjC,IAFA+F,EAAa4e,EAAcxnB,KAAM4I,IAE5Buf,EACH,MAAO7L,GAAc9Z,KAAKxC,KAAM6C,EAAM+F,EAAYoV,EAGpD,IAAI2J,GAAejkB,EAAO4Y,cAAc6L,EAAON,SAAUjf,GAAY,GACjEgf,EAAalkB,EAAO4Y,cAAc6L,EAAOL,OAAQlf,GAAY,EACjE,OAAOmf,GAAmBrkB,EAAQikB,EAAcC,EAAYI,EAAsBtkB,EAAQykB,EAAON,YAIrGjlB,EAAK,iBAAkBslB,GACvBtlB,EAAK,gBAAiBslB,GAEtBtlB,EAAK,YAAa,SAASyI,GACzB,MAAO,UAASxI,EAAM+F,EAAYoV,GAChC,GAAIta,GAAS1D,IAEb4I,GAAa4e,EAAcxnB,KAAM4I,EAEjC,IAAIuf,GAAST,EAAYhkB,EAAQb,EAEjC,OAAKslB,GAGEtc,QAAQsD,KACbzL,EAAO2H,UAAU8c,EAAON,SAAUjf,GAAY,GAC9ClF,EAAO2H,UAAU8c,EAAOL,OAAQlf,GAAY,KAE7C0C,KAAK,SAAS0P,GACb,MAAO+M,GAAmBrkB,EAAQsX,EAAW,GAAIA,EAAW,GAAIgN,EAAsBtkB,EAAQykB,EAAON,aAP9Fxc,EAAU7I,KAAKkB,EAAQb,EAAM+F,EAAYoV,MAYtDpb,EAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,GAKI4c,GALA1kB,EAAS1D,KAET6C,EAAO2I,EAAK3I,IAiBhB,OAbIa,GAAO4V,aACJ8O,EAAoBvlB,EAAK5B,QAAQ,QAAS,IAC7CuK,EAAKgC,SAAS9J,OAASb,EAAKzB,OAAO,EAAGgnB,GACtC5c,EAAK3I,KAAOA,EAAKzB,OAAOgnB,EAAoB,KAIzCA,EAAoBvlB,EAAKnD,YAAY,QAAS,IACjD8L,EAAKgC,SAAS9J,OAASb,EAAKzB,OAAOgnB,EAAoB,GACvD5c,EAAK3I,KAAOA,EAAKzB,OAAO,EAAGgnB,IAIxB5Z,EAAOhM,KAAKkB,EAAQ8H,GAC1BF,KAAK,SAASsC,GACb,MAAIwa,KAAqB,GAAO5c,EAAKgC,SAAS9J,QAKtCA,EAAO+Q,cAAgB/Q,GAAQ2H,UAAUG,EAAKgC,SAAS9J,OAAQ8H,EAAK3I,MAC3EyI,KAAK,SAAS+c,GAEb,MADA7c,GAAKgC,SAAS9J,OAAS2kB,EAChBza,IAPAA,IAUVtC,KAAK,SAASsC,GACb,GAAIka,GAAStc,EAAKgC,SAAS9J,MAE3B,KAAKokB,EACH,MAAOla,EAGT,IAAIpC,EAAK3I,MAAQilB,EACf,KAAM,IAAIrmB,OAAM,UAAYqmB,EAAS,sHAGvC,IAAIpkB,EAAOyc,SAAWzc,EAAOyc,QAAQtd,GACnC,MAAO+K,EAET,IAAI6G,GAAe/Q,EAAO+Q,cAAgB/Q,CAG1C,OAAO+Q,GAAqB,OAAEqT,GAC7Bxc,KAAK,SAASoX,GAKb,MAHAlX,GAAKgC,SAASkV,aAAeA,EAE7BlX,EAAKoC,QAAUA,EACX8U,EAAalU,OACRkU,EAAalU,OAAOhM,KAAKkB,EAAQ8H,GAEnCoC,SAMfhL,EAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GACd,GAAI9H,GAAS1D,IACb,OAAIwL,GAAKgC,SAASkV,cAAgBlX,EAAKgC,SAASkV,aAAahU,OAAiC,WAAxBlD,EAAKgC,SAAS0J,QAClF1L,EAAKgC,SAAS+R,YAAa,EACpB/T,EAAKgC,SAASkV,aAAahU,MAAMlM,KAAKkB,EAAQ8H,EAAM,SAASA,GAClE,MAAOkD,GAAMlM,KAAKkB,EAAQ8H,MAIrBkD,EAAMlM,KAAKkB,EAAQ8H,MAKhC5I,EAAK,YAAa,SAAS+L,GACzB,MAAO,UAASnD,GACd,GAAI9H,GAAS1D,KACTsiB,EAAOpK,SACX,OAAI1M,GAAKgC,SAASkV,cAAgBlX,EAAKgC,SAASkV,aAAa/T,WAAqC,WAAxBnD,EAAKgC,SAAS0J,OAC/ErL,QAAQC,QAAQN,EAAKgC,SAASkV,aAAa/T,UAAUsJ,MAAMvU,EAAQ4e,IAAOhX,KAAK,SAASgd,GAC7F,GAAI/S,GAAY/J,EAAKgC,SAAS+H,SAG9B,IAAIA,EAAW,CACb,GAAwB,gBAAbA,GACT,KAAM,IAAI9T,OAAM,oDAElB,IAAIkhB,GAAenX,EAAKoC,QAAQhN,MAAM,KAAK,EAGtC2U,GAAUqN,MAAQrN,EAAUqN,MAAQpX,EAAKoC,UAC5C2H,EAAUqN,KAAOD,EAAe,iBAG7BpN,EAAUsN,SAAWtN,EAAUsN,QAAQ9hB,QAAU,KAAOwU,EAAUsN,QAAQ,IAAMtN,EAAUsN,QAAQ,IAAMrX,EAAKoC,YAChH2H,EAAUsN,SAAWF,IAWzB,MALqB,gBAAV2F,GACT9c,EAAKhC,OAAS8e,EAEd7hB,EAAKjE,KAAKxC,KAAM,UAAYwL,EAAKgC,SAAS9J,OAAS,qHAE9CiL,EAAUsJ,MAAMvU,EAAQ4e,KAI1B3T,EAAUsJ,MAAMvU,EAAQ4e,MAKrC1f,EAAK,cAAe,SAASgM,GAC3B,MAAO,UAASpD,GACd,GAAI9H,GAAS1D,KACTuoB,GAAoB,CAExB,OAAI/c,GAAKgC,SAASkV,cAAgBlX,EAAKgC,SAASkV,aAAa9T,cAAgBlL,EAAOqF,SAAmC,WAAxByC,EAAKgC,SAAS0J,OACpGrL,QAAQC,QAAQN,EAAKgC,SAASkV,aAAa9T,YAAYpM,KAAKkB,EAAQ8H,EAAM,SAASA,GACxF,GAAI+c,EACF,KAAM,IAAI9mB,OAAM,wCAElB,OADA8mB,IAAoB,EACb3Z,EAAYpM,KAAKkB,EAAQ8H,MAC9BF,KAAK,SAASgd,GAChB,MAAIC,GACKD,GAET9c,EAAKgC,SAASqM,MAAQlQ,IACtB6B,EAAKgC,SAASqM,MAAM/P,QAAU,WAC5B,MAAOwe,IAET9c,EAAKgC,SAASqM,MAAMxV,KAAOmH,EAAKgC,SAASnJ,KACzCmH,EAAKgC,SAAS0J,OAAS,UAChBtI,EAAYpM,KAAKkB,EAAQ8H,MAG3BoD,EAAYpM,KAAKkB,EAAQ8H,QA4CtC,IAAIT,KAAiB,UAAW,OAAQ,MAAO,QAAS,aAAc,WAuDlEa,GAAqB,aAsDzBhJ,GAAK,YAAa,SAASyI,GACzB,MAAO,UAASxI,EAAM+F,EAAY4Q,GAChC,GAAI9V,GAAS1D,IACb,OAAOgM,GAAmBxJ,KAAKkB,EAAQb,EAAM+F,GAC5C0C,KAAK,SAASzI,GACb,MAAOwI,GAAU7I,KAAKkB,EAAQb,EAAM+F,EAAY4Q,KAEjDlO,KAAK,SAAS0P,GACb,MAAOtP,GAAuBlJ,KAAKkB,EAAQsX,EAAYpS,QAY/D,WAEEhG,EAAK,QAAS,SAAS8L,GACrB,MAAO,UAASlD,GACd,GAAIgd,GAAQhd,EAAKgC,SAASgb,MACtBC,EAAYjd,EAAKgC,SAASnJ,QAC9B,IAAImkB,EAAO,CACThd,EAAKgC,SAAS0J,OAAS,SACvB,IAAI2C,GAAQlQ,GAeZ,OAdA3J,MAAKmgB,QAAQ3U,EAAK3I,MAAQgX,EAC1BA,EAAM7P,aAAc,EACpB6P,EAAMxV,KAAOokB,EAAU5iB,QAAQ2iB,IAC/B3O,EAAMhQ,QAAU,SAAS6e,GACvB,OACEzH,SAAU,SAAS7W,GACjB,IAAK,GAAIxK,KAAKwK,GACZse,EAAQ9oB,EAAGwK,EAAOxK,GAChBwK,GAAOsK,eACTmF,EAAMzP,OAAOzF,QAAQ+P,cAAe,KAExC5K,QAAS,eAGN,GAGT,MAAO4E,GAAMlM,KAAKxC,KAAMwL,SA8C9B,WA8CE,QAASmd,GAAgBzS,EAAQtW,EAAGoF,GAGlC,IAFA,GACI4jB,GADAxhB,EAASxH,EAAEgB,MAAM,KAEdwG,EAAOrG,OAAS,GACrB6nB,EAAUxhB,EAAOC,QACjB6O,EAASA,EAAO0S,GAAW1S,EAAO0S,MAEpCA,GAAUxhB,EAAOC,QACXuhB,IAAW1S,KACfA,EAAO0S,GAAW5jB,GArDtBjC,EAAgB,SAASsO,GACvB,MAAO,YACLrR,KAAKqG,QACLgL,EAAY7O,KAAKxC,SAIrB4C,EAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,GAQIoS,GARAvX,EAAOrG,KAAKqG,KACZxD,EAAO2I,EAAK3I,KAMZ2b,EAAY,CAEhB,KAAK,GAAIpU,KAAU/D,GAEjB,GADAuX,EAAgBxT,EAAOnJ,QAAQ,KAC3B2c,KAAkB,GAElBxT,EAAOhJ,OAAO,EAAGwc,KAAmB/a,EAAKzB,OAAO,EAAGwc,IAChDxT,EAAOhJ,OAAOwc,EAAgB,KAAO/a,EAAKzB,OAAOyB,EAAK9B,OAASqJ,EAAOrJ,OAAS6c,EAAgB,GAAI,CACxG,GAAIiL,GAAQze,EAAOxJ,MAAM,KAAKG,MAC1B8nB,GAAQrK,IACVA,EAAYqK,GACdnjB,EAAW8F,EAAKgC,SAAUnH,EAAK+D,GAASoU,GAAaqK,GAQzD,MAHIxiB,GAAKxD,IACP6C,EAAW8F,EAAKgC,SAAUnH,EAAKxD,IAE1B2L,EAAOhM,KAAKxC,KAAMwL,KAM7B,IAAIsd,GAAY,uFACZC,EAAgB,uEAcpBnmB,GAAK,YAAa,SAAS+L,GACzB,MAAO,UAASnD,GAEd,GAA4B,WAAxBA,EAAKgC,SAAS0J,OAEhB,MADA1L,GAAKgC,SAASnJ,KAAOmH,EAAKgC,SAASnJ,SAC5BwH,QAAQC,QAAQN,EAAKhC,OAI9B,IAAInD,GAAOmF,EAAKhC,OAAO7K,MAAMmqB,EAC7B,IAAIziB,EAGF,IAAK,GAFD2iB,GAAY3iB,EAAK,GAAG1H,MAAMoqB,GAErBjoB,EAAI,EAAGA,EAAIkoB,EAAUjoB,OAAQD,IAAK,CACzC,GAAI8nB,GAAUI,EAAUloB,GACpBugB,EAAMuH,EAAQ7nB,OAEdkoB,EAAYL,EAAQxnB,OAAO,EAAG,EAIlC,IAHkC,KAA9BwnB,EAAQxnB,OAAOigB,EAAM,EAAG,IAC1BA,IAEe,KAAb4H,GAAiC,KAAbA,EAAxB,CAGA,GAAIC,GAAaN,EAAQxnB,OAAO,EAAGwnB,EAAQ7nB,OAAS,GAChDooB,EAAWD,EAAW9nB,OAAO,EAAG8nB,EAAWjoB,QAAQ,KAEvD,IAAIkoB,EAAU,CACZ,GAAIC,GAAYF,EAAW9nB,OAAO+nB,EAASpoB,OAAS,EAAGmoB,EAAWnoB,OAASooB,EAASpoB,OAAS,EAE9C,OAA3CooB,EAAS/nB,OAAO+nB,EAASpoB,OAAS,EAAG,IACvCooB,EAAWA,EAAS/nB,OAAO,EAAG+nB,EAASpoB,OAAS,GAChDyK,EAAKgC,SAAS2b,GAAY3d,EAAKgC,SAAS2b,OACxC3d,EAAKgC,SAAS2b,GAAUrpB,KAAKspB,IAEtB5d,EAAKgC,SAAS2b,YAAqBvjB,QAE1Ca,EAAKjE,KAAKxC,KAAM,UAAYwL,EAAK3I,KAAO,8BAAgCumB,EAAY,qDAAuDA,EAAY,gCACvJ5d,EAAKgC,SAAS2b,GAAUrpB,KAAKspB,IAG7BT,EAAgBnd,EAAKgC,SAAU2b,EAAUC,OAI3C5d,GAAKgC,SAAS0b,IAAc,GAKlC,MAAOva,GAAUsJ,MAAMjY,KAAMkY,iBAmBnC,WAMEnV,EAAgB,SAASsO,GACvB,MAAO,YACLA,EAAY7O,KAAKxC,MACjBA,KAAKsa,WACLta,KAAK+B,QAAQsnB,oBAKjBzmB,EAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,GAAI9H,GAAS1D,KACTspB,GAAU,CAEd,MAAM9d,EAAK3I,OAAQa,GAAOyc,SACxB,IAAK,GAAI3a,KAAK9B,GAAO4W,QAAS,CAC5B,IAAK,GAAIxZ,GAAI,EAAGA,EAAI4C,EAAO4W,QAAQ9U,GAAGzE,OAAQD,IAAK,CACjD,GAAIyoB,GAAY7lB,EAAO4W,QAAQ9U,GAAG1E,EAElC,IAAIyoB,GAAa/d,EAAK3I,KAAM,CAC1BymB,GAAU,CACV,OAIF,GAAIC,EAAUtoB,QAAQ,OAAQ,EAAI,CAChC,GAAIuoB,GAAQD,EAAU3oB,MAAM,IAC5B,IAAoB,GAAhB4oB,EAAMzoB,OAAa,CACrB2C,EAAO4W,QAAQ9U,GAAGmL,OAAO7P,IAAK,EAC9B,UAGF,GAAI0K,EAAK3I,KAAK4mB,UAAU,EAAGD,EAAM,GAAGzoB,SAAWyoB,EAAM,IACjDhe,EAAK3I,KAAKzB,OAAOoK,EAAK3I,KAAK9B,OAASyoB,EAAM,GAAGzoB,OAAQyoB,EAAM,GAAGzoB,SAAWyoB,EAAM,IAC/Ehe,EAAK3I,KAAKzB,OAAOooB,EAAM,GAAGzoB,OAAQyK,EAAK3I,KAAK9B,OAASyoB,EAAM,GAAGzoB,OAASyoB,EAAM,GAAGzoB,QAAQE,QAAQ,OAAQ,EAAI,CAC9GqoB,GAAU,CACV,SAKN,GAAIA,EACF,MAAO5lB,GAAe,OAAE8B,GACvB8F,KAAK,WACJ,MAAOkD,GAAOhM,KAAKkB,EAAQ8H,KAInC,MAAOgD,GAAOhM,KAAKkB,EAAQ8H,SA0BjC,WACEzI,EAAgB,SAASsO,GACvB,MAAO,YACLA,EAAY7O,KAAKxC,MACjBA,KAAKsG,eAIT1D,EAAK,SAAU,SAAS4L,GACtB,MAAO,UAAShD,GACd,GAAI9H,GAAS1D,KAETqE,EAAOX,EAAO4C,SAASkF,EAAK3I,KAChC,IAAIwB,EACF,IAAK,GAAIvD,GAAI,EAAGA,EAAIuD,EAAKtD,OAAQD,IAC/B4C,EAAe,OAAEW,EAAKvD,GAAI0K,EAAK3I,KAEnC,OAAO2L,GAAOhM,KAAKkB,EAAQ8H,SAKjC0G,EAAS,GAAI3P,GAEbnC,EAASqX,SAAWvF,EACpBA,EAAOwX,QAAU,mBACM,gBAAVtf,SAAsBA,OAAOzF,SAA6B,gBAAXA,WACxDyF,OAAOzF,QAAUuN,GAEnB9R,EAAS8R,OAASA,GAEF,mBAAR/R,MAAsBA,KAAOhC,QAGvC,GAAIwrB,GAAgC,mBAAZ9d,QAGxB,IAAwB,mBAAbQ,UAA0B,CACnC,GAAI0M,GAAU1M,SAASS,qBAAqB,SAI5C,IAHA9L,aAAe+X,EAAQA,EAAQhY,OAAS,GACpCsL,SAASud,gBAAkB5oB,aAAa6oB,OAAS7oB,aAAa6e,SAChE7e,aAAeqL,SAASud,eACtBD,EAAY,CACd,GAAIG,GAAU9oB,aAAaE,IACvB6oB,EAAWD,EAAQ1oB,OAAO,EAAG0oB,EAAQpqB,YAAY,KAAO,EAC5DyM,QAAO6d,kBAAoB9rB,EAC3BmO,SAAS4d,MACP,uCAA8CF,EAAW,sCAI3D7rB,SAIC,IAA6B,mBAAlBkO,eAA+B,CAC7C,GAAI2d,GAAW,EACf,KACE,KAAM,IAAItoB,OAAM,KAChB,MAAOkL,GACPA,EAAElM,MAAM/B,QAAQ,iCAAkC,SAASF,EAAGH,GAC5D2C,cAAiBE,IAAK7C,GACtB0rB,EAAW1rB,EAAIK,QAAQ,YAAa,OAGpCirB,GACFvd,cAAc2d,EAAW,uBAC3B7rB,QAGA8C,cAAoC,mBAAdkpB,aAA8BhpB,IAAKgpB,YAAe,KACxEhsB"} \ No newline at end of file diff --git a/node_modules/systemjs/dist/system.src.js b/node_modules/systemjs/dist/system.src.js new file mode 100644 index 0000000..3734388 --- /dev/null +++ b/node_modules/systemjs/dist/system.src.js @@ -0,0 +1,5153 @@ +/* + * SystemJS v0.19.39 + */ +(function() { +function bootstrap() {// from https://gist.github.com/Yaffle/1088850 +(function(global) { +function URLPolyfill(url, baseURL) { + if (typeof url != 'string') + throw new TypeError('URL must be a string'); + var m = String(url).replace(/^\s+|\s+$/g, "").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); + if (!m) + throw new RangeError('Invalid URL format'); + var protocol = m[1] || ""; + var username = m[2] || ""; + var password = m[3] || ""; + var host = m[4] || ""; + var hostname = m[5] || ""; + var port = m[6] || ""; + var pathname = m[7] || ""; + var search = m[8] || ""; + var hash = m[9] || ""; + if (baseURL !== undefined) { + var base = baseURL instanceof URLPolyfill ? baseURL : new URLPolyfill(baseURL); + var flag = !protocol && !host && !username; + if (flag && !pathname && !search) + search = base.search; + if (flag && pathname[0] !== "/") + pathname = (pathname ? (((base.host || base.username) && !base.pathname ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + pathname) : base.pathname); + // dot segments removal + var output = []; + pathname.replace(/^(\.\.?(\/|$))+/, "") + .replace(/\/(\.(\/|$))+/g, "/") + .replace(/\/\.\.$/, "/../") + .replace(/\/?[^\/]*/g, function (p) { + if (p === "/..") + output.pop(); + else + output.push(p); + }); + pathname = output.join("").replace(/^\//, pathname[0] === "/" ? "/" : ""); + if (flag) { + port = base.port; + hostname = base.hostname; + host = base.host; + password = base.password; + username = base.username; + } + if (!protocol) + protocol = base.protocol; + } + + // convert URLs to use / always + pathname = pathname.replace(/\\/g, '/'); + + this.origin = host ? protocol + (protocol !== "" || host !== "" ? "//" : "") + host : ""; + this.href = protocol + (protocol && host || protocol == "file:" ? "//" : "") + (username !== "" ? username + (password !== "" ? ":" + password : "") + "@" : "") + host + pathname + search + hash; + this.protocol = protocol; + this.username = username; + this.password = password; + this.host = host; + this.hostname = hostname; + this.port = port; + this.pathname = pathname; + this.search = search; + this.hash = hash; +} +global.URLPolyfill = URLPolyfill; +})(typeof self != 'undefined' ? self : global);(function(__global) { + + var isWorker = typeof window == 'undefined' && typeof self != 'undefined' && typeof importScripts != 'undefined'; + var isBrowser = typeof window != 'undefined' && typeof document != 'undefined'; + var isWindows = typeof process != 'undefined' && typeof process.platform != 'undefined' && !!process.platform.match(/^win/); + + if (!__global.console) + __global.console = { assert: function() {} }; + + // IE8 support + var indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, thisLen = this.length; i < thisLen; i++) { + if (this[i] === item) { + return i; + } + } + return -1; + }; + + var defineProperty; + (function () { + try { + if (!!Object.defineProperty({}, 'a', {})) + defineProperty = Object.defineProperty; + } + catch (e) { + defineProperty = function(obj, prop, opt) { + try { + obj[prop] = opt.value || opt.get.call(obj); + } + catch(e) {} + } + } + })(); + + var errArgs = new Error(0, '_').fileName == '_'; + + function addToError(err, msg) { + // parse the stack removing loader code lines for simplification + if (!err.originalErr) { + var stack = ((err.message || err) + (err.stack ? '\n' + err.stack : '')).toString().split('\n'); + var newStack = []; + for (var i = 0; i < stack.length; i++) { + if (typeof $__curScript == 'undefined' || stack[i].indexOf($__curScript.src) == -1) + newStack.push(stack[i]); + } + } + + var newMsg = '(SystemJS) ' + (newStack ? newStack.join('\n\t') : err.message.substr(11)) + '\n\t' + msg; + + // Convert file:/// URLs to paths in Node + if (!isBrowser) + newMsg = newMsg.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, ''); + + var newErr = errArgs ? new Error(newMsg, err.fileName, err.lineNumber) : new Error(newMsg); + + newErr.stack = newMsg; + + // track the original error + newErr.originalErr = err.originalErr || err; + + return newErr; + } + + function __eval(source, debugName, context) { + try { + new Function(source).call(context); + } + catch(e) { + throw addToError(e, 'Evaluating ' + debugName); + } + } + + var baseURI; + + // environent baseURI detection + if (typeof document != 'undefined' && document.getElementsByTagName) { + baseURI = document.baseURI; + + if (!baseURI) { + var bases = document.getElementsByTagName('base'); + baseURI = bases[0] && bases[0].href || window.location.href; + } + } + else if (typeof location != 'undefined') { + baseURI = __global.location.href; + } + + // sanitize out the hash and querystring + if (baseURI) { + baseURI = baseURI.split('#')[0].split('?')[0]; + baseURI = baseURI.substr(0, baseURI.lastIndexOf('/') + 1); + } + else if (typeof process != 'undefined' && process.cwd) { + baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd() + '/'; + if (isWindows) + baseURI = baseURI.replace(/\\/g, '/'); + } + else { + throw new TypeError('No environment baseURI'); + } + + try { + var nativeURL = new __global.URL('test:///').protocol == 'test:'; + } + catch(e) {} + + var URL = nativeURL ? __global.URL : __global.URLPolyfill; + +/* +********************************************************************************************* + + Dynamic Module Loader Polyfill + + - Implemented exactly to the former 2014-08-24 ES6 Specification Draft Rev 27, Section 15 + http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27 + + - Functions are commented with their spec numbers, with spec differences commented. + + - Spec bugs are commented in this code with links. + + - Abstract functions have been combined where possible, and their associated functions + commented. + + - Realm implementation is entirely omitted. + +********************************************************************************************* +*/ + +function Module() {} +// http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag +defineProperty(Module.prototype, 'toString', { + value: function() { + return 'Module'; + } +}); +function Loader(options) { + this._loader = { + loaderObj: this, + loads: [], + modules: {}, + importPromises: {}, + moduleRecords: {} + }; + + // 26.3.3.6 + defineProperty(this, 'global', { + get: function() { + return __global; + } + }); + + // 26.3.3.13 realm not implemented +} + +(function() { + +// Some Helpers + +// logs a linkset snapshot for debugging +/* function snapshot(loader) { + console.log('---Snapshot---'); + for (var i = 0; i < loader.loads.length; i++) { + var load = loader.loads[i]; + var linkSetLog = ' ' + load.name + ' (' + load.status + '): '; + + for (var j = 0; j < load.linkSets.length; j++) { + linkSetLog += '{' + logloads(load.linkSets[j].loads) + '} '; + } + console.log(linkSetLog); + } + console.log(''); +} +function logloads(loads) { + var log = ''; + for (var k = 0; k < loads.length; k++) + log += loads[k].name + (k != loads.length - 1 ? ' ' : ''); + return log; +} */ + + +/* function checkInvariants() { + // see https://bugs.ecmascript.org/show_bug.cgi?id=2603#c1 + + var loads = System._loader.loads; + var linkSets = []; + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + console.assert(load.status == 'loading' || load.status == 'loaded', 'Each load is loading or loaded'); + + for (var j = 0; j < load.linkSets.length; j++) { + var linkSet = load.linkSets[j]; + + for (var k = 0; k < linkSet.loads.length; k++) + console.assert(loads.indexOf(linkSet.loads[k]) != -1, 'linkSet loads are a subset of loader loads'); + + if (linkSets.indexOf(linkSet) == -1) + linkSets.push(linkSet); + } + } + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + for (var j = 0; j < linkSets.length; j++) { + var linkSet = linkSets[j]; + + if (linkSet.loads.indexOf(load) != -1) + console.assert(load.linkSets.indexOf(linkSet) != -1, 'linkSet contains load -> load contains linkSet'); + + if (load.linkSets.indexOf(linkSet) != -1) + console.assert(linkSet.loads.indexOf(load) != -1, 'load contains linkSet -> linkSet contains load'); + } + } + + for (var i = 0; i < linkSets.length; i++) { + var linkSet = linkSets[i]; + for (var j = 0; j < linkSet.loads.length; j++) { + var load = linkSet.loads[j]; + + for (var k = 0; k < load.dependencies.length; k++) { + var depName = load.dependencies[k].value; + var depLoad; + for (var l = 0; l < loads.length; l++) { + if (loads[l].name != depName) + continue; + depLoad = loads[l]; + break; + } + + // loading records are allowed not to have their dependencies yet + // if (load.status != 'loading') + // console.assert(depLoad, 'depLoad found'); + + // console.assert(linkSet.loads.indexOf(depLoad) != -1, 'linkset contains all dependencies'); + } + } + } +} */ + + // 15.2.3 - Runtime Semantics: Loader State + + // 15.2.3.11 + function createLoaderLoad(object) { + return { + // modules is an object for ES5 implementation + modules: {}, + loads: [], + loaderObj: object + }; + } + + // 15.2.3.2 Load Records and LoadRequest Objects + + var anonCnt = 0; + + // 15.2.3.2.1 + function createLoad(name) { + return { + status: 'loading', + name: name || '', + linkSets: [], + dependencies: [], + metadata: {} + }; + } + + // 15.2.3.2.2 createLoadRequestObject, absorbed into calling functions + + // 15.2.4 + + // 15.2.4.1 + function loadModule(loader, name, options) { + return new Promise(asyncStartLoadPartwayThrough({ + step: options.address ? 'fetch' : 'locate', + loader: loader, + moduleName: name, + // allow metadata for import https://bugs.ecmascript.org/show_bug.cgi?id=3091 + moduleMetadata: options && options.metadata || {}, + moduleSource: options.source, + moduleAddress: options.address + })); + } + + // 15.2.4.2 + function requestLoad(loader, request, refererName, refererAddress) { + // 15.2.4.2.1 CallNormalize + return new Promise(function(resolve, reject) { + resolve(loader.loaderObj.normalize(request, refererName, refererAddress)); + }) + // 15.2.4.2.2 GetOrCreateLoad + .then(function(name) { + var load; + if (loader.modules[name]) { + load = createLoad(name); + load.status = 'linked'; + // https://bugs.ecmascript.org/show_bug.cgi?id=2795 + load.module = loader.modules[name]; + return load; + } + + for (var i = 0, l = loader.loads.length; i < l; i++) { + load = loader.loads[i]; + if (load.name != name) + continue; + return load; + } + + load = createLoad(name); + loader.loads.push(load); + + proceedToLocate(loader, load); + + return load; + }); + } + + // 15.2.4.3 + function proceedToLocate(loader, load) { + proceedToFetch(loader, load, + Promise.resolve() + // 15.2.4.3.1 CallLocate + .then(function() { + return loader.loaderObj.locate({ name: load.name, metadata: load.metadata }); + }) + ); + } + + // 15.2.4.4 + function proceedToFetch(loader, load, p) { + proceedToTranslate(loader, load, + p + // 15.2.4.4.1 CallFetch + .then(function(address) { + // adjusted, see https://bugs.ecmascript.org/show_bug.cgi?id=2602 + if (load.status != 'loading') + return; + load.address = address; + + return loader.loaderObj.fetch({ name: load.name, metadata: load.metadata, address: address }); + }) + ); + } + + // 15.2.4.5 + function proceedToTranslate(loader, load, p) { + p + // 15.2.4.5.1 CallTranslate + .then(function(source) { + if (load.status != 'loading') + return; + + load.address = load.address || load.name; + + return Promise.resolve(loader.loaderObj.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source })) + + // 15.2.4.5.2 CallInstantiate + .then(function(source) { + load.source = source; + return loader.loaderObj.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source }); + }) + + // 15.2.4.5.3 InstantiateSucceeded + .then(function(instantiateResult) { + if (instantiateResult === undefined) + throw new TypeError('Declarative modules unsupported in the polyfill.'); + + if (typeof instantiateResult != 'object') + throw new TypeError('Invalid instantiate return value'); + + load.depsList = instantiateResult.deps || []; + load.execute = instantiateResult.execute; + }) + // 15.2.4.6 ProcessLoadDependencies + .then(function() { + load.dependencies = []; + var depsList = load.depsList; + + var loadPromises = []; + for (var i = 0, l = depsList.length; i < l; i++) (function(request, index) { + loadPromises.push( + requestLoad(loader, request, load.name, load.address) + + // 15.2.4.6.1 AddDependencyLoad (load is parentLoad) + .then(function(depLoad) { + + // adjusted from spec to maintain dependency order + // this is due to the System.register internal implementation needs + load.dependencies[index] = { + key: request, + value: depLoad.name + }; + + if (depLoad.status != 'linked') { + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + addLoadToLinkSet(linkSets[i], depLoad); + } + + // console.log('AddDependencyLoad ' + depLoad.name + ' for ' + load.name); + // snapshot(loader); + }) + ); + })(depsList[i], i); + + return Promise.all(loadPromises); + }) + + // 15.2.4.6.2 LoadSucceeded + .then(function() { + // console.log('LoadSucceeded ' + load.name); + // snapshot(loader); + + load.status = 'loaded'; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + updateLinkSetOnLoad(linkSets[i], load); + }); + }) + // 15.2.4.5.4 LoadFailed + ['catch'](function(exc) { + load.status = 'failed'; + load.exception = exc; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) { + linkSetFailed(linkSets[i], load, exc); + } + + console.assert(load.linkSets.length == 0, 'linkSets not removed'); + }); + } + + // 15.2.4.7 PromiseOfStartLoadPartwayThrough absorbed into calling functions + + // 15.2.4.7.1 + function asyncStartLoadPartwayThrough(stepState) { + return function(resolve, reject) { + var loader = stepState.loader; + var name = stepState.moduleName; + var step = stepState.step; + + if (loader.modules[name]) + throw new TypeError('"' + name + '" already exists in the module table'); + + // adjusted to pick up existing loads + var existingLoad; + for (var i = 0, l = loader.loads.length; i < l; i++) { + if (loader.loads[i].name == name) { + existingLoad = loader.loads[i]; + + if (step == 'translate' && !existingLoad.source) { + existingLoad.address = stepState.moduleAddress; + proceedToTranslate(loader, existingLoad, Promise.resolve(stepState.moduleSource)); + } + + // a primary load -> use that existing linkset if it is for the direct load here + // otherwise create a new linkset unit + if (existingLoad.linkSets.length && existingLoad.linkSets[0].loads[0].name == existingLoad.name) + return existingLoad.linkSets[0].done.then(function() { + resolve(existingLoad); + }); + } + } + + var load = existingLoad || createLoad(name); + + load.metadata = stepState.moduleMetadata; + + var linkSet = createLinkSet(loader, load); + + loader.loads.push(load); + + resolve(linkSet.done); + + if (step == 'locate') + proceedToLocate(loader, load); + + else if (step == 'fetch') + proceedToFetch(loader, load, Promise.resolve(stepState.moduleAddress)); + + else { + console.assert(step == 'translate', 'translate step'); + load.address = stepState.moduleAddress; + proceedToTranslate(loader, load, Promise.resolve(stepState.moduleSource)); + } + } + } + + // Declarative linking functions run through alternative implementation: + // 15.2.5.1.1 CreateModuleLinkageRecord not implemented + // 15.2.5.1.2 LookupExport not implemented + // 15.2.5.1.3 LookupModuleDependency not implemented + + // 15.2.5.2.1 + function createLinkSet(loader, startingLoad) { + var linkSet = { + loader: loader, + loads: [], + startingLoad: startingLoad, // added see spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + loadingCount: 0 + }; + linkSet.done = new Promise(function(resolve, reject) { + linkSet.resolve = resolve; + linkSet.reject = reject; + }); + addLoadToLinkSet(linkSet, startingLoad); + return linkSet; + } + // 15.2.5.2.2 + function addLoadToLinkSet(linkSet, load) { + if (load.status == 'failed') + return; + + for (var i = 0, l = linkSet.loads.length; i < l; i++) + if (linkSet.loads[i] == load) + return; + + linkSet.loads.push(load); + load.linkSets.push(linkSet); + + // adjustment, see https://bugs.ecmascript.org/show_bug.cgi?id=2603 + if (load.status != 'loaded') { + linkSet.loadingCount++; + } + + var loader = linkSet.loader; + + for (var i = 0, l = load.dependencies.length; i < l; i++) { + if (!load.dependencies[i]) + continue; + + var name = load.dependencies[i].value; + + if (loader.modules[name]) + continue; + + for (var j = 0, d = loader.loads.length; j < d; j++) { + if (loader.loads[j].name != name) + continue; + + addLoadToLinkSet(linkSet, loader.loads[j]); + break; + } + } + // console.log('add to linkset ' + load.name); + // snapshot(linkSet.loader); + } + + // linking errors can be generic or load-specific + // this is necessary for debugging info + function doLink(linkSet) { + var error = false; + try { + link(linkSet, function(load, exc) { + linkSetFailed(linkSet, load, exc); + error = true; + }); + } + catch(e) { + linkSetFailed(linkSet, null, e); + error = true; + } + return error; + } + + // 15.2.5.2.3 + function updateLinkSetOnLoad(linkSet, load) { + // console.log('update linkset on load ' + load.name); + // snapshot(linkSet.loader); + + console.assert(load.status == 'loaded' || load.status == 'linked', 'loaded or linked'); + + linkSet.loadingCount--; + + if (linkSet.loadingCount > 0) + return; + + // adjusted for spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + var startingLoad = linkSet.startingLoad; + + // non-executing link variation for loader tracing + // on the server. Not in spec. + /***/ + if (linkSet.loader.loaderObj.execute === false) { + var loads = [].concat(linkSet.loads); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + load.module = { + name: load.name, + module: _newModule({}), + evaluated: true + }; + load.status = 'linked'; + finishLoad(linkSet.loader, load); + } + return linkSet.resolve(startingLoad); + } + /***/ + + var abrupt = doLink(linkSet); + + if (abrupt) + return; + + console.assert(linkSet.loads.length == 0, 'loads cleared'); + + linkSet.resolve(startingLoad); + } + + // 15.2.5.2.4 + function linkSetFailed(linkSet, load, exc) { + var loader = linkSet.loader; + var requests; + + checkError: + if (load) { + if (linkSet.loads[0].name == load.name) { + exc = addToError(exc, 'Error loading ' + load.name); + } + else { + for (var i = 0; i < linkSet.loads.length; i++) { + var pLoad = linkSet.loads[i]; + for (var j = 0; j < pLoad.dependencies.length; j++) { + var dep = pLoad.dependencies[j]; + if (dep.value == load.name) { + exc = addToError(exc, 'Error loading ' + load.name + ' as "' + dep.key + '" from ' + pLoad.name); + break checkError; + } + } + } + exc = addToError(exc, 'Error loading ' + load.name + ' from ' + linkSet.loads[0].name); + } + } + else { + exc = addToError(exc, 'Error linking ' + linkSet.loads[0].name); + } + + + var loads = linkSet.loads.concat([]); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + + // store all failed load records + loader.loaderObj.failed = loader.loaderObj.failed || []; + if (indexOf.call(loader.loaderObj.failed, load) == -1) + loader.loaderObj.failed.push(load); + + var linkIndex = indexOf.call(load.linkSets, linkSet); + console.assert(linkIndex != -1, 'link not present'); + load.linkSets.splice(linkIndex, 1); + if (load.linkSets.length == 0) { + var globalLoadsIndex = indexOf.call(linkSet.loader.loads, load); + if (globalLoadsIndex != -1) + linkSet.loader.loads.splice(globalLoadsIndex, 1); + } + } + linkSet.reject(exc); + } + + // 15.2.5.2.5 + function finishLoad(loader, load) { + // add to global trace if tracing + if (loader.loaderObj.trace) { + if (!loader.loaderObj.loads) + loader.loaderObj.loads = {}; + var depMap = {}; + load.dependencies.forEach(function(dep) { + depMap[dep.key] = dep.value; + }); + loader.loaderObj.loads[load.name] = { + name: load.name, + deps: load.dependencies.map(function(dep){ return dep.key }), + depMap: depMap, + address: load.address, + metadata: load.metadata, + source: load.source + }; + } + // if not anonymous, add to the module table + if (load.name) { + console.assert(!loader.modules[load.name] || loader.modules[load.name].module === load.module.module, 'load not in module table'); + loader.modules[load.name] = load.module; + } + var loadIndex = indexOf.call(loader.loads, load); + if (loadIndex != -1) + loader.loads.splice(loadIndex, 1); + for (var i = 0, l = load.linkSets.length; i < l; i++) { + loadIndex = indexOf.call(load.linkSets[i].loads, load); + if (loadIndex != -1) + load.linkSets[i].loads.splice(loadIndex, 1); + } + load.linkSets.splice(0, load.linkSets.length); + } + + function doDynamicExecute(linkSet, load, linkError) { + try { + var module = load.execute(); + } + catch(e) { + linkError(load, e); + return; + } + if (!module || !(module instanceof Module)) + linkError(load, new TypeError('Execution must define a Module instance')); + else + return module; + } + + // 26.3 Loader + + // 26.3.1.1 + // defined at top + + // importPromises adds ability to import a module twice without error - https://bugs.ecmascript.org/show_bug.cgi?id=2601 + function createImportPromise(loader, name, promise) { + var importPromises = loader._loader.importPromises; + return importPromises[name] = promise.then(function(m) { + importPromises[name] = undefined; + return m; + }, function(e) { + importPromises[name] = undefined; + throw e; + }); + } + + Loader.prototype = { + // 26.3.3.1 + constructor: Loader, + // 26.3.3.2 + define: function(name, source, options) { + // check if already defined + if (this._loader.importPromises[name]) + throw new TypeError('Module is already loading.'); + return createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'translate', + loader: this._loader, + moduleName: name, + moduleMetadata: options && options.metadata || {}, + moduleSource: source, + moduleAddress: options && options.address + }))); + }, + // 26.3.3.3 + 'delete': function(name) { + var loader = this._loader; + delete loader.importPromises[name]; + delete loader.moduleRecords[name]; + return loader.modules[name] ? delete loader.modules[name] : false; + }, + // 26.3.3.4 entries not implemented + // 26.3.3.5 + get: function(key) { + if (!this._loader.modules[key]) + return; + return this._loader.modules[key].module; + }, + // 26.3.3.7 + has: function(name) { + return !!this._loader.modules[name]; + }, + // 26.3.3.8 + 'import': function(name, parentName, parentAddress) { + if (typeof parentName == 'object') + parentName = parentName.name; + + // run normalize first + var loaderObj = this; + + // added, see https://bugs.ecmascript.org/show_bug.cgi?id=2659 + return Promise.resolve(loaderObj.normalize(name, parentName)) + .then(function(name) { + var loader = loaderObj._loader; + + if (loader.modules[name]) + return loader.modules[name].module; + + return loader.importPromises[name] || createImportPromise(loaderObj, name, + loadModule(loader, name, {}) + .then(function(load) { + delete loader.importPromises[name]; + return load.module.module; + })); + }); + }, + // 26.3.3.9 keys not implemented + // 26.3.3.10 + load: function(name) { + var loader = this._loader; + if (loader.modules[name]) + return Promise.resolve(); + return loader.importPromises[name] || createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'locate', + loader: loader, + moduleName: name, + moduleMetadata: {}, + moduleSource: undefined, + moduleAddress: undefined + })) + .then(function() { + delete loader.importPromises[name]; + })); + }, + // 26.3.3.11 + module: function(source, options) { + var load = createLoad(); + load.address = options && options.address; + var linkSet = createLinkSet(this._loader, load); + var sourcePromise = Promise.resolve(source); + var loader = this._loader; + var p = linkSet.done.then(function() { + return load.module.module; + }); + proceedToTranslate(loader, load, sourcePromise); + return p; + }, + // 26.3.3.12 + newModule: function (obj) { + if (typeof obj != 'object') + throw new TypeError('Expected object'); + + var m = new Module(); + + var pNames = []; + if (Object.getOwnPropertyNames && obj != null) + pNames = Object.getOwnPropertyNames(obj); + else + for (var key in obj) + pNames.push(key); + + for (var i = 0; i < pNames.length; i++) (function(key) { + defineProperty(m, key, { + configurable: false, + enumerable: true, + get: function () { + return obj[key]; + }, + set: function() { + throw new Error('Module exports cannot be changed externally.'); + } + }); + })(pNames[i]); + + if (Object.freeze) + Object.freeze(m); + + return m; + }, + // 26.3.3.14 + set: function(name, module) { + if (!(module instanceof Module)) + throw new TypeError('Loader.set(' + name + ', module) must be a module'); + this._loader.modules[name] = { + module: module + }; + }, + // 26.3.3.15 values not implemented + // 26.3.3.16 @@iterator not implemented + // 26.3.3.17 @@toStringTag not implemented + + // 26.3.3.18.1 + normalize: function(name, referrerName, referrerAddress) {}, + // 26.3.3.18.2 + locate: function(load) { + return load.name; + }, + // 26.3.3.18.3 + fetch: function(load) { + }, + // 26.3.3.18.4 + translate: function(load) { + return load.source; + }, + // 26.3.3.18.5 + instantiate: function(load) { + } + }; + + var _newModule = Loader.prototype.newModule; + +/* + * ES6 Module Declarative Linking Code + */ + function link(linkSet, linkError) { + + var loader = linkSet.loader; + + if (!linkSet.loads.length) + return; + + var loads = linkSet.loads.concat([]); + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + + var module = doDynamicExecute(linkSet, load, linkError); + if (!module) + return; + load.module = { + name: load.name, + module: module + }; + load.status = 'linked'; + + finishLoad(loader, load); + } + } + +})(); + +var System; + + var fetchTextFromURL; + if (typeof XMLHttpRequest != 'undefined') { + fetchTextFromURL = function(url, authorization, fulfill, reject) { + var xhr = new XMLHttpRequest(); + var sameDomain = true; + var doTimeout = false; + if (!('withCredentials' in xhr)) { + // check if same domain + var domainCheck = /^(\w+:)?\/\/([^\/]+)/.exec(url); + if (domainCheck) { + sameDomain = domainCheck[2] === window.location.host; + if (domainCheck[1]) + sameDomain &= domainCheck[1] === window.location.protocol; + } + } + if (!sameDomain && typeof XDomainRequest != 'undefined') { + xhr = new XDomainRequest(); + xhr.onload = load; + xhr.onerror = error; + xhr.ontimeout = error; + xhr.onprogress = function() {}; + xhr.timeout = 0; + doTimeout = true; + } + function load() { + fulfill(xhr.responseText); + } + function error() { + reject(new Error('XHR error' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url)); + } + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + // in Chrome on file:/// URLs, status is 0 + if (xhr.status == 0) { + if (xhr.responseText) { + load(); + } + else { + // when responseText is empty, wait for load or error event + // to inform if it is a 404 or empty file + xhr.addEventListener('error', error); + xhr.addEventListener('load', load); + } + } + else if (xhr.status === 200) { + load(); + } + else { + error(); + } + } + }; + xhr.open("GET", url, true); + + if (xhr.setRequestHeader) { + xhr.setRequestHeader('Accept', 'application/x-es-module, */*'); + // can set "authorization: true" to enable withCredentials only + if (authorization) { + if (typeof authorization == 'string') + xhr.setRequestHeader('Authorization', authorization); + xhr.withCredentials = true; + } + } + + if (doTimeout) { + setTimeout(function() { + xhr.send(); + }, 0); + } else { + xhr.send(null); + } + }; + } + else if (typeof require != 'undefined' && typeof process != 'undefined') { + var fs; + fetchTextFromURL = function(url, authorization, fulfill, reject) { + if (url.substr(0, 8) != 'file:///') + throw new Error('Unable to fetch "' + url + '". Only file URLs of the form file:/// allowed running in Node.'); + fs = fs || require('fs'); + if (isWindows) + url = url.replace(/\//g, '\\').substr(8); + else + url = url.substr(7); + return fs.readFile(url, function(err, data) { + if (err) { + return reject(err); + } + else { + // Strip Byte Order Mark out if it's the leading char + var dataString = data + ''; + if (dataString[0] === '\ufeff') + dataString = dataString.substr(1); + + fulfill(dataString); + } + }); + }; + } + else if (typeof self != 'undefined' && typeof self.fetch != 'undefined') { + fetchTextFromURL = function(url, authorization, fulfill, reject) { + var opts = { + headers: {'Accept': 'application/x-es-module, */*'} + }; + + if (authorization) { + if (typeof authorization == 'string') + opts.headers['Authorization'] = authorization; + opts.credentials = 'include'; + } + + fetch(url, opts) + .then(function (r) { + if (r.ok) { + return r.text(); + } else { + throw new Error('Fetch error: ' + r.status + ' ' + r.statusText); + } + }) + .then(fulfill, reject); + } + } + else { + throw new TypeError('No environment fetch API available.'); + } +/* + * Traceur, Babel and TypeScript transpile hook for Loader + */ +var transpile = (function() { + + // use Traceur by default + Loader.prototype.transpiler = 'traceur'; + + function transpile(load) { + var self = this; + + return Promise.resolve(__global[self.transpiler == 'typescript' ? 'ts' : self.transpiler] + || (self.pluginLoader || self)['import'](self.transpiler)) + .then(function(transpiler) { + if (transpiler.__useDefault) + transpiler = transpiler['default']; + + var transpileFunction; + if (transpiler.Compiler) + transpileFunction = traceurTranspile; + else if (transpiler.createLanguageService) + transpileFunction = typescriptTranspile; + else + transpileFunction = babelTranspile; + + // note __moduleName will be part of the transformer meta in future when we have the spec for this + return '(function(__moduleName){' + transpileFunction.call(self, load, transpiler) + '\n})("' + load.name + '");\n//# sourceURL=' + load.address + '!transpiled'; + }); + }; + + function traceurTranspile(load, traceur) { + var options = this.traceurOptions || {}; + options.modules = 'instantiate'; + options.script = false; + if (options.sourceMaps === undefined) + options.sourceMaps = 'inline'; + options.filename = load.address; + options.inputSourceMap = load.metadata.sourceMap; + options.moduleName = false; + + var compiler = new traceur.Compiler(options); + + return doTraceurCompile(load.source, compiler, options.filename); + } + function doTraceurCompile(source, compiler, filename) { + try { + return compiler.compile(source, filename); + } + catch(e) { + // on older versions of traceur (<0.9.3), an array of errors is thrown + // rather than a single error. + if (e.length) { + throw e[0]; + } + throw e; + } + } + + function babelTranspile(load, babel) { + var options = this.babelOptions || {}; + options.modules = 'system'; + if (options.sourceMap === undefined) + options.sourceMap = 'inline'; + options.inputSourceMap = load.metadata.sourceMap; + options.filename = load.address; + options.code = true; + options.ast = false; + + return babel.transform(load.source, options).code; + } + + function typescriptTranspile(load, ts) { + var options = this.typescriptOptions || {}; + options.target = options.target || ts.ScriptTarget.ES5; + if (options.sourceMap === undefined) + options.sourceMap = true; + if (options.sourceMap && options.inlineSourceMap !== false) + options.inlineSourceMap = true; + + options.module = ts.ModuleKind.System; + + return ts.transpile(load.source, options, load.address); + } + + return transpile; +})(); +// SystemJS Loader Class and Extension helpers +function SystemJSLoader() { + Loader.call(this); + + this.paths = {}; + this._loader.paths = {}; + + systemJSConstructor.call(this); +} + +// inline Object.create-style class extension +function SystemProto() {}; +SystemProto.prototype = Loader.prototype; +SystemJSLoader.prototype = new SystemProto(); +SystemJSLoader.prototype.constructor = SystemJSLoader; + +var systemJSConstructor; + +function hook(name, hook) { + SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {}); +} +function hookConstructor(hook) { + systemJSConstructor = hook(systemJSConstructor || function() {}); +} + + +var absURLRegEx = /^[^\/]+:\/\//; +function isAbsolute(name) { + return name.match(absURLRegEx); +} +function isRel(name) { + return (name[0] == '.' && (!name[1] || name[1] == '/' || name[1] == '.')) || name[0] == '/'; +} +function isPlain(name) { + return !isRel(name) && !isAbsolute(name); +} + +var baseURIObj = new URL(baseURI); + +function urlResolve(name, parent) { + // url resolution shortpaths + if (name[0] == '.') { + // dot-relative url normalization + if (name[1] == '/' && name[2] != '.') + return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name.substr(2); + } + else if (name[0] != '/' && name.indexOf(':') == -1) { + // plain parent normalization + return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name; + } + + return new URL(name, parent && parent.replace(/#/g, '%05') || baseURIObj).href.replace(/%05/g, '#'); +} + +// NB no specification provided for System.paths, used ideas discussed in https://github.com/jorendorff/js-loaders/issues/25 +function applyPaths(loader, name) { + // most specific (most number of slashes in path) match wins + var pathMatch = '', wildcard, maxWildcardPrefixLen = 0; + + var paths = loader.paths; + var pathsCache = loader._loader.paths; + + // check to see if we have a paths entry + for (var p in paths) { + if (paths.hasOwnProperty && !paths.hasOwnProperty(p)) + continue; + + // paths sanitization + var path = paths[p]; + if (path !== pathsCache[p]) + path = paths[p] = pathsCache[p] = urlResolve(paths[p], isRel(paths[p]) ? baseURI : loader.baseURL); + + // exact path match + if (p.indexOf('*') === -1) { + if (name == p) + return paths[p]; + + // support trailing / in paths rules + else if (name.substr(0, p.length - 1) == p.substr(0, p.length - 1) && (name.length < p.length || name[p.length - 1] == p[p.length - 1]) && (paths[p][paths[p].length - 1] == '/' || paths[p] == '')) { + return paths[p].substr(0, paths[p].length - 1) + (name.length > p.length ? (paths[p] && '/' || '') + name.substr(p.length) : ''); + } + } + // wildcard path match + else { + var pathParts = p.split('*'); + if (pathParts.length > 2) + throw new TypeError('Only one wildcard in a path is permitted'); + + var wildcardPrefixLen = pathParts[0].length; + if (wildcardPrefixLen >= maxWildcardPrefixLen && + name.substr(0, pathParts[0].length) == pathParts[0] && + name.substr(name.length - pathParts[1].length) == pathParts[1]) { + maxWildcardPrefixLen = wildcardPrefixLen; + pathMatch = p; + wildcard = name.substr(pathParts[0].length, name.length - pathParts[1].length - pathParts[0].length); + } + } + } + + var outPath = paths[pathMatch]; + if (typeof wildcard == 'string') + outPath = outPath.replace('*', wildcard); + + return outPath; +} + +function dedupe(deps) { + var newDeps = []; + for (var i = 0, l = deps.length; i < l; i++) + if (indexOf.call(newDeps, deps[i]) == -1) + newDeps.push(deps[i]) + return newDeps; +} + +function group(deps) { + var names = []; + var indices = []; + for (var i = 0, l = deps.length; i < l; i++) { + var index = indexOf.call(names, deps[i]); + if (index === -1) { + names.push(deps[i]); + indices.push([i]); + } + else { + indices[index].push(i); + } + } + return { names: names, indices: indices }; +} + +var getOwnPropertyDescriptor = true; +try { + Object.getOwnPropertyDescriptor({ a: 0 }, 'a'); +} +catch(e) { + getOwnPropertyDescriptor = false; +} + +// converts any module.exports object into an object ready for SystemJS.newModule +function getESModule(exports) { + var esModule = {}; + // don't trigger getters/setters in environments that support them + if ((typeof exports == 'object' || typeof exports == 'function') && exports !== __global) { + if (getOwnPropertyDescriptor) { + for (var p in exports) { + // The default property is copied to esModule later on + if (p === 'default') + continue; + defineOrCopyProperty(esModule, exports, p); + } + } + else { + extend(esModule, exports); + } + } + esModule['default'] = exports; + defineProperty(esModule, '__useDefault', { + value: true + }); + return esModule; +} + +function defineOrCopyProperty(targetObj, sourceObj, propName) { + try { + var d; + if (d = Object.getOwnPropertyDescriptor(sourceObj, propName)) + defineProperty(targetObj, propName, d); + } + catch (ex) { + // Object.getOwnPropertyDescriptor threw an exception, fall back to normal set property + // we dont need hasOwnProperty here because getOwnPropertyDescriptor would have returned undefined above + targetObj[propName] = sourceObj[propName]; + return false; + } +} + +function extend(a, b, prepend) { + var hasOwnProperty = b && b.hasOwnProperty; + for (var p in b) { + if (hasOwnProperty && !b.hasOwnProperty(p)) + continue; + if (!prepend || !(p in a)) + a[p] = b[p]; + } + return a; +} + +// meta first-level extends where: +// array + array appends +// object + object extends +// other properties replace +function extendMeta(a, b, prepend) { + var hasOwnProperty = b && b.hasOwnProperty; + for (var p in b) { + if (hasOwnProperty && !b.hasOwnProperty(p)) + continue; + var val = b[p]; + if (!(p in a)) + a[p] = val; + else if (val instanceof Array && a[p] instanceof Array) + a[p] = [].concat(prepend ? val : a[p]).concat(prepend ? a[p] : val); + else if (typeof val == 'object' && val !== null && typeof a[p] == 'object') + a[p] = extend(extend({}, a[p]), val, prepend); + else if (!prepend) + a[p] = val; + } +} + +function extendPkgConfig(pkgCfgA, pkgCfgB, pkgName, loader, warnInvalidProperties) { + for (var prop in pkgCfgB) { + if (indexOf.call(['main', 'format', 'defaultExtension', 'basePath'], prop) != -1) { + pkgCfgA[prop] = pkgCfgB[prop]; + } + else if (prop == 'map') { + extend(pkgCfgA.map = pkgCfgA.map || {}, pkgCfgB.map); + } + else if (prop == 'meta') { + extend(pkgCfgA.meta = pkgCfgA.meta || {}, pkgCfgB.meta); + } + else if (prop == 'depCache') { + for (var d in pkgCfgB.depCache) { + var dNormalized; + + if (d.substr(0, 2) == './') + dNormalized = pkgName + '/' + d.substr(2); + else + dNormalized = coreResolve.call(loader, d); + loader.depCache[dNormalized] = (loader.depCache[dNormalized] || []).concat(pkgCfgB.depCache[d]); + } + } + else if (warnInvalidProperties && indexOf.call(['browserConfig', 'nodeConfig', 'devConfig', 'productionConfig'], prop) == -1 && + (!pkgCfgB.hasOwnProperty || pkgCfgB.hasOwnProperty(prop))) { + warn.call(loader, '"' + prop + '" is not a valid package configuration option in package ' + pkgName); + } + } +} + +// deeply-merge (to first level) config with any existing package config +function setPkgConfig(loader, pkgName, cfg, prependConfig) { + var pkg; + + // first package is config by reference for fast path, cloned after that + if (!loader.packages[pkgName]) { + pkg = loader.packages[pkgName] = cfg; + } + else { + var basePkg = loader.packages[pkgName]; + pkg = loader.packages[pkgName] = {}; + + extendPkgConfig(pkg, prependConfig ? cfg : basePkg, pkgName, loader, prependConfig); + extendPkgConfig(pkg, prependConfig ? basePkg : cfg, pkgName, loader, !prependConfig); + } + + // main object becomes main map + if (typeof pkg.main == 'object') { + pkg.map = pkg.map || {}; + pkg.map['./@main'] = pkg.main; + pkg.main['default'] = pkg.main['default'] || './'; + pkg.main = '@main'; + } + + return pkg; +} + +function warn(msg) { + if (this.warnings && typeof console != 'undefined' && console.warn) + console.warn(msg); +} +// we define a __exec for globally-scoped execution +// used by module format implementations +var __exec; + +(function() { + + var hasBuffer = typeof Buffer != 'undefined'; + try { + if (hasBuffer && new Buffer('a').toString('base64') != 'YQ==') + hasBuffer = false; + } + catch(e) { + hasBuffer = false; + } + + var sourceMapPrefix = '\n//# sourceMappingURL=data:application/json;base64,'; + function inlineSourceMap(sourceMapString) { + if (hasBuffer) + return sourceMapPrefix + new Buffer(sourceMapString).toString('base64'); + else if (typeof btoa != 'undefined') + return sourceMapPrefix + btoa(unescape(encodeURIComponent(sourceMapString))); + else + return ''; + } + + function getSource(load, wrap) { + var lastLineIndex = load.source.lastIndexOf('\n'); + + // wrap ES formats with a System closure for System global encapsulation + if (load.metadata.format == 'global') + wrap = false; + + var sourceMap = load.metadata.sourceMap; + if (sourceMap) { + if (typeof sourceMap != 'object') + throw new TypeError('load.metadata.sourceMap must be set to an object.'); + + sourceMap = JSON.stringify(sourceMap); + } + + return (wrap ? '(function(System, SystemJS) {' : '') + load.source + (wrap ? '\n})(System, System);' : '') + // adds the sourceURL comment if not already present + + (load.source.substr(lastLineIndex, 15) != '\n//# sourceURL=' + ? '\n//# sourceURL=' + load.address + (sourceMap ? '!transpiled' : '') : '') + // add sourceMappingURL if load.metadata.sourceMap is set + + (sourceMap && inlineSourceMap(sourceMap) || ''); + } + + var curLoad; + + // System.register, System.registerDynamic, AMD define pipeline + // if currently evalling code here, immediately reduce the registered entry against the load record + hook('pushRegister_', function() { + return function(register) { + if (!curLoad) + return false; + + this.reduceRegister_(curLoad, register); + return true; + }; + }); + + // System clobbering protection (mostly for Traceur) + var curSystem; + var callCounter = 0; + function preExec(loader, load) { + curLoad = load; + if (callCounter++ == 0) + curSystem = __global.System; + __global.System = __global.SystemJS = loader; + } + function postExec() { + if (--callCounter == 0) + __global.System = __global.SystemJS = curSystem; + curLoad = undefined; + } + + var useVm; + var vm; + __exec = function(load) { + if (!load.source) + return; + if ((load.metadata.integrity || load.metadata.nonce) && supportsScriptExec) + return scriptExec.call(this, load); + try { + preExec(this, load); + curLoad = load; + // global scoped eval for node (avoids require scope leak) + if (!vm && this._nodeRequire) { + vm = this._nodeRequire('vm'); + useVm = vm.runInThisContext("typeof System !== 'undefined' && System") === this; + } + if (useVm) + vm.runInThisContext(getSource(load, true), { filename: load.address + (load.metadata.sourceMap ? '!transpiled' : '') }); + else + (0, eval)(getSource(load, true)); + postExec(); + } + catch(e) { + postExec(); + throw addToError(e, 'Evaluating ' + load.address); + } + }; + + var supportsScriptExec = false; + if (isBrowser && typeof document != 'undefined' && document.getElementsByTagName) { + var scripts = document.getElementsByTagName('script'); + $__curScript = scripts[scripts.length - 1]; + + if (!(window.chrome && window.chrome.extension || navigator.userAgent.match(/^Node\.js/))) + supportsScriptExec = true; + } + + // script execution via injecting a script tag into the page + // this allows CSP integrity and nonce to be set for CSP environments + var head; + function scriptExec(load) { + if (!head) + head = document.head || document.body || document.documentElement; + + var script = document.createElement('script'); + script.text = getSource(load, false); + var onerror = window.onerror; + var e; + window.onerror = function(_e) { + e = addToError(_e, 'Evaluating ' + load.address); + if (onerror) + onerror.apply(this, arguments); + } + preExec(this, load); + + if (load.metadata.integrity) + script.setAttribute('integrity', load.metadata.integrity); + if (load.metadata.nonce) + script.setAttribute('nonce', load.metadata.nonce); + + head.appendChild(script); + head.removeChild(script); + postExec(); + window.onerror = onerror; + if (e) + throw e; + } + +})(); +function readMemberExpression(p, value) { + var pParts = p.split('.'); + while (pParts.length) + value = value[pParts.shift()]; + return value; +} + +function getMapMatch(map, name) { + var bestMatch, bestMatchLength = 0; + + for (var p in map) { + if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) { + var curMatchLength = p.split('/').length; + if (curMatchLength <= bestMatchLength) + continue; + bestMatch = p; + bestMatchLength = curMatchLength; + } + } + + return bestMatch; +} + +function prepareBaseURL(loader) { + // ensure baseURl is fully normalized + if (this._loader.baseURL !== this.baseURL) { + if (this.baseURL[this.baseURL.length - 1] != '/') + this.baseURL += '/'; + + this._loader.baseURL = this.baseURL = new URL(this.baseURL, baseURIObj).href; + } +} + +var envModule; +function setProduction(isProduction, isBuilder) { + this.set('@system-env', envModule = this.newModule({ + browser: isBrowser, + node: !!this._nodeRequire, + production: !isBuilder && isProduction, + dev: isBuilder || !isProduction, + build: isBuilder, + 'default': true + })); +} + +hookConstructor(function(constructor) { + return function() { + constructor.call(this); + + // support baseURL + this.baseURL = baseURI; + + // support map and paths + this.map = {}; + + // make the location of the system.js script accessible + if (typeof $__curScript != 'undefined') + this.scriptSrc = $__curScript.src; + + // global behaviour flags + this.warnings = false; + this.defaultJSExtensions = false; + this.pluginFirst = false; + this.loaderErrorStack = false; + + // by default load ".json" files as json + // leading * meta doesn't need normalization + // NB add this in next breaking release + // this.meta['*.json'] = { format: 'json' }; + + // support the empty module, as a concept + this.set('@empty', this.newModule({})); + + setProduction.call(this, false, false); + }; +}); + +// include the node require since we're overriding it +if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser) + SystemJSLoader.prototype._nodeRequire = require; + +/* + Core SystemJS Normalization + + If a name is relative, we apply URL normalization to the page + If a name is an absolute URL, we leave it as-is + + Plain names (neither of the above) run through the map and paths + normalization phases. + + The paths normalization phase applies last (paths extension), which + defines the `decanonicalize` function and normalizes everything into + a URL. + */ + +var parentModuleContext; +function getNodeModule(name, baseURL) { + if (!isPlain(name)) + throw new Error('Node module ' + name + ' can\'t be loaded as it is not a package require.'); + + if (!parentModuleContext) { + var Module = this._nodeRequire('module'); + var base = baseURL.substr(isWindows ? 8 : 7); + parentModuleContext = new Module(base); + parentModuleContext.paths = Module._nodeModulePaths(base); + } + return parentModuleContext.require(name); +} + +function coreResolve(name, parentName) { + // standard URL resolution + if (isRel(name)) + return urlResolve(name, parentName); + else if (isAbsolute(name)) + return name; + + // plain names not starting with './', '://' and '/' go through custom resolution + var mapMatch = getMapMatch(this.map, name); + + if (mapMatch) { + name = this.map[mapMatch] + name.substr(mapMatch.length); + + if (isRel(name)) + return urlResolve(name); + else if (isAbsolute(name)) + return name; + } + + if (this.has(name)) + return name; + + // dynamically load node-core modules when requiring `@node/fs` for example + if (name.substr(0, 6) == '@node/') { + if (!this._nodeRequire) + throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.'); + if (this.builder) + this.set(name, this.newModule({})); + else + this.set(name, this.newModule(getESModule(getNodeModule.call(this, name.substr(6), this.baseURL)))); + return name; + } + + // prepare the baseURL to ensure it is normalized + prepareBaseURL.call(this); + + return applyPaths(this, name) || this.baseURL + name; +} + +hook('normalize', function(normalize) { + return function(name, parentName, skipExt) { + var resolved = coreResolve.call(this, name, parentName); + if (this.defaultJSExtensions && !skipExt && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved)) + resolved += '.js'; + return resolved; + }; +}); + +// percent encode just '#' in urls if using HTTP requests +var httpRequest = typeof XMLHttpRequest != 'undefined'; +hook('locate', function(locate) { + return function(load) { + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + if (httpRequest) + return address.replace(/#/g, '%23'); + return address; + }); + }; +}); + +/* + * Fetch with authorization + */ +hook('fetch', function() { + return function(load) { + return new Promise(function(resolve, reject) { + fetchTextFromURL(load.address, load.metadata.authorization, resolve, reject); + }); + }; +}); + +/* + __useDefault + + When a module object looks like: + newModule( + __useDefault: true, + default: 'some-module' + }) + + Then importing that module provides the 'some-module' + result directly instead of the full module. + + Useful for eg module.exports = function() {} +*/ +hook('import', function(systemImport) { + return function(name, parentName, parentAddress) { + if (parentName && parentName.name) + warn.call(this, 'SystemJS.import(name, { name: parentName }) is deprecated for SystemJS.import(name, parentName), while importing ' + name + ' from ' + parentName.name); + return systemImport.call(this, name, parentName, parentAddress).then(function(module) { + return module.__useDefault ? module['default'] : module; + }); + }; +}); + +/* + * Allow format: 'detect' meta to enable format detection + */ +hook('translate', function(systemTranslate) { + return function(load) { + if (load.metadata.format == 'detect') + load.metadata.format = undefined; + return systemTranslate.apply(this, arguments); + }; +}); + + +/* + * JSON format support + * + * Supports loading JSON files as a module format itself + * + * Usage: + * + * SystemJS.config({ + * meta: { + * '*.json': { format: 'json' } + * } + * }); + * + * Module is returned as if written: + * + * export default {JSON} + * + * No named exports are provided + * + * Files ending in ".json" are treated as json automatically by SystemJS + */ +hook('instantiate', function(instantiate) { + return function(load) { + if (load.metadata.format == 'json' && !this.builder) { + var entry = load.metadata.entry = createEntry(); + entry.deps = []; + entry.execute = function() { + try { + return JSON.parse(load.source); + } + catch(e) { + throw new Error("Invalid JSON file " + load.name); + } + }; + } + }; +}) + +/* + Extend config merging one deep only + + loader.config({ + some: 'random', + config: 'here', + deep: { + config: { too: 'too' } + } + }); + + <=> + + loader.some = 'random'; + loader.config = 'here' + loader.deep = loader.deep || {}; + loader.deep.config = { too: 'too' }; + + + Normalizes meta and package configs allowing for: + + SystemJS.config({ + meta: { + './index.js': {} + } + }); + + To become + + SystemJS.meta['https://thissite.com/index.js'] = {}; + + For easy normalization canonicalization with latest URL support. + +*/ +function envSet(loader, cfg, envCallback) { + if (envModule.browser && cfg.browserConfig) + envCallback(cfg.browserConfig); + if (envModule.node && cfg.nodeConfig) + envCallback(cfg.nodeConfig); + if (envModule.dev && cfg.devConfig) + envCallback(cfg.devConfig); + if (envModule.build && cfg.buildConfig) + envCallback(cfg.buildConfig); + if (envModule.production && cfg.productionConfig) + envCallback(cfg.productionConfig); +} + +SystemJSLoader.prototype.getConfig = function(name) { + var cfg = {}; + var loader = this; + for (var p in loader) { + if (loader.hasOwnProperty && !loader.hasOwnProperty(p) || p in SystemJSLoader.prototype && p != 'transpiler') + continue; + if (indexOf.call(['_loader', 'amdDefine', 'amdRequire', 'defined', 'failed', 'version', 'loads'], p) == -1) + cfg[p] = loader[p]; + } + cfg.production = envModule.production; + return cfg; +}; + +var curCurScript; +SystemJSLoader.prototype.config = function(cfg, isEnvConfig) { + var loader = this; + + if ('loaderErrorStack' in cfg) { + curCurScript = $__curScript; + if (cfg.loaderErrorStack) + $__curScript = undefined; + else + $__curScript = curCurScript; + } + + if ('warnings' in cfg) + loader.warnings = cfg.warnings; + + // transpiler deprecation path + if (cfg.transpilerRuntime === false) + loader._loader.loadedTranspilerRuntime = true; + + if ('production' in cfg || 'build' in cfg) + setProduction.call(loader, !!cfg.production, !!(cfg.build || envModule && envModule.build)); + + if (!isEnvConfig) { + // if using nodeConfig / browserConfig / productionConfig, take baseURL from there + // these exceptions will be unnecessary when we can properly implement config queuings + var baseURL; + envSet(loader, cfg, function(cfg) { + baseURL = baseURL || cfg.baseURL; + }); + baseURL = baseURL || cfg.baseURL; + + // always configure baseURL first + if (baseURL) { + var hasConfig = false; + function checkHasConfig(obj) { + for (var p in obj) + if (obj.hasOwnProperty(p)) + return true; + } + if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths)) + throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.'); + + this.baseURL = baseURL; + prepareBaseURL.call(this); + } + + if (cfg.paths) + extend(loader.paths, cfg.paths); + + envSet(loader, cfg, function(cfg) { + if (cfg.paths) + extend(loader.paths, cfg.paths); + }); + + // warn on wildcard path deprecations + if (this.warnings) { + for (var p in loader.paths) + if (p.indexOf('*') != -1) + warn.call(loader, 'Paths configuration "' + p + '" -> "' + loader.paths[p] + '" uses wildcards which are being deprecated for simpler trailing "/" folder paths.'); + } + } + + if (cfg.defaultJSExtensions) { + loader.defaultJSExtensions = cfg.defaultJSExtensions; + warn.call(loader, 'The defaultJSExtensions configuration option is deprecated, use packages configuration instead.'); + } + + if (cfg.pluginFirst) + loader.pluginFirst = cfg.pluginFirst; + + if (cfg.map) { + var objMaps = ''; + for (var p in cfg.map) { + var v = cfg.map[p]; + + // object map backwards-compat into packages configuration + if (typeof v !== 'string') { + objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"'; + + var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js'; + var prop = loader.decanonicalize(p); + if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js') + prop = prop.substr(0, prop.length - 3); + + // if a package main, revert it + var pkgMatch = ''; + for (var pkg in loader.packages) { + if (prop.substr(0, pkg.length) == pkg + && (!prop[pkg.length] || prop[pkg.length] == '/') + && pkgMatch.split('/').length < pkg.split('/').length) + pkgMatch = pkg; + } + if (pkgMatch && loader.packages[pkgMatch].main) + prop = prop.substr(0, prop.length - loader.packages[pkgMatch].main.length - 1); + + var pkg = loader.packages[prop] = loader.packages[prop] || {}; + pkg.map = v; + } + else { + loader.map[p] = v; + } + } + if (objMaps) + warn.call(loader, 'The map configuration for ' + objMaps + ' uses object submaps, which is deprecated in global map.\nUpdate this to use package contextual map with configs like SystemJS.config({ packages: { "' + p + '": { map: {...} } } }).'); + } + + if (cfg.packageConfigPaths) { + var packageConfigPaths = []; + for (var i = 0; i < cfg.packageConfigPaths.length; i++) { + var path = cfg.packageConfigPaths[i]; + var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/')); + var normalized = coreResolve.call(loader, path.substr(0, packageLength)); + packageConfigPaths[i] = normalized + path.substr(packageLength); + } + loader.packageConfigPaths = packageConfigPaths; + } + + if (cfg.bundles) { + for (var p in cfg.bundles) { + var bundle = []; + for (var i = 0; i < cfg.bundles[p].length; i++) { + var defaultJSExtension = loader.defaultJSExtensions && cfg.bundles[p][i].substr(cfg.bundles[p][i].length - 3, 3) != '.js'; + var normalizedBundleDep = loader.decanonicalize(cfg.bundles[p][i]); + if (defaultJSExtension && normalizedBundleDep.substr(normalizedBundleDep.length - 3, 3) == '.js') + normalizedBundleDep = normalizedBundleDep.substr(0, normalizedBundleDep.length - 3); + bundle.push(normalizedBundleDep); + } + loader.bundles[p] = bundle; + } + } + + if (cfg.packages) { + for (var p in cfg.packages) { + if (p.match(/^([^\/]+:)?\/\/$/)) + throw new TypeError('"' + p + '" is not a valid package name.'); + + var prop = coreResolve.call(loader, p); + + // allow trailing slash in packages + if (prop[prop.length - 1] == '/') + prop = prop.substr(0, prop.length - 1); + + setPkgConfig(loader, prop, cfg.packages[p], false); + } + } + + for (var c in cfg) { + var v = cfg[c]; + + if (indexOf.call(['baseURL', 'map', 'packages', 'bundles', 'paths', 'warnings', 'packageConfigPaths', + 'loaderErrorStack', 'browserConfig', 'nodeConfig', 'devConfig', 'buildConfig', 'productionConfig'], c) != -1) + continue; + + if (typeof v != 'object' || v instanceof Array) { + loader[c] = v; + } + else { + loader[c] = loader[c] || {}; + + for (var p in v) { + // base-level wildcard meta does not normalize to retain catch-all quality + if (c == 'meta' && p[0] == '*') { + extend(loader[c][p] = loader[c][p] || {}, v[p]); + } + else if (c == 'meta') { + // meta can go through global map, with defaultJSExtensions adding + var resolved = coreResolve.call(loader, p); + if (loader.defaultJSExtensions && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved)) + resolved += '.js'; + extend(loader[c][resolved] = loader[c][resolved] || {}, v[p]); + } + else if (c == 'depCache') { + var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js'; + var prop = loader.decanonicalize(p); + if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js') + prop = prop.substr(0, prop.length - 3); + loader[c][prop] = [].concat(v[p]); + } + else { + loader[c][p] = v[p]; + } + } + } + } + + envSet(loader, cfg, function(cfg) { + loader.config(cfg, true); + }); +};/* + * Package Configuration Extension + * + * Example: + * + * SystemJS.packages = { + * jquery: { + * main: 'index.js', // when not set, package name is requested directly + * format: 'amd', + * defaultExtension: 'ts', // defaults to 'js', can be set to false + * modules: { + * '*.ts': { + * loader: 'typescript' + * }, + * 'vendor/sizzle.js': { + * format: 'global' + * } + * }, + * map: { + * // map internal require('sizzle') to local require('./vendor/sizzle') + * sizzle: './vendor/sizzle.js', + * // map any internal or external require of 'jquery/vendor/another' to 'another/index.js' + * './vendor/another.js': './another/index.js', + * // test.js / test -> lib/test.js + * './test.js': './lib/test.js', + * + * // environment-specific map configurations + * './index.js': { + * '~browser': './index-node.js', + * './custom-condition.js|~export': './index-custom.js' + * } + * }, + * // allows for setting package-prefixed depCache + * // keys are normalized module names relative to the package itself + * depCache: { + * // import 'package/index.js' loads in parallel package/lib/test.js,package/vendor/sizzle.js + * './index.js': ['./test'], + * './test.js': ['external-dep'], + * 'external-dep/path.js': ['./another.js'] + * } + * } + * }; + * + * Then: + * import 'jquery' -> jquery/index.js + * import 'jquery/submodule' -> jquery/submodule.js + * import 'jquery/submodule.ts' -> jquery/submodule.ts loaded as typescript + * import 'jquery/vendor/another' -> another/index.js + * + * Detailed Behaviours + * - main can have a leading "./" can be added optionally + * - map and defaultExtension are applied to the main + * - defaultExtension adds the extension only if the exact extension is not present + * - defaultJSExtensions applies after map when defaultExtension is not set + * - if a meta value is available for a module, map and defaultExtension are skipped + * - like global map, package map also applies to subpaths (sizzle/x, ./vendor/another/sub) + * - condition module map is '@env' module in package or '@system-env' globally + * - map targets support conditional interpolation ('./x': './x.#{|env}.js') + * - internal package map targets cannot use boolean conditionals + * + * Package Configuration Loading + * + * Not all packages may already have their configuration present in the System config + * For these cases, a list of packageConfigPaths can be provided, which when matched against + * a request, will first request a ".json" file by the package name to derive the package + * configuration from. This allows dynamic loading of non-predetermined code, a key use + * case in SystemJS. + * + * Example: + * + * SystemJS.packageConfigPaths = ['packages/test/package.json', 'packages/*.json']; + * + * // will first request 'packages/new-package/package.json' for the package config + * // before completing the package request to 'packages/new-package/path' + * SystemJS.import('packages/new-package/path'); + * + * // will first request 'packages/test/package.json' before the main + * SystemJS.import('packages/test'); + * + * When a package matches packageConfigPaths, it will always send a config request for + * the package configuration. + * The package name itself is taken to be the match up to and including the last wildcard + * or trailing slash. + * The most specific package config path will be used. + * Any existing package configurations for the package will deeply merge with the + * package config, with the existing package configurations taking preference. + * To opt-out of the package configuration request for a package that matches + * packageConfigPaths, use the { configured: true } package config option. + * + */ +(function() { + + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + this.packages = {}; + this.packageConfigPaths = []; + }; + }); + + function getPackage(loader, normalized) { + // use most specific package + var curPkg, curPkgLen = 0, pkgLen; + for (var p in loader.packages) { + if (normalized.substr(0, p.length) === p && (normalized.length === p.length || normalized[p.length] === '/')) { + pkgLen = p.split('/').length; + if (pkgLen > curPkgLen) { + curPkg = p; + curPkgLen = pkgLen; + } + } + } + return curPkg; + } + + function addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions) { + // don't apply extensions to folders or if defaultExtension = false + if (!subPath || subPath[subPath.length - 1] == '/' || skipExtensions || pkg.defaultExtension === false) + return subPath; + + var metaMatch = false; + + // exact meta or meta with any content after the last wildcard skips extension + if (pkg.meta) + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + // exact global meta or meta with any content after the last wildcard skips extension + if (!metaMatch && loader.meta) + getMetaMatches(loader.meta, pkgName + '/' + subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + if (metaMatch) + return subPath; + + // work out what the defaultExtension is and add if not there already + // NB reconsider if default should really be ".js"? + var defaultExtension = '.' + (pkg.defaultExtension || 'js'); + if (subPath.substr(subPath.length - defaultExtension.length) != defaultExtension) + return subPath + defaultExtension; + else + return subPath; + } + + function applyPackageConfigSync(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return pkgName + (loader.defaultJSExtensions ? '.js' : ''); + } + + // map config checking without then with extensions + if (pkg.map) { + var mapPath = './' + subPath; + + var mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + if (mapMatch) { + var mapped = doMapSync(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions); + if (mapped) + return mapped; + } + } + + // normal package resolution + return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + } + + function validMapping(mapMatch, mapped, pkgName, path) { + // disallow internal to subpath maps + if (mapMatch == '.') + throw new Error('Package ' + pkgName + ' has a map entry for "." which is not permitted.'); + + // allow internal ./x -> ./x/y or ./x/ -> ./x/y recursive maps + // but only if the path is exactly ./x and not ./x/z + if (mapped.substr(0, mapMatch.length) == mapMatch && path.length > mapMatch.length) + return false; + + return true; + } + + function doMapSync(loader, pkg, pkgName, mapMatch, path, skipExtensions) { + if (path[path.length - 1] == '/') + path = path.substr(0, path.length - 1); + var mapped = pkg.map[mapMatch]; + + if (typeof mapped == 'object') + throw new Error('Synchronous conditional normalization not supported sync normalizing ' + mapMatch + ' in ' + pkgName); + + if (!validMapping(mapMatch, mapped, pkgName, path) || typeof mapped != 'string') + return; + + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions); + + // external map reference + return loader.normalizeSync(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function applyPackageConfig(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return Promise.resolve(pkgName + (loader.defaultJSExtensions ? '.js' : '')); + } + + // map config checking without then with extensions + var mapPath, mapMatch; + + if (pkg.map) { + mapPath = './' + subPath; + mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + } + + return (mapMatch ? doMap(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions) : Promise.resolve()) + .then(function(mapped) { + if (mapped) + return Promise.resolve(mapped); + + // normal package resolution / fallback resolution for no conditional match + return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions)); + }); + } + + function doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions) { + // NB the interpolation cases should strictly skip subsequent interpolation + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions)) + .then(function(name) { + return interpolateConditional.call(loader, name, pkgName + '/'); + }); + + // external map reference + return loader.normalize(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function doMap(loader, pkg, pkgName, mapMatch, path, skipExtensions) { + if (path[path.length - 1] == '/') + path = path.substr(0, path.length - 1); + + var mapped = pkg.map[mapMatch]; + + if (typeof mapped == 'string') { + if (!validMapping(mapMatch, mapped, pkgName, path)) + return Promise.resolve(); + return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions); + } + + // we use a special conditional syntax to allow the builder to handle conditional branch points further + if (loader.builder) + return Promise.resolve(pkgName + '/#:' + path); + + // we load all conditions upfront + var conditionPromises = []; + var conditions = []; + for (var e in mapped) { + var c = parseCondition(e); + conditions.push({ + condition: c, + map: mapped[e] + }); + conditionPromises.push(loader['import'](c.module, pkgName)); + } + + // map object -> conditional map + return Promise.all(conditionPromises) + .then(function(conditionValues) { + // first map condition to match is used + for (var i = 0; i < conditions.length; i++) { + var c = conditions[i].condition; + var value = readMemberExpression(c.prop, conditionValues[i]); + if (!c.negate && value || c.negate && !value) + return conditions[i].map; + } + }) + .then(function(mapped) { + if (mapped) { + if (!validMapping(mapMatch, mapped, pkgName, path)) + return; + return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions); + } + + // no environment match -> fallback to original subPath by returning undefined + }); + } + + // normalizeSync = decanonicalize + package resolution + SystemJSLoader.prototype.normalizeSync = SystemJSLoader.prototype.decanonicalize = SystemJSLoader.prototype.normalize; + + // decanonicalize must JUST handle package defaultExtension: false case when defaultJSExtensions is set + // to be deprecated! + hook('decanonicalize', function(decanonicalize) { + return function(name, parentName) { + if (this.builder) + return decanonicalize.call(this, name, parentName, true); + + var decanonicalized = decanonicalize.call(this, name, parentName, false); + + if (!this.defaultJSExtensions) + return decanonicalized; + + var pkgName = getPackage(this, decanonicalized); + + var pkg = this.packages[pkgName]; + var defaultExtension = pkg && pkg.defaultExtension; + + if (defaultExtension == undefined && pkg && pkg.meta) + getMetaMatches(pkg.meta, decanonicalized.substr(pkgName), function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) { + defaultExtension = false; + return true; + } + }); + + if ((defaultExtension === false || defaultExtension && defaultExtension != '.js') && name.substr(name.length - 3, 3) != '.js' && decanonicalized.substr(decanonicalized.length - 3, 3) == '.js') + decanonicalized = decanonicalized.substr(0, decanonicalized.length - 3); + + return decanonicalized; + }; + }); + + hook('normalizeSync', function(normalizeSync) { + return function(name, parentName, isPlugin) { + var loader = this; + isPlugin = isPlugin === true; + + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name[0] != '.') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch && typeof parentMap[parentMapMatch] == 'string') { + var mapped = doMapSync(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin); + if (mapped) + return mapped; + } + } + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalizeSync.call(loader, name, parentName, false); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return normalized + (defaultJSExtension ? '.js' : ''); + + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfigSync(loader, loader.packages[pkgName] || {}, pkgName, subPath, isPlugin); + }; + }); + + hook('normalize', function(normalize) { + return function(name, parentName, isPlugin) { + var loader = this; + isPlugin = isPlugin === true; + + return Promise.resolve() + .then(function() { + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name.substr(0, 2) != './') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch) + return doMap(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin); + } + + return Promise.resolve(); + }) + .then(function(mapped) { + if (mapped) + return mapped; + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalize.call(loader, name, parentName, false); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return Promise.resolve(normalized + (defaultJSExtension ? '.js' : '')); + + var pkg = loader.packages[pkgName]; + + // if package is already configured or not a dynamic config package, use existing package config + var isConfigured = pkg && (pkg.configured || !pkgConfigMatch); + return (isConfigured ? Promise.resolve(pkg) : loadPackageConfigPath(loader, pkgName, pkgConfigMatch.configPath)) + .then(function(pkg) { + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfig(loader, pkg, pkgName, subPath, isPlugin); + }); + }); + }; + }); + + // check if the given normalized name matches a packageConfigPath + // if so, loads the config + var packageConfigPaths = {}; + + // data object for quick checks against package paths + function createPkgConfigPathObj(path) { + var lastWildcard = path.lastIndexOf('*'); + var length = Math.max(lastWildcard + 1, path.lastIndexOf('/')); + return { + length: length, + regEx: new RegExp('^(' + path.substr(0, length).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^\\/]+') + ')(\\/|$)'), + wildcard: lastWildcard != -1 + }; + } + + // most specific match wins + function getPackageConfigMatch(loader, normalized) { + var pkgName, exactMatch = false, configPath; + for (var i = 0; i < loader.packageConfigPaths.length; i++) { + var packageConfigPath = loader.packageConfigPaths[i]; + var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath)); + if (normalized.length < p.length) + continue; + var match = normalized.match(p.regEx); + if (match && (!pkgName || (!(exactMatch && p.wildcard) && pkgName.length < match[1].length))) { + pkgName = match[1]; + exactMatch = !p.wildcard; + configPath = pkgName + packageConfigPath.substr(p.length); + } + } + + if (!pkgName) + return; + + return { + packageName: pkgName, + configPath: configPath + }; + } + + function loadPackageConfigPath(loader, pkgName, pkgConfigPath) { + var configLoader = loader.pluginLoader || loader; + + // NB remove this when json is default + (configLoader.meta[pkgConfigPath] = configLoader.meta[pkgConfigPath] || {}).format = 'json'; + configLoader.meta[pkgConfigPath].loader = null; + + return configLoader.load(pkgConfigPath) + .then(function() { + var cfg = configLoader.get(pkgConfigPath)['default']; + + // support "systemjs" prefixing + if (cfg.systemjs) + cfg = cfg.systemjs; + + // modules backwards compatibility + if (cfg.modules) { + cfg.meta = cfg.modules; + warn.call(loader, 'Package config file ' + pkgConfigPath + ' is configured with "modules", which is deprecated as it has been renamed to "meta".'); + } + + return setPkgConfig(loader, pkgName, cfg, true); + }); + } + + function getMetaMatches(pkgMeta, subPath, matchFn) { + // wildcard meta + var meta = {}; + var wildcardIndex; + for (var module in pkgMeta) { + // allow meta to start with ./ for flexibility + var dotRel = module.substr(0, 2) == './' ? './' : ''; + if (dotRel) + module = module.substr(2); + + wildcardIndex = module.indexOf('*'); + if (wildcardIndex === -1) + continue; + + if (module.substr(0, wildcardIndex) == subPath.substr(0, wildcardIndex) + && module.substr(wildcardIndex + 1) == subPath.substr(subPath.length - module.length + wildcardIndex + 1)) { + // alow match function to return true for an exit path + if (matchFn(module, pkgMeta[dotRel + module], module.split('/').length)) + return; + } + } + // exact meta + var exactMeta = pkgMeta[subPath] && pkgMeta.hasOwnProperty && pkgMeta.hasOwnProperty(subPath) ? pkgMeta[subPath] : pkgMeta['./' + subPath]; + if (exactMeta) + matchFn(exactMeta, exactMeta, 0); + } + + hook('locate', function(locate) { + return function(load) { + var loader = this; + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + var pkgName = getPackage(loader, load.name); + if (pkgName) { + var pkg = loader.packages[pkgName]; + var subPath = load.name.substr(pkgName.length + 1); + + var meta = {}; + if (pkg.meta) { + var bestDepth = 0; + + // NB support a main shorthand in meta here? + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth > bestDepth) + bestDepth = matchDepth; + extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth); + }); + + extendMeta(load.metadata, meta); + } + + // format + if (pkg.format && !load.metadata.loader) + load.metadata.format = load.metadata.format || pkg.format; + } + + return address; + }); + }; + }); + +})(); +/* + * Script tag fetch + * + * When load.metadata.scriptLoad is true, we load via script tag injection. + */ +(function() { + + if (typeof document != 'undefined') + var head = document.getElementsByTagName('head')[0]; + + var curSystem; + var curRequire; + + // if doing worker executing, this is set to the load record being executed + var workerLoad = null; + + // interactive mode handling method courtesy RequireJS + var ieEvents = head && (function() { + var s = document.createElement('script'); + var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]'; + return s.attachEvent && !(s.attachEvent.toString && s.attachEvent.toString().indexOf('[native code') < 0) && !isOpera; + })(); + + // IE interactive-only part + // we store loading scripts array as { script: